首页 > 解决方案 > 使用 flexbox 和 hack 之前的嵌套网格布局

问题描述

有人可以解释这个例子是如何工作的吗?

  1. 为什么在.content::before那里使用?
  2. 为什么如果我取消注释第 19 行 ( /* align-items: center; */) 就全部中断了?

PS:codepen的相同代码

* {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
}

*::before, *::after {
  box-sizing: border-box;
}

html, body {
  width: 100%;
  height: 100%;
  font: 1rem/1.5 sans-serif;
}

.container {
  display: flex;
/*  align-items: center; */
  justify-content: center;
  height: 100%;
  max-width: 960px;
  margin: auto;
}

.content {
  display: flex;
	flex-flow: column wrap;	
	align-content: space-between;
  position: relative;
  background-color: gold;
}

.content::before, .content::after {
  content: '';
  flex-basis: 100%;
  width: 0;
  order: 2;
  position: relative;
}

.content::after {
  display: none;
}

.content > * {
  flex-grow: 1;
  flex-shrink: 1;
  min-height: 0.0033rem;
}

.a {
  width: calc(100% / 3 * 2 + 0.0033rem);
  order: 1;
}

.b {
  width: calc(100%  / 3 * 1 + 0.0033rem);
  order: 2;
}

.c {
  width:  calc(100% / 3  * 1 + 0.0033rem); 
  order: 2;
}

.a { background: red;  }
.b { background: green;  }
.c { background: blue; }

.a, .b, .c {
  padding: 1rem;
  min-height: 120px;
}
<div class="container">
  <div class="content">
    <div class="a">Lorem ipsum dolor sit amet consectetur adipisicing elit. </div>
    <div class="b">Lorem ipsum dolor sit amet consectetur adipisicing elit.</div>
    <div class="c">Lorem ipsum dolor sit amet consectetur adipisicing elit. </div>
  </div>
</div>

标签: htmlcssflexbox

解决方案


::before伪元素

应用于弹性容器的伪元素被认为是弹性项目(MDN)。

因此,该::before元素是.contentflex 容器中的一个 flex 项。如果::afterpseudo 未设置为display: none,它也将是 的弹性项目.content

简而言之,.contentflex 容器有四个项目,并且伪设置为order: 2. 所以元素的顺序如下:

<div class="content">
    <div class="a">Lorem ipsum dolor sit amet consectetur adipisicing elit.</div>
    <css pseudo element></css pseudo element>
    <div class="b">Lorem ipsum dolor sit amet consectetur adipisicing elit.</div>
    <div class="c">Lorem ipsum dolor sit amet consectetur adipisicing elit.</div>
</div>

伪设置为flex-basis: 100%

.content::before {
  content: '';
  flex-basis: 100%;
  width: 0;
  order: 2;
  position: relative;
}

在列方向容器(即.content)中,这等价于height: 100%

由于容器也设置为wrap,带有 的项目height: 100%占据一整列并将后续项目强制到新列。

.container {
  display: flex;
  /* align-items: center; */
  justify-content: center;
  height: 100%;
  max-width: 960px;
  margin: auto;
}

.content {
  display: flex;
  flex-flow: column wrap;
  align-content: space-between;
  position: relative;
  background-color: gold;
}

.content::before,
.content::after {
  content: '';
  flex-basis: 100%;
  width: 0;
  order: 2;
  position: relative;
}

.content::after {
  display: none;
}

.content>* {
  flex-grow: 1;
  flex-shrink: 1;
  min-height: 0.0033rem;
}

.a {
  width: calc(100% / 3 * 2 + 0.0033rem);
  order: 1;
}

.b {
  width: calc(100% / 3 * 1 + 0.0033rem);
  order: 2;
}

.c {
  width: calc(100% / 3 * 1 + 0.0033rem);
  order: 2;
}

.a {
  background: red;
}

.b {
  background: green;
}

.c {
  background: blue;
}

.a,
.b,
.c {
  padding: 1rem;
  min-height: 120px;
}

* {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
}

*::before,
*::after {
  box-sizing: border-box;
}

