【问题标题】:Remove a pseudo-element when there is only one child element当只有一个子元素时移除一个伪元素
【发布时间】:2018-03-19 15:59:49
【问题描述】:

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

所以为了做到这一点,我需要在这种情况下“删除”伪元素。

如果可能,我该怎么做?

.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. 示例取自 here,但儿童数量减少到 1 个。

附注附: 如果有很多 div - 看起来像这样

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

【问题讨论】:

  • 去掉 width:30% 怎么样?
  • 如果.box只有一个,你想去掉伪元素还是居中?
  • @karthikaruna 移除伪元素
  • 在发布了一个通用解决方案,如果只有一个项目,它应该居中,这意味着当 2 个或更多时,它们将左对齐。我刚刚在下面的评论中注意到您现在还说一个一个地居中。这是否意味着如果有 2 个它们也应该居中而不是左对齐?如果它自己有 1 或 2 个呢?
  • @LGSon 通常,无论一行中有多少项目:1)如果只存在一行,则项目应居中 2)如果存在两行或更多行 - 最后一行项目应保留对齐

标签: html css flexbox css-grid


【解决方案1】:

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

不过最后一个框也可以是第一个框,覆盖这个用法:

   .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>

【讨论】:

【解决方案2】:

试试这个。更新了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

【讨论】:

    【解决方案3】:

    如果父母有一个孩子,如何不显示 ::after 内容?

    没有 CSS 方法(今天,但有一天可能会使用父选择器)来根据弹性项目的数量删除伪,即使它是一个子项目并充当弹性项目,它仍然可以'除了通过其父项之外,不要以任何其他方式明确定位。


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

    也可以使用position: relative; left: 50%,尽管margin-left 少了一行

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

    堆栈sn-p

    .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 个项目,它们也应该居中。

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

    如果有 1 或 2 个元素,则使用一对聪明的 CSS selectors, we can count

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

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

    Fiddle demo

    堆栈sn-p

    .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>

    【讨论】:

      【解决方案4】:

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

      请注意,您需要一个技巧——伪元素——来实现主布局。

      因此,您需要更复杂的 hack(请参阅其他答案)来构建该布局的变体也就不足为奇了。

      Flexbox 旨在通过分配可用空间来实现灵活性。一旦你开始限制这种灵活性(例如,通过引入一个假项目来保持一个位置来强制一个 flex 项目留在列中),flexbox 就会开始中断。

      这里进一步解释了这个概念:Targeting flex items on the last row

      这是 W3C 人员意识到的一个问题/限制,这也是他们推出 CSS Grid Layout 的原因之一,它干净而轻松地解决了这个问题:

      多个项目

      .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

      【讨论】:

        猜你喜欢
        • 2017-01-04
        • 2019-01-12
        • 2015-06-18
        • 1970-01-01
        • 1970-01-01
        • 2012-08-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多