当只有一个 child 元素时删除一个 pseudo-element

Remove a pseudo-element when there is only one child element

我使用了一个不可见的 pseudo-element (::after),它占据了容器中的最后一个槽位。但是如果只有一个元素,我想把它放在中间。

所以为了做到这一点,我需要 "remove" 在这种情况下 pseudo-element。

如果可能,我该怎么做?

.main {
  background: #999;
  margin: 0 auto;
  width: 500px;
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
}
.box {
  background: #7ab9d7;
  color: #555;
  height: 30px;
  width: 30%;
  margin-bottom: 30px;
  text-align: center;
  font-size: 30px;
  padding-top: 120px;
}
.main::after {
  height: 0;
  width: 30%;
  content: "";
}
<div class="main">
  <div class="box">1</div>
</div>

P.S. 示例取自 但将 children 的数量减少到 1.

P.S。 P.S. 如果很多 divs - 看起来像这样

如果一个 div - 看起来像这样

要实现这一点,您首先需要删除 ::after,然后您需要 justify-content: center; 默认情况下,并使用 margin: 0 auto 30px 0;[=17 将每个最后一个框定位到左中心=]

但是最后一个框也可以是第一个框,要覆盖这个使用:

   .box:first-child {
        margin: 0 auto 30px auto !important;
    }

要在每个框内获得额外的填充,您需要添加额外的 div 并单独添加蓝色背景。

.main {
  background: #999;
  margin: 0 auto;
  width: 500px;
  display: flex;
  flex-wrap: wrap;
  /*justify-content: space-between;*/
  justify-content: center;
  align-items: center;

}
.box {
    background: #7ab9d7;
    color: #555;
    height: 30px;
    /* width: 30%; */
    margin-bottom: 30px;
    text-align: center;
    font-size: 30px;
    padding-top: 120px;
    /* flex: auto; */
    /* flex: 1; */
    flex-basis: 33.33%;
}

.box:last-child{
   margin: 0 auto 30px 0;
}

.box:first-child {
    margin: 0 auto 30px auto !important;
}
/*
.main::after {
  height: 0;
  width: 30%;
  content: "";
}
*/
<div class="main">
  <div class="box">1</div>
  <div class="box">2</div>
  <div class="box">3</div>
  <div class="box">4</div>
  <div class="box">5</div>
</div>

试试这个。更新了 fiddle。删除了用作占位符的伪元素。以下是更新后的 CSS.

.main {
  background: #999;
  margin: 0 auto;
  width: 500px;
  display: flex;
  flex-wrap: wrap;
}
.box {
  background: #7ab9d7;
  color: #555;
  height: 30px;
  width: 30%;
  margin-bottom: 30px;
  text-align: center;
  font-size: 30px;
  padding-top: 120px;
}
.box:not(:nth-child(3n)) {
  margin-right: 5%;
}
.box:only-child {
  margin-right: auto;
  margin-left: auto;
}

With multiple .boxes

With single .box

How to not display ::after content if one child in parent?

没有 CSS 方法(今天,但有父选择器可能有一天)根据 flex 项目的数量删除伪,即使它是子项并充当 flex项,它仍然不能通过其父项明确定位。


一个简单的解决方法是在只有 1 个元素时使用左边距和 transform,这里使用 only-child 选择器。

也可以用position: relative; left: 50%,虽然margin-left少了一行

这将适用于任意数量的元素,无论它们的大小如何。

堆栈片段

.main {
  background: #999;
  margin: 0 auto;
  width: 500px;
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
}

.box {
  background: #7ab9d7;
  color: #555;
  height: 30px;
  width: 30%;
  margin-bottom: 30px;
  text-align: center;
  font-size: 30px;
  padding-top: 120px;
}

.main::after {
  height: 0;
  width: 30%;
  content: "";
}

.main div:only-child {                /*  added rule  */
  margin-left: 50%;
  transform: translateX(-50%);
}
<div class="main">
  <div class="box">1</div>
</div>
<br>
<div class="main">
  <div class="box">1</div>
  <div class="box">1</div>
