将弹性箱放在列表项目内部会导致内容被显示为实线高度推下来。
我一直在使用不同的CSS属性,例如提供flexbox margin-top: 0
,其子margin-top:0
,将flex-wrap
添加到flexbox等等。没有骰子!
.wrapper {
display: flex;
}
li {
background: #ccc;
}

<ul>
<li>
<div class="wrapper">
<div>hello</div>
<div>world</div>
</div>
</li>
</ul>
&#13;
答案 0 :(得分:14)
这似乎是由于::marker
伪元素。
我不确切知道应该发生什么,因为这是各种规格的重叠
list-item
keyword ::marker
pseudo-element 这是有问题的,因为它们是尚未准备好实施的提案。例如,请参阅CSS Lists 3 - Positioning Markers中的警告,该问题与此问题相关:
此部分尚未准备好实施。这是未经审查的 草稿尚未经过适当检查 网络兼容性。随意发送反馈,但不要使用此部分 该规范
以下是我对Chrome如何处理标记的猜测。
首先,让我们在列表项上使用更简单的list-style-position: inside
,并让它包含一个块:
ul {
list-style-position: inside;
}
li {
border: 1px solid blue;
}
div {
border: 1px solid red;
}
<ul>
<li>
<div>Hello<br />world</div>
</li>
</ul>
Chrome会像这样显示:
请注意,标记与div重叠,但缩小其第一个行框。这种行为是浮动的典型行为!
浮点数不应与格式化上下文根重叠。例如,display: inline-block
建立了一个块格式化上下文。
ul {
list-style-position: inside;
}
li {
border: 1px solid blue;
}
div {
display: inline-block;
border: 1px solid red;
}
<ul>
<li>
<div>Hello<br />world</div>
</li>
</ul>
所以像浮标一样,标记将其向右推,以防止重叠。
但请注意标记是垂直对齐的。使用overflow: hidden
建立块格式化上下文不会阻止重叠。
ul {
list-style-position: inside;
}
li {
border: 1px solid blue;
}
div {
overflow: hidden;
border: 1px solid red;
}
<ul>
<li>
<div>Hello<br />world</div>
</li>
</ul>
所以它有一些类似浮动的行为,但它不是浮动的。
我的猜测是Chrome会继续迭代列表项中的第一个框,然后是其中的第一个框,依此类推,直到第一个框不再是一个块。然后它在它之前插入标记,显示内联级别(可能是inline-block
)。像这样:
var deepestFirstBlock,
child = listItem;
do {
deepestFirstBlock = child;
child = deepestFirstBlock.firstBoxChild;
} while (child.style.display == 'block');
deepestFirstBlock.insertBefore(marker, deepestFirstBlock.firstBoxChild);
并非如此,因为如果最深的第一个块的direction
是从右到左,则在第一行的最后一个框之后插入标记。
因此,正如Michael_B所注意到的,当您使用display: inline-flex
设置内部容器样式时,没有空白空间。那是因为标记插在它之前,因为它们都是内联级别的,所以它们并排出现。
ul {
list-style-position: inside;
}
li {
border: 1px solid blue;
}
div {
display: inline-flex;
border: 1px solid red;
}
<ul>
<li>
<div>Hello<br />world</div>
</li>
</ul>
但是display: flex
容器是块级的。所以它被迫转到下一行。然后空的空格就是标记,占据第一个线框。
ul {
list-style-position: inside;
}
li {
border: 1px solid blue;
}
div {
display: flex;
border: 1px solid red;
}
<ul>
<li>
<div>Hello<br />world</div>
</li>
</ul>
display: block
也不会发生这种情况,它也是块级的,因为标记插入其中。我想标记没有插入块级Flex容器中,因为它会成为一个flex项目,它可能会产生一个奇怪的布局。
当您使用初始list-style-position: outside
时,Chrome似乎只对标记应用了某种负水平边距,因此以下框(插入标记之前的第一个框)在左侧对齐插入标记之前的容器也许标记也会浮动,因为列表项中的浮动内容不再能够显示在其左侧。
但是,这个负边距将不允许块级flex容器上升。这就是为什么空间仍然存在,即使标记不再存在。
请注意,这与当前未经审核的粗略草案相矛盾,该草案尚未准备好实施,其中list-style-position: outside
的标记应为position: marker
,
绝对定位的元素被取出并且在元素之后重叠,因此我应该将flex容器移到顶部。
Firefox似乎做了一些更简单的事情。使用list-style-position: inside
,它只是将标记作为列表项的第一个(内联级别)框插入。它不会尝试迭代块以在尽可能最深的水平插入标记。
然而,对于list-style-position: outside
,它可能需要标记流出,就像草稿所说的那样。这就是为什么你没有在Firefox中看到空间的原因。
答案 1 :(得分:8)
如果您将.wrapper
从display: flex
切换为inline-flex
,问题就会得到解决(demo)。
如果您将list-style-type
设置为none
,问题就会得到解决(评论中为@Ricky_Ruiz}(demo)。
Chrome,Edge和IE11存在问题。原始代码在Firefox和Safari中运行良好。
我目前还不确定导致这种行为的原因。
出于某种原因(显然是标记),li
的顶部是禁区。父母不允许孩子进入该区域。
( 更新: another answer已提供详细说明。)
在测试中......
padding
和后代中删除了margin
和ul
。它没有帮助。line-height
和vertical-align
。也没有帮助。通过为所有元素设置相等的高度,可以清楚地看到某些东西迫使Flex容器呈现低于预期的值,并溢出父级。
ul {
padding: 0;
margin: 0;
height: 100px;
border: 1px solid black;
}
li {
padding: 0;
margin: 0;
background: #ccc;
height: 100%;
}
.wrapper {
display: flex;
padding: 0;
margin: 0;
height: 100%;
border: 1px dashed red;
}
&#13;
<ul>
<li>
<div class="wrapper">
<div>hello</div>
<div>world</div>
</div>
</li>
</ul>
&#13;
答案 2 :(得分:1)
将display: block
添加到li
样式属性会解决此问题。默认情况下,用户代理样式会将li
元素设置为list-item
。 flexbox specifications do not account for this,而是仅指定块,内联和内联块元素(以及触发块级弹性项的table-cell元素)的行为。