内容列表项中的Flexbox不会与列表项的顶部对齐

时间:2016-11-03 23:37:28

标签: html css css3 flexbox

将弹性箱放在列表项目内部会导致内容被显示为实线高度推下来。

我一直在使用不同的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;
&#13;
&#13;

codepen

3 个答案:

答案 0 :(得分:14)

这似乎是由于::marker伪元素。

我不确切知道应该发生什么,因为这是各种规格的重叠

这是有问题的,因为它们是尚未准备好实施的提案。例如,请参阅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会像这样显示:

enter image description here

请注意,标记与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>

enter image description here

所以像浮标一样,标记将其向右推,以防止重叠。

但请注意标记是垂直对齐的。使用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>

enter image description here

但是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>

enter image description here

display: block也不会发生这种情况,它也是块级的,因为标记插入其中。我想标记没有插入块级Flex容器中,因为它会成为一个flex项目,它可能会产生一个奇怪的布局。

当您使用初始list-style-position: outside时,Chrome似乎只对标记应用了某种负水平边距,因此以下框(插入标记之前的第一个框)在左侧对齐插入标记之前的容器也许标记也会浮动,因为列表项中的浮动内容不再能够显示在其左侧。

但是,这个负边距将不允许块级flex容器上升。这就是为什么空间仍然存在,即使标记不再存在。

请注意,这与当前未经审核的粗略草案相矛盾,该草案尚未准备好实施,其中list-style-position: outside的标记应为position: marker

  

position: marker的元素计为absolutely positioned

绝对定位的元素被取出并且在元素之后重叠,因此我应该将flex容器移到顶部。

Firefox似乎做了一些更简单的事情。使用list-style-position: inside,它只是将标记作为列表项的第一个(内联级别)框插入。它不会尝试迭代块以在尽可能最深的水平插入标记。

然而,对于list-style-position: outside,它可能需要标记流出,就像草稿所说的那样。这就是为什么你没有在Firefox中看到空间的原因。

答案 1 :(得分:8)

解决方案

如果您将.wrapperdisplay: flex切换为inline-flex,问题就会得到解决(demo)。

如果您将list-style-type设置为none,问题就会得到解决(评论中为@Ricky_Ruiz}(demo)。

浏览器行为

Chrome,Edge和IE11存在问题。原始代码在Firefox和Safari中运行良好。

说明

我目前还不确定导致这种行为的原因。

出于某种原因(显然是标记),li的顶部是禁区。父母不允许孩子进入该区域。

更新: another answer已提供详细说明。

在测试中......

  • 我从padding和后代中删除了marginul。它没有帮助。
  • 我玩过line-heightvertical-align。也没有帮助。

通过为所有元素设置相等的高度,可以清楚地看到某些东西迫使Flex容器呈现低于预期的值,并溢出父级。

&#13;
&#13;
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;
&#13;
&#13;

revised codepen

答案 2 :(得分:1)

display: block添加到li样式属性会解决此问题。默认情况下,用户代理样式会将li元素设置为list-itemflexbox specifications do not account for this,而是仅指定块,内联和内联块元素(以及触发块级弹性项的table-cell元素)的行为。