使用CSS,如何在每个奇数子元素之前添加一个伪元素,该子元素位于该子元素的“外部”?

时间:2016-01-01 20:30:40

标签: css

我想创建一个两列宽度相等的网格。我的基本HTML代码如下所示:

<div class="linkgrid">
  <div class="gridentry">
    <a href="#">Loooooooooooooong</a>
  </div>
  <div class="gridentry">
    <a href="#">Short</a>
  </div>
  <div class="gridentry">
    <a href="#">Meeeedium</a>
  </div>
</div>

在此示例中,第一个和第二个gridentry应位于第一行。第三行gridentry应该位于第二行。所有gridentry都应具有相同的宽度。

~~~

我想出了一个使用CSS表的解决方案。但是,为了确保每隔一个单元格后行“中断”,它当前需要非语义元素来强制这些“行中断”:

.linkgrid {
  display: table;
  border-spacing: 2px;
  table-layout: fixed;
  width: 50%;
}

.gridentry {
  display: table-cell;
  background-color: red;
  padding: 5px;
  text-align: center;
}

.gridentry a {
  color: white;
}

.THIS-SHOULD-BE-A-PSEUDO-ELEMENT-BEFORE-EVERY-ODD-CHILD {
/* I imagine a selector that looks somewhat like this:
.linkgrid .gridentry:nth-child(odd):outsidebefore {
*/
  display: table-row;
}
<div class="linkgrid">
  <span class="THIS-SHOULD-BE-A-PSEUDO-ELEMENT-BEFORE-EVERY-ODD-CHILD"></span>
  <div class="gridentry">
    <a href="#">Loooooooooooooong</a>
  </div>
  <div class="gridentry">
    <a href="#">Short</a>
  </div>
  <span class="THIS-SHOULD-BE-A-PSEUDO-ELEMENT-BEFORE-EVERY-ODD-CHILD"></span>
  <div class="gridentry">
    <a href="#">Meeeedium</a>
  </div>
</div>

有没有办法从我的HTML中删除<span>(因为它们没有任何语义)并使用一个聪明的CSS选择器,将它们作为伪元素添加到正确的位置?

我知道:before将在所选元素中“创建”中的伪元素。是否有一种非JavaScript,仅CSS的方法来添加所选元素的伪元素 ,如本示例所示?

其他编辑:对于所有熟悉Chrome开发者工具的人,我希望我的结果在DOM树中看起来像这样:

<div class="linkgrid">
  ::outsidebefore
  <div class="gridentry">
    <a href="#">Loooooooooooooong</a>
  </div>
  <div class="gridentry">
    <a href="#">Short</a>
  </div>
  ::outsidebefore
  <div class="gridentry">
    <a href="#">Meeeedium</a>
  </div>
</div>

... ::outsidebefore伪元素应该具有CSS属性display: table-row;

更新2016-01-04:虽然这个具体问题仍未得到解决,但我的原始问题又解决了:https://stackoverflow.com/a/34588007/1560865

因此,请仅回复此问题的答案,以准确回答给定的问题。

2 个答案:

答案 0 :(得分:1)

展示级别3介绍了display: contents

  

元素本身不生成任何框,但它的子元素和   伪元素仍然正常生成框。出于...的目的   框生成和布局,必须将元素视为具有   已被文档中的子元素和伪元素替换   树。

然后,你可以:

  1. 将每个单元格包装在容器元素中
  2. display: contents设置为这些容器
  3. ::before::after个伪元素添加到这些容器
  4. 结果看起来好像伪元素被添加到单元格中,但在它之外。

    .wrapper {
      display: contents;
    }
    .wrapper:nth-child(odd)::before {
      content: '';
      display: table-row;
    }
    

    &#13;
    &#13;
    .linkgrid {
      display: table;
      border-spacing: 2px;
      table-layout: fixed;
      width: 50%;
    }
    .wrapper {
      display: contents;
    }
    .wrapper:nth-child(odd)::before {
      content: '';
      display: table-row;
    }
    .gridentry {
      display: table-cell;
      background-color: red;
      padding: 5px;
      text-align: center;
    }
    .gridentry a {
      color: white;
    }
    &#13;
    <div class="linkgrid">
      <div class="wrapper">
        <div class="gridentry">
          <a href="#">Loooooooooooooong</a>
        </div>
      </div>
      <div class="wrapper">
        <div class="gridentry">
          <a href="#">Short</a>
        </div>
      </div>
      <div class="wrapper">
        <div class="gridentry">
          <a href="#">Meeeedium</a>
        </div>
      </div>
    </div>
    &#13;
    &#13;
    &#13;

    注意display: contents尚未得到广泛支持,但适用于Firefox。

答案 1 :(得分:0)

最直接的方法是使用实​​际的表结构。也就是说,一个表分为行,其中条目位于其中 此外,您在桌面上有width:50%,但我从问题文本中相信您的每个表格单元格宽度为50%,而不是占用窗口宽度的50%;所以我纠正了这一点。

.linkgrid {
  display: table;
  border-spacing: 2px;
}
.gridrow {                     /* new */
  display: table-row;
}
.gridentry {
  display: table-cell;
  background-color: red;
  padding: 5px;
  text-align: center;
  width: 50%;                  /* moved */
}
.gridentry a {
  color: white;
}
<div class="linkgrid">
  <div class="gridrow">
    <div class="gridentry">
      <a href="#">Loooooooooooooong</a>
    </div>
    <div class="gridentry">
      <a href="#">Short</a>
    </div>
  </div>

  <div class="gridrow">
    <div class="gridentry">
      <a href="#">Meeeedium</a>
    </div>
  </div>
</div>