html,
body {
  width: 100%;
  height: 100%;
  font: 1rem/1.5 sans-serif;
}
<div class="container">
  <div class="content">
    <div class="a">Lorem ipsum dolor sit amet consectetur adipisicing elit. </div>
    <div class="b">Lorem ipsum dolor sit amet consectetur adipisicing elit.</div>
    <div class="c">Lorem ipsum dolor sit amet consectetur adipisicing elit. </div>
  </div>
</div>

DOM 元素设置为min-height: 120px...

.a, .b, .c {
  min-height: 120px;
}

...但是它们消耗了容器中的所有高度,因为它们也设置为flex-grow: 1

.content > * {
  flex-grow: 1;
}

伪列是完全不可见的,因为它设置为width: 0

如果,假设您添加了宽度或内容,则由伪创建的列将变得可见:

.container {
  display: flex;
  /* align-items: center; */
  justify-content: center;
  height: 100%;
  max-width: 960px;
  margin: auto;
}

.content {
  display: flex;
  flex-flow: column wrap;
  align-content: space-between;
  position: relative;
  background-color: gold;
}

.content::before,
.content::after {
  content: 'X';
  flex-basis: 100%;
  /* width: 0; */
  order: 2;
  position: relative;
}

.content::after {
  display: none;
}

.content>* {
  flex-grow: 1;
  flex-shrink: 1;
  min-height: 0.0033rem;
}

.a {
  width: calc(100% / 3 * 2 + 0.0033rem);
  order: 1;
}

.b {
  width: calc(100% / 3 * 1 + 0.0033rem);
  order: 2;
}

.c {
  width: calc(100% / 3 * 1 + 0.0033rem);
  order: 2;
}

.a {
  background: red;
}

.b {
  background: green;
}

.c {
  background: blue;
}

.a,
.b,
.c {
  padding: 1rem;
  min-height: 120px;
}

* {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
}

*::before,
*::after {
  box-sizing: border-box;
}

html,
body {
  width: 100%;
  height: 100%;
  font: 1rem/1.5 sans-serif;
}
<div class="container">
  <div class="content">
    <div class="a">Lorem ipsum dolor sit amet consectetur adipisicing elit. </div>
    <div class="b">Lorem ipsum dolor sit amet consectetur adipisicing elit.</div>
    <div class="c">Lorem ipsum dolor sit amet consectetur adipisicing elit. </div>
  </div>
</div>


align-items: center

如上所述,align-items: center在主 flex 容器 ( .container) 上禁用的布局允许项目.b&.c换行,因为::before伪项目占用了前一列中的所有空间flex-basis: 100%。视口设置环绕的高度限制和断点。

当您启用align-items: center时,容器 ( .content) 通过自由空间的分布垂直居中。不再有身高限制。没有断点告诉项目要包装。所以所有项目(包括伪项目)都保留在一个列中。

.container {
  display: flex;
  align-items: center;  /* enabled */
  justify-content: center;
  height: 100%;
  max-width: 960px;
  margin: auto;
}

.content {
  display: flex;
  flex-flow: column wrap;
  align-content: space-between;
  position: relative;
  background-color: gold;
}

.content::before,
.content::after {
  content: 'X';
  flex-basis: 100%;
  /* width: 0; */
  order: 2;
  position: relative;
}

.content::after {
  display: none;
}

.content>* {
  flex-grow: 1;
  flex-shrink: 1;
  min-height: 0.0033rem;
}

.a {
  width: calc(100% / 3 * 2 + 0.0033rem);
  order: 1;
}

.b {
  width: calc(100% / 3 * 1 + 0.0033rem);
  order: 2;
}

.c {
  width: calc(100% / 3 * 1 + 0.0033rem);
  order: 2;
}

.a {
  background: red;
}

.b {
  background: green;
}

.c {
  background: blue;
}

.a,
.b,
.c {
  padding: 1rem;
  min-height: 120px;
}

* {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
}

*::before,
*::after {
  box-sizing: border-box;
}

html,
body {
  width: 100%;
  height: 100%;
  font: 1rem/1.5 sans-serif;
}
<div class="container">
  <div class="content">
    <div class="a">Lorem ipsum dolor sit amet consectetur adipisicing elit. </div>
    <div class="b">Lorem ipsum dolor sit amet consectetur adipisicing elit.</div>
    <div class="c">Lorem ipsum dolor sit amet consectetur adipisicing elit. </div>
  </div>
</div>


推荐阅读