</div>
<br>
<div class="main">
  <div class="box">1</div>
  <div class="box">1</div>
  <div class="box">1</div>
  <div class="box">1</div>
</div>
<br>


根据评论更新,其中,如果有 2 个项目,它们也应该居中。

为了能够使用现有的 markup/CSS 实现这一点,我们还需要利用 ::before 伪。

如果有 1 或 2 个元素,有几个聪明的 CSS selectors, we can count

这样工作,当 1 或 2 个项目时,使用自动边距,并且使用 order 属性 项目位于 ::after 之后,现在是 100 % wide 并将项目推到新行,在那里它们不会受到任何伪造的影响。

对于 3 个或更多项目,它们将位于两个伪项目之前,其中 ::before 现在将充当 ::after 在初始解决方案中所做的,并在最后一行左对齐项目。

Fiddle demo

堆栈片段

.main {
  background: #999;
  margin: 0 auto;
  width: 500px;
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
}

.box {
  background: #7ab9d7;
  color: #555;
  height: 30px;
  width: 30%;
  margin-bottom: 30px;
  text-align: center;
  font-size: 30px;
  padding-top: 120px;
}

.main::before {
  height: 0;
  width: 30%;
  content: "";
  order: 1;
}
.main::after {
  height: 0;
  width: 100%;
  content: "";
  order: 2;
}

/* new rules */

.main div:only-child,                            /* if 1 only */
.main div:first-child:nth-last-child(2) + div {  /* if 2, the 2nd*/
  order: 3;
  margin-left: auto;
  margin-right: auto;
}

.main div:first-child:nth-last-child(2) {         /* if 2, the 1st */
  order: 3;
  margin-left: auto;
}
<div class="main">
  <div class="box">1</div>
</div>
<br>
<div class="main">
  <div class="box">1</div>
  <div class="box">2</div>
</div>
<br>
<div class="main">
  <div class="box">1</div>
  <div class="box">2</div>
  <div class="box">3</div>
  <div class="box">4</div>
</div>
<br>
<div class="main">
  <div class="box">1</div>
  <div class="box">2</div>
  <div class="box">3</div>
  <div class="box">4</div>
  <div class="box">5</div>
</div>

对于使用 flexbox 的这个问题没有简单的解决方案,因为 flexbox 不是为这种布局设计的。

请注意,您需要一个 hack – 伪元素 – 来实现主布局。

因此,您需要更复杂的 hack – 查看其他答案 – 来构建该布局的变体也就不足为奇了。

Flexbox 旨在通过免费分发 space 实现灵活性。一旦你开始限制这种灵活性(例如,通过引入一个假项目来保持一个位置来强制一个弹性项目留在一个列中),flexbox 就会开始崩溃。

这里进一步解释了这个概念:

这是 W3C 人员意识到的一个问题/限制,这也是他们推出 CSS 网格布局 的原因之一,它解决了这个问题干净利落:

多项

.main {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  grid-template-rows: 150px 150px;
  grid-row-gap: 30px;
  grid-column-gap: 3%;
  width: 500px;  
  background: #999;
  margin: 0 auto;
}

.box {
  display: flex;
  align-items: flex-end;
  justify-content: center;
  text-align: center;
  background: #7ab9d7;
  color: #555;
  font-size: 30px;
}

.box:only-child {
  grid-column: 2 / 3;
}
<div class="main">
  <div class="box">1</div>
  <div class="box">2</div>
  <div class="box">3</div>
  <div class="box">4</div>
  <div class="box">5</div>
</div>

单项

.main {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  grid-template-rows: 150px 150px;
  grid-row-gap: 30px;
  grid-column-gap: 3%;
  width: 500px;  
  background: #999;
  margin: 0 auto;
}

.box {
  display: flex;
  align-items: flex-end;
  justify-content: center;
  text-align: center;
  background: #7ab9d7;
  color: #555;
  font-size: 30px;
}

.box:only-child {
  grid-column: 2 / 3;
}
<div class="main">
  <div class="box">1</div>
</div>

jsFiddle demo