为什么带有内容的 ::before 伪元素在“display: flex"容器中只去掉了前导空格? [英] Why does a ::before pseudoelement with content have only leading spaces stripped in a 'display: flex' container?

查看:17
本文介绍了为什么带有内容的 ::before 伪元素在“display: flex"容器中只去掉了前导空格?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

参见 jsfiddle

请注意,除了伪元素 (::before.content) 外,每个元素的前导和尾随空格都被相当一致地去除,它只修剪了前导空格.为什么是这样?我希望也删除尾随空格

.flexy {显示:inline-flex;}.noname::before {内容:有";}

一个女孩<span class="noname">no name</span>

<br/><div class="flexy">一个女孩<span class="noname"><span>no name</span></span>

<br/><div class="flexy">琼恩·雪诺<跨度>知道 </span><span>什么都没有</span>

解决方案

为了更好地理解这一点,让我们先添加缺失的案例.

.flexy {显示:inline-flex;}.noname::before {内容:有";}.noname-after::after {内容:有";}跨度 {边框:1px 实心;}

一个女孩<span class="noname">no name</span>

<br><div class="flexy">一个女孩<span class="noname"><span>no name</span></span>

<br><div class="flexy">一个女孩<span class="noname-after"><span>no name</span></span>一些文字之后

<br><div class="flexy">一个女孩<span class="noname-after"></span><span>no name</span>一些文字之后

<br><div class="flexy">琼恩·雪诺<跨度>知道 </span><span>什么都没有</span>

我们可以清楚地看到,在 where 使用 before 时缺少前导空格,在使用 after 时缺少尾随空格,如果只使用 after(或before)在span内.

换句话说,我们缺少所有 <span> 元素(使用或不使用伪元素)边缘的空格,这是合乎逻辑的,因为这是空格.来自规范:

<块引用>

随着每一行的布局,

  1. 如果空格 (U+0020) 在一行的开头 'white-space' 设置为 'normal'、'nowrap' 或 'pre-line',它被删除.
  2. 所有制表符 (U+0009) 都呈现为水平移位,将下一个字形的起始边缘与下一个制表位对齐.制表位出现在从块的起始内容边缘以块的字体呈现的空格 (U+0020) 宽度的 8 倍的倍数处.
  3. 如果空格 (U+0020) 在行尾 将white-space"设置为normal"、nowrap"或pre-line",它也被删除.
  4. 如果行尾的空格 (U+0020) 或制表符 (U+0009) 将white-space"设置为pre-wrap",UA 可能会在视觉上折叠它们.

现在你会告诉我我们正在处理 span 元素,我们没有块和新行,但我们在一个 flex 容器中,因此每个元素都会被块化,并且上述规则适用在这里.

<块引用>

弹性项目的显示值被屏蔽ref

值得注意的是,伪元素不是 flex 容器的直接子元素,因此它们仍然是块元素内的行内元素.如果我们将它们更改为块元素(使用 inline-block1 例如)你会看到空格总是会消失:

.flexy {显示:inline-flex;}.noname::before {内容:有";显示:内联块;}.noname-after::after {内容:有";显示:内联块;}跨度 {边框:1px 实心;}

一个女孩<span class="noname">no name</span>

<br><div class="flexy">一个女孩<span class="noname"><span style="display:inline-block;">no name</span></span>

<br><div class="flexy">一个女孩<span class="noname-after"><span>no name</span></span>一些文字之后

<br><div class="flexy">一个女孩<span class="noname-after"></span><span>no name</span>一些文字之后

<br><div class="flexy">琼恩·雪诺<跨度>知道 </span><span>什么都没有</span>


另一个需要注意的重要事项是 flexbox 如何处理空格:

<块引用>

Flex 容器的每个流入子元素都成为一个 Flex 项目,每个连续的子文本序列都被包裹在一个匿名块容器 Flex 项目中.但是,如果整个子文本序列只包含空格(即可能受 white-space 属性影响的字符),它会不呈现(就像如果它的文本节点是 display:none).

现在我们可以清楚地了解正在发生的事情.在我们的 flex 容器中,我们首先通过删除它们之间的所有额外空格来创建 flex 项目.然后每个 flex 项目成为一个块级元素,在里面我们应用空白算法来删除该块内的尾随和前导空格.


如果您想保留尾随和前导空格,可以更改 white-space 属性:

.flexy {显示:inline-flex;}.noname::before {内容:有";}.noname-after::after {内容:有";}跨度 {边框:1px 实心;空白:预;}

一个女孩<span class="noname">no name</span>

<br><div class="flexy">一个女孩<span class="noname"><span>no name</span></span>

<br><div class="flexy">一个女孩<span class="noname-after"><span>no name</span></span>一些文字之后

<br><div class="flexy">一个女孩<span class="noname-after"></span><span>no name</span>一些文字之后

<br><div class="flexy">琼恩·雪诺<跨度>知道 </span><span>什么都没有</span>

这是另一个示例,可以更好地逐步了解正在发生的事情:

span {边框:1px 实心;}div {边框:1px 纯红色;边距:10px 0;}

去掉开头和结尾的空格,保留里面的空格(连续的空格被折叠成只有一个空格)<div><跨度>跨度内的文本</span>没有跨度的文本跨度内的文本</span>

我制作了最后一个 span inline-block 所以它里面的第一个空格被删除了<div><跨度>跨度内的文本</span>没有跨度的文本跨度内的文本</span>

弹性项目之间的空格被删除(我们有 3 个项目,一个在匿名块内)然后每个弹性项目内的第一个和最后一个空格也被删除<div style="display:flex;"><跨度>跨度内的文本</span>没有跨度的文本跨度内的文本</span>

我们改变了空格算法,现在所有的空格都被保留了<div style="display:flex;white-space:pre;"><跨度>跨度内的文本</span>没有跨度的文本跨度内的文本</span>


<块引用>

1:该值使元素生成内联级块容器.行内块的内部格式化为块框,而元素本身被格式化为原子行内级框.

See jsfiddle

Note that both leading and trailing spaces are stripped from each element fairly consistently, except for the pseudo element (::before.content), which only has its leading space trimmed. Why is this? I would expect the trailing space to be removed as well

.flexy {
  display: inline-flex;
}

.noname::before {
  content: ' has ';
}

<div class="flexy">
  A girl
  <span class="noname">no name</span>
</div>
<br/>
<div class="flexy">
  A girl
  <span class="noname"><span>no name</span></span>
</div>
<br/>
<div class="flexy">
  Jon Snow
  <span> knows </span>
  <span>nothing</span>
</div>

解决方案

To better understand this, let's first add the missing cases.

.flexy {
  display: inline-flex;
}

.noname::before {
  content: ' has ';
}

.noname-after::after {
  content: ' has ';
}
span {
  border:1px solid;
}

<div class="flexy">
  A girl <span class="noname">no name</span>
</div>
<br>
<div class="flexy">
  A girl <span class="noname"><span>no name</span></span>
</div>
<br>
<div class="flexy">
  A girl <span class="noname-after"><span>no name</span></span> some text after
</div>
<br>
<div class="flexy">
  A girl <span class="noname-after"></span><span>no name</span> some text after
</div>
<br>
<div class="flexy">
  Jon Snow
  <span> knows </span>
  <span>nothing</span>
</div>

We can clearly see that we are missing the leading space when where are using before and the trailing one when using after and both of them if only after (or before) is inside the span.

In other words, we are missing the spaces at the edges of all the <span> elements (with or without the use of pseudo element) and this is logical because it's the default behavior of white-space. From the specification:

As each line is laid out,

  1. If a space (U+0020) at the beginning of a line has 'white-space' set to 'normal', 'nowrap', or 'pre-line', it is removed.
  2. All tabs (U+0009) are rendered as a horizontal shift that lines up the start edge of the next glyph with the next tab stop. Tab stops occur at points that are multiples of 8 times the width of a space (U+0020) rendered in the block's font from the block's starting content edge.
  3. If a space (U+0020) at the end of a line has 'white-space' set to 'normal', 'nowrap', or 'pre-line', it is also removed.
  4. If spaces (U+0020) or tabs (U+0009) at the end of a line have 'white-space' set to 'pre-wrap', UAs may visually collapse them.

Now you will tell me that we are dealing with span elements and we don't have block and new lines but we are inside a flex container thus each element will get blockified and the above rules applies here.

The display value of a flex item is blockifiedref

Worth to note that the pseudo element aren't direct child of the flex container so they are still inline element inside block element .If we change them to block element (using inline-block1 for example) you will see that the spaces will always disappear:

.flexy {
  display: inline-flex;
}

.noname::before {
  content: ' has ';
  display:inline-block;
}

.noname-after::after {
  content: ' has ';
  display:inline-block;
}
span {
  border:1px solid;
}

<div class="flexy">
  A girl <span class="noname">no name</span>
</div>
<br>
<div class="flexy">
  A girl <span class="noname"><span style="display:inline-block;">no name</span></span>
</div>
<br>
<div class="flexy">
  A girl <span class="noname-after"><span>no name</span></span> some text after
</div>
<br>
<div class="flexy">
  A girl <span class="noname-after"></span><span>no name</span> some text after
</div>
<br>
<div class="flexy">
  Jon Snow
  <span> knows </span>
  <span>nothing</span>
</div>


Another important thing to note is how flexbox handle spaces:

Each in-flow child of a flex container becomes a flex item, and each contiguous sequence of child text runs is wrapped in an anonymous block container flex item. However, if the entire sequence of child text runs contains only white space (i.e. characters that can be affected by the white-space property) it is instead not rendered (just as if its text nodes were display:none).

Now we can clearly understand what is happening. Inside our flex container we first create the flex items by removing all the extra spaces between them. Then each flex item become a block level element and inside we apply the white space algorithm that removes the trailing and leading spaces inside that block.


You can change the white-space property if you want to keep the trailing and leading spaces:

.flexy {
  display: inline-flex;
}

.noname::before {
  content: ' has ';
}

.noname-after::after {
  content: ' has ';
}
span {
  border:1px solid;
  white-space:pre;
}

<div class="flexy">
  A girl <span class="noname">no name</span>
</div>
<br>
<div class="flexy">
  A girl <span class="noname"><span>no name</span></span>
</div>
<br>
<div class="flexy">
  A girl <span class="noname-after"><span>no name</span></span> some text after
</div>
<br>
<div class="flexy">
  A girl <span class="noname-after"></span><span>no name</span> some text after
</div>
<br>
<div class="flexy">
  Jon Snow
  <span> knows </span>
  <span>nothing</span>
</div>

Here is another example to better understand what is happening step by step:

span {
  border:1px solid;
}
div {
  border:1px solid red;
  margin:10px 0;
}

Spaces are removed from the start and the end, spaces inside are kept (contiguous spaces are collapsed to only one space)
<div>
<span> text inside span </span>   text without span<span> text inside span </span>
</div>
I made the last span inline-block so its first space inside is removed
<div>
<span> text inside span </span>   text without span<span style="display:inline-block"> text inside span </span>
</div>
Spaces between flex items are removed (We have 3 items and one inside an anonymous block) then first and last space inside each flex items are also removed
<div style="display:flex;">
<span> text inside span </span>   text without span<span> text inside span </span>
</div>
We change the white space algorithm and now all the spaces are kept
<div style="display:flex;white-space:pre;">
<span> text inside span </span>   text without span<span> text inside span </span>
</div>

1: This value causes an element to generate an inline-level block container. The inside of an inline-block is formatted as a block box, and the element itself is formatted as an atomic inline-level box.

这篇关于为什么带有内容的 ::before 伪元素在“display: flex"容器中只去掉了前导空格?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
前端开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