简体   繁体   English

如何在 html/css 有序列表中使用列表项的块子元素使项目编号具有自适应性?

[英]How to make item number's with adaptive in html/css ordered list with block children element of list item?

Targets目标

  1. Make ordered list as custom as :before pseudo element styling allowed (AFAIK arbitrary shape is impossible).使有序列表自定义为:before允许伪元素样式(AFAIK 任意形状是不可能的)。
  2. The spacing between container content edge (even with border when left padding is 0 ) and item number (designated as l ) also between number and item (designated as m ) must be adjustable.容器内容边缘(即使左侧填充为0时有边框)和项目编号(指定为l )之间的间距也必须是可调整的,编号和项目(指定为m )。
  3. The item number with must be adaptive due to increasing digits count.由于位数增加,项目编号必须是自适应的。

在此处输入图像描述

  1. li could has children block elements as div , p , figure , etc. li可以有子块元素,如divpfigure等。

在此处输入图像描述

Problem问题

Below solution without positioning satisfies to first three requirements.以下没有定位的解决方案满足前三个要求。

ol {
  counter-reset: section;
}
ol li:before {
  content: "";
  display: inline-block;
  counter-increment: section;
  content: counters(section, ".") " ";
  margin-left: 4px;
  margin-right: 10px;
  padding: 4px 6px;
  background: lightblue;
  border: 1px solid skyblue;
  border-radius: 4px;
}
ol + li {
  margin-top: 6px;
}

Fiddle小提琴

在此处输入图像描述

But what about fourth requirement?但是第四个要求呢? Let's try to add child elements to li :让我们尝试将子元素添加到li

<ol>
  <li>Alpha</li>
  <li>
    <ol>
      <li>
        <p>Lorem ipsum</p>
        <p>Duis aute</p>
      </li>
    </ol>
  </li>
</ol>

在此处输入图像描述

Conceptually, :before pseudo element must take the one column (space below it must be empty until next li ).从概念上讲, :before伪元素必须占据一列(它下面的空间必须是空的,直到下一个li )。 Currently, I know just one solution: positioning.目前,我只知道一种解决方案:定位。

ol {
  counter-reset: section;
}
ol li {
  position: relative;
}
ol li:before {
  position: absolute;
  left: 0;
  counter-increment: section;
  content: counters(section, ".") " ";
  display: inline-block;
  padding: 4px 6px;
  background: lightblue;
  border: 1px solid skyblue;
  border-radius: 4px;
}
ol li + li {
  margin-top: 12px;
}
ol li > li {
  padding-left: 30px;
}
ol li > li > ol > li {
  padding-left: 44px;
}

Fillde菲尔德

In addition to ugliness, this solution reaches just first and fourth target:除了丑陋之外,这个解决方案只达到了第一个和第四个目标:

  • Second target We can not control neither l not m anymore: we can control just total spacing l + m + o .第二个目标我们不能再控制lm了:我们只能控制总间距l + m + o
  • Third target No adaptivity: the l + m + o is actual only for initial digits count.第三个目标没有适应性: l + m + o仅适用于初始数字计数。

For the fouth target, vertical spacing adjusting is required, but it no too hard.对于第四个目标,需要进行垂直间距调整,但并不难。

Could you suggest some alternative solutions?您能否提出一些替代解决方案? Does CSS flexibility ends here? CSS 灵活性到此结束了吗?

Here is an idea using CSS grid where I will tweak your initial code a little:这是一个使用 CSS 网格的想法,我将在其中稍微调整您的初始代码:

 ol { counter-reset: section; list-style:none; margin:0; padding:0; } ol li { display:grid; /* added this */ grid-template-columns:auto 1fr; /* auto for the bullet and 1fr for the content*/ align-items:baseline; /* keep all the text aligned */ } ol li:before { content: ""; /* make sure the bullet span many rows os it's kept on the first column and the content will placed on the second column */ grid-row:span 1000; counter-increment: section; content: counters(section, ".") " "; margin-left: 4px; margin-bottom:3px; margin-right: 10px; padding: 4px 6px; background: lightblue; border: 1px solid skyblue; border-radius: 4px; } ol + li { margin-top: 6px; }
 <ol> <li>Alpha</li> <li> <ol> <p>Something</p> <li> <p>Lorem ipsum</p> <p>Duis aute</p> </li> </ol> </li> <li>Charlie</li> <li>Delta</li> <li>Echo</li> <li>Foxtrotg</li> <li>Golf</li> <li>Hotel</li> <li>India</li> <li>Juliet</li> </ol>

Or like below:或者像下面这样:

 ol { counter-reset: section; list-style:none; margin:0; padding:0; } ol li { display:grid; /* added this */ grid-template-columns:auto 1fr; /* auto for the bullet and 1fr for the content*/ align-items:baseline; /* keep all the text aligned */ } ol li > * { grid-column:2; /* all the content in the second column and keep only the bullet in the first*/ } ol li:before { content: ""; counter-increment: section; content: counters(section, ".") " "; margin-left: 4px; margin-bottom:3px; margin-right: 10px; padding: 4px 6px; background: lightblue; border: 1px solid skyblue; border-radius: 4px; } ol + li { margin-top: 6px; }
 <ol> <li>Alpha</li> <li> <ol> <p>Something</p> <li> <p>Lorem ipsum</p> <p>Duis aute</p> </li> </ol> </li> <li>Charlie</li> <li>Delta</li> <li>Echo</li> <li>Foxtrotg</li> <li>Golf</li> <li>Hotel</li> <li>India</li> <li>Juliet</li> </ol>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM