当只有一个子元素时删除伪元素

时间:2017-10-08 09:28:49

标签: html css css3 flexbox css-grid

我使用一个不可见的伪元素(::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人。

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

enter image description here

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

enter image description here

4 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:1)

  

如果父母中有一个孩子,如何在内容后显示::

没有CSS方式(今天,但有一天可能有父选择器)根据弹性项目的数量删除伪,即使它是一个子项并充当弹性项目,它仍然可以&# 39;除了通过其父母之外,其他任何事物都是明确的目标。

一个简单的解决方法是在只有1个元素的情况下使用左边距和transform,此处使用only-child选择器。

也可以使用position: relative; left: 50%,但margin-left只需一行

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

Stack snippet

&#13;
&#13;
.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%);
}
&#13;
<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>
&#13;
&#13;
&#13;

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

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

如果有1个或2个元素,可以使用两个聪明的CSS selectors, we can count

这样的工作,当使用1或2项,自动保证金时,order属性项目位于::after之后,现在是100%宽,并将推动项目到新行,并且它们不会受到伪的影响。

对于3个或更多项目,它们将定位在伪两个项目之前,其中::before现在将作为初始解决方案中的::after,并在最后一个项目上保留对齐项目行。

Fiddle demo

Stack snippet

&#13;
&#13;
.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;
}
&#13;
<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>
&#13;
&#13;
&#13;

答案 2 :(得分:1)

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

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

因此,您需要更复杂的黑客 - 查看其他答案 - 构建该布局的变体并不奇怪。

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

此概念在此处进一步说明:Targeting flex items on the last row

这是W3C的人都知道的问题/限制,这是他们推出 CSS网格布局的一个原因,它可以干净利落地解决这个问题:

多项

&#13;
&#13;
.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;
}
&#13;
<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>
&#13;
&#13;
&#13;

单项

&#13;
&#13;
.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;
}
&#13;
<div class="main">
  <div class="box">1</div>
</div>
&#13;
&#13;
&#13;

jsFiddle demo

答案 3 :(得分:0)

要实现此目的,首先需要移除char,然后默认情况下需要::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: "";
}
*/