在 ::before 元素中堆叠两个字符的语义方式?

Semantic way of stacking two characters in a ::before element?

我正在尝试将清单符号添加到 table 单元格的左边缘。到目前为止,这确实有效。但是,当我试图在清单符号顶部堆叠另一个字符时,事情变得很难看。 我找到了几种方法来实现我想要的结果,但其中 none 对我来说特别好。 有没有人有更好的主意,最好是可以专注于语义的主意?

.checklist::before {
  content: "◯ ";
}
.checklistabs::before {
  content: "◯ ";
  position: absolute;
}
.check::before {
  content: " ✘";
  position: absolute;
  font-size: 130%
}
.checked {
  position: absolute;
  font-size: 130%
}
.checklisttext {
  margin-left: 1.5em;
}
<table>
  <tr>
    <td class="checklist">
      perfect as long as nothing needs to be overlaid 
    </td>
  </tr>
  <tr>
    <td>
      <b class="checked">✘</b>
      ◯ Seems to work best, but has explicit bullet symbol as part of the text.
    </td>
  </tr>
  <tr>
    <td>
      <div class="checklistabs" />
      <div class="check" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;If the bullet symbol goes into another absolutely positioned item, we need to make space at the beginning of the text. ::before would have been much more elegant.
    </td>
  </tr>
  <tr>
    <td class="checklist">
      <div class="check" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;why does this introduce a linebreak?

    </td>
  </tr>
  <tr>
    <td class="checklistabs">
      <div class="check" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Saving on divs
    </td>
  </tr>
  <tr>
    <td>
      <div class="checklistabs" />
      <div class="check" />
      <div class="checklisttext">So this works...</div>
    </td>
  </tr>
  <tr>
    <td class="checklist check">
      Looks preferrable from a semantic point of view but does not work - see 
    </td>
  </tr>
</table>

我会将 ◯ 显示为内联元素,然后使用绝对定位将 ✘ 放在它上面。似乎在没有任何不必要的标记的情况下工作。

.checklist:before {
  content: "◯ ";
}
.checklist:after {
  content: " ✘";
  position: absolute;
  left: .6em;
  font-size: 1.3em;
  top: .6em;
}
<table>
  <tr>
    <td class="checklist">
      perfect as long as nothing needs to be overlaid perfect as long as nothing needs to be overlaid perfect as long as nothing needs to be overlaid perfect as long as nothing needs to be overlaid perfect as long as nothing needs to be overlaid 
    </td>
  </tr>
</table>

why does this introduce a linebreak?

因为 .checkdivdisplay: block;,所以它的内容将显示在它自己的行上。将其设置为 display: inline-block; 或将 float: left; 应用于 .checklist:before 元素,这些元素将在同一行上。

如果将 ::before::after 都定位为绝对位置,并向 <td> 元素添加填充,则可以获得您想要的效果。它需要更多 CSS 和一些与您的 font-size 密切相关的值。但是,如果您将 px 值更改为 em,它应该可以很好地扩展。

table {
  width: 350px;
}
 
.checklist {
  padding: 0 0 0 20px;
  position: relative;
}

.checklist::before,
.checked::after {
  position: absolute;
  left: 0;
  top: 0;
  width: 17px;
  text-align: center;
  line-height: 20px;
}

.checklist::before {
  content: "◯ ";
}

.checked::after {
   content: " ✘";
   font-size: 130%;
}
<table>
  <tr>
    <td class="checklist checked">
      A little more CSS and positioning, but will work well if the text linebreaks.
    </td>
  </tr>
</table>