【问题标题】:Why does flexbox affect its containing list-item's marker?为什么 flexbox 会影响其包含列表项的标记?
【发布时间】:2019-02-01 07:37:06
【问题描述】:

在知道a list-item element cannot be display: flex at the same time之后,我用一个容器包装了我的内容,然后将容器放入<li />中。

对于有内容的元素来说一切都是正确的。 但是,如果容器中的第一个元素没有子节点,则<li /> 的标记意外地位于底部。

虽然就我而言,我可以简单地添加一个display: none 来解决问题,但我仍然感到困惑: flexbox 中的内容如何影响其祖父节点?

示例:(标记1.位于<li />的右下角)

.flex { display: flex; }
<ol style="width: 15em">
    <li>
        <div class="flex">
            <div></div>
          <div>When an element without content is preceding, the ::marker of the list-item is located at the bottom.</div>
        </div>
    </li>
    <li>
        <div class="flex">
            <div>TITLE</div>
            <div>If there's content in the first element, then it goes as expected.</div>
        </div>
    </li>
    <li>
        <div class="flex">
            <div>It's also fine if there's only one child here.</div>
        </div>
    </li>
</ol>

相关问题: CSS伪元素::marker在流行的浏览器中没有实现,只有Firefox支持@counter-style。现在建议在&lt;ol /&gt; 中实现用户定义的标记? (我看到有人使用::before 这样做,以使用户不要复制标记的文本。但我不知道它是否好。)

【问题讨论】:

  • 如果您删除原生 HTML 列表样式 list-style: none 并使用伪元素和 css 计数器添加您自己的样式,您将获得更多控制
  • 使用 ::before 是一种可怕的 hack,它带有各种各样的陷阱,试图假装某物是一个标记,而实际上它不是,但这是我们多年来所拥有的一切,并将继续只要 ::marker 仍未实现,就一直坚持下去。换句话说,“它和它会得到的一样好”。

标签: css flexbox listitem


【解决方案1】:

我不确定你想在元素内使用 flexbox 来完成什么,但是 display flex 内的一个空元素会塌陷,所以它会奇怪地影响事情。您可以通过使用 flex: numberflex-basis: 50px 为元素指定“大小”来解决此问题

我会避免使用 ::marker 属性,因为它有 horrific support 并且只需使用 css 计数器创建您自己的属性。

这是一个例子:

ol {
  display:block;
  width: 30em;
  list-style: none;
  counter-reset: counterName;
}
li {
 padding-left: 2em;
 padding-bottom: 1em;
 border-bottom: 1px solid #ccc;
 margin-bottom: 1em;
 position: relative;
 counter-increment: counterName;
}
li:before {
  content:'#' counter(counterName);
  position: absolute;
  left:0;
  top:0;
}

.flex {
  display:flex;
  justify-content: space-between;
  flex-wrap:no-wrap;
}

.flex > * {
  flex: 1;
}
<ol>
    <li>
        <div class="flex">
            <div></div>
          <div>When an element without content is preceding, the ::marker of the list-item is located at the bottom.</div>
        </div>
    </li>
    <li>
        <div class="flex">
            <div>TITLE</div>
            <div>If there's content in the first element, then it goes as expected.</div>
        </div>
    </li>
    <li>
        <div class="flex">
            <div>It's also fine if there's only one child here.</div>
        </div>
    </li>
</ol>

【讨论】:

    【解决方案2】:

    要解决这个问题,只需将对齐调整为基线:(最后的另一种解决方案)

    .flex {
      display: flex;
      align-items:baseline;
    }
    <ol style="width: 15em">
      <li>
        <div class="flex">
          <div></div>
          <div>When an element without content is preceding, the ::marker of the list-item is located at the bottom.</div>
        </div>
      </li>
      <li>
        <div class="flex">
          <div>TITLE</div>
          <div>If there's content in the first element, then it goes as expected.</div>
        </div>
      </li>
      <li>
        <div class="flex">
          <div>It's also fine if there's only one child here.</div>
        </div>
      </li>
    </ol>

    为了更好地理解正在发生的事情(根据我自己的解释),让我们为空元素添加一些宽度和背景:

    .flex {
      display: flex;
    }
    div:empty {
      width:30px;
      background:red;
    }
    <ol style="width: 15em">
      <li>
        <div class="flex">
          <div></div>
          <div>When an element without content is preceding, the ::marker of the list-item is located at the bottom.</div>
        </div>
      </li>
      <li>
        <div class="flex">
          <div>TITLE</div>
          <div>If there's content in the first element, then it goes as expected.</div>
        </div>
      </li>
      <li>
        <div class="flex">
          <div>It's also fine if there's only one child here.</div>
        </div>
      </li>
    </ol>

    由于默认对齐方式,空元素被拉伸,然后编号与其底部对齐。

    如果你增加/减少高度,你会更好地注意到这一点

    .flex {
      display: flex;
    }
    div:empty {
      width:30px;
      background:red;
      animation:change 5s linear infinite alternate;
    }
    @keyframes change {
       from {
         height:5px;
       }
       to  {
         height:80px;
       }
    }
    <ol style="width: 15em">
      <li>
        <div class="flex">
          <div></div>
          <div>When an element without content is preceding, the ::marker of the list-item is located at the bottom.</div>
        </div>
      </li>
      <li>
        <div class="flex">
          <div>TITLE</div>
          <div>If there's content in the first element, then it goes as expected.</div>
        </div>
      </li>
      <li>
        <div class="flex">
          <div>It's also fine if there's only one child here.</div>
        </div>
      </li>
    </ol>

    如果您将第一个弹性项目内的inline-block 元素设置为overlow:hidden(使其基线成为底部边框),也会发生这种情况

    .flex {
      display: flex;
    }
    div:empty {
      width:30px;
      background:red;
    }
    .inline-block {
      display:inline-block;
      height:50px;
      background:green;
      width:50px;
      overflow:hidden;
    }
    <ol style="width: 15em">
      <li>
        <div class="flex">
          <div></div>
          <div>When an element without content is preceding, the ::marker of the list-item is located at the bottom.</div>
        </div>
      </li>
      <li>
        <div class="flex">
          <div><div class="inline-block">some text </div></div>
          <div>TITLE</div>
        </div>
      </li>
      <li>
        <div class="flex">
          <div>It's also fine if there's only one child here.</div>
        </div>
      </li>
    </ol>

    基本上,计数试图与第一项的基线对齐。如果增加第一项的font-size,我们也可以注意到这一点:

    .flex {
      display: flex;
    }
    .size {
      animation:change 5s linear infinite alternate;
    }
    @keyframes change {
       from {
         font-size:5px;
       }
       to  {
         font-size:30px;
       }
    }
    <ol style="width: 15em">
      <li>
        <div class="flex">
          <div></div>
          <div>When an element without content is preceding, the ::marker of the list-item is located at the bottom.</div>
        </div>
      </li>
      <li>
        <div class="flex">
          <div class="size">TITLE</div>
          <div>If there's content in the first element, then it goes as expected.</div>
        </div>
      </li>
      <li>
        <div class="flex">
          <div>It's also fine if there's only one child here.</div>
        </div>
      </li>
    </ol>

    正如您已经注意到的那样,只有在涉及第一项时才会发生这种情况,这使得这有点复杂且不容易解释:

    .flex {
      display: flex;
    }
    div:empty {
      width:30px;
      background:red;
    }
    .inline-block {
      display:inline-block;
      height:50px;
      background:green;
      width:50px;
      overflow:hidden;
    }
    <ol style="width: 15em">
      <li>
        <div class="flex">
          <div>When an element without content is preceding, the ::marker of the list-item is located at the bottom.</div>
          <div></div>
        </div>
      </li>
      <li>
        <div class="flex">
          <div>TITLE</div>
          <div><div class="inline-block">some text </div></div>
        </div>
      </li>
      <li>
        <div class="flex">
          <div>It's also fine if there's only one child here.</div>
        </div>
      </li>
    </ol>

    除了改变对齐方式之外,另一个解决方法是在 flexbox 容器中考虑一个伪元素,这将是我们的第一个 flex 项,因此我们避免与我们的 真实 元素进行任何交互。

    诀窍是不要让该元素为空,但至少要有一个内容。我使用了零宽度空格字符\200B:

    .flex {
      display: flex;
    }
    .flex:before {
      content:"\200B"; /*a non collapsible white space*/ 
    }
    div:empty {
      width:30px;
      background:red;
      animation:change 5s linear infinite alternate;
    }
    @keyframes change {
       from {
         height:5px;
       }
       to  {
         height:80px;
       }
    }
    .size {
      color:green;
      animation:size 5s linear infinite alternate;
    }
    @keyframes size {
       from {
         font-size:5px;
       }
       to  {
         font-size:20px;
       }
    }
    <ol style="width: 15em">
      <li>
        <div class="flex">
          <div></div>
          <div>When an element without content is preceding, the ::marker of the list-item is located at the bottom.</div>
        </div>
      </li>
      <li>
        <div class="flex">
          <div class="size">TITLE</div>
          <div>If there's content in the first element, then it goes as expected.</div>
        </div>
      </li>
      <li>
        <div class="flex">
          <div>It's also fine if there's only one child here.</div>
        </div>
      </li>
    </ol>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-03-10
      • 1970-01-01
      • 2021-06-06
      • 2011-12-20
      • 1970-01-01
      • 2013-04-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多