弹性盒子
flex
弹性盒子是一种新技术,但在如今各个浏览器都广泛支持的情况下,它已经开始准备广泛应用了。 弹性盒子提供了工具,允许快速创建曾经被证明用CSS很难实现的一些复杂,灵活的布局和功能。
长久以来,唯一可用的且有稳定的跨浏览器兼容性的能用来构建 CSS 布局的工具只有 floats 和 positioning。这些都很好而且有效,但是在某些布局方面它们就有限制,并且难以实现。
以下简单的布局要求是难以或不可能用这样的工具( floats 和 positioning)方便且灵活的实现的:
- 在父内容里面垂直居中一个块内容。
- 使容器的所有子项占用等量的可用宽度/高度,而不管有多少宽度/高度可用。
- 使多列布局中的所有列采用相同的高度,即使它们包含的内容量不同。
首先,我们需要选择将哪些元素将设置为柔性的盒子。我们需要给这些 flexible 元素的父元素 display 设置一个特定值。例如:
1 | section { |
flex 模型说明当元素表现为 flex 框时,它们沿着两个轴来布局:
主轴(main axis)
是沿着 flex 元素放置的方向延伸的轴(比如页面上的横向的行、纵向的列)。该轴的开始和结束被称为 main start
和main end
。交叉轴(cross axis)
是垂直于 flex 元素放置方向的轴。该轴的开始和结束被称为cross start
和cross end
。
设置了display: flex
的父元素(如是< section>)被称之为 flex 容器(flex container)。
在 flex 容器中表现为柔性的盒子的元素被称之为 flex 项(flex item)。
列还是行
弹性盒子提供了flex-direction
这样一个属性,它可以指定主轴的方向(弹性盒子子类放置的地方)— 它默认值是 row,这使得它们在按我们浏览器的默认语言方向排成一排(在英语/中文浏览器中是从左到右)。
1 | flex-direction: column; |
添加该代码到css代码里面去会看到,这会将那些元素设置为列布局。
注意:还可以使用row-reverse
和column-reverse
值反向排列 flex 项目。
换行
当我们在布局中使用定宽或者定高的时候,可能会有一个问题出来即处于容器中的 弹性盒子子元素会溢出,破坏了布局。解决此问题的一种方法是将以下声明添加到父元素css 规则中:
1 | flex-wrap: wrap |
同时把以下规则也添加到子元素中:
1 | flex: 200px; |
现在我们有了多行 弹性盒子— 任何溢出的元素将被移到下一行。但是这里我们可以做得更多。首先,改变flex-direction
属性值为row-reverse
— 会看到仍然有多行布局,但是每一行元素排列的方向和原来是相反的了。
flex-flow 缩写
到这里,应当注意到存在着flex-direction
和flex-wrap
的缩写flex-flow
。比如可以将
1 | flex-direction: row; |
替换为
1 | flex-flow: row wrap; |
flex 项的动态尺寸
1 | article { |
这是一个无单位的比例值,表示每个 flex 项沿主轴的可用空间大小。
本例中,我们设置 < article> 元素的 flex 值为 1,这表示每个元素占用空间都是相等的,占用的空间是在设置 padding 和 margin 之后剩余的空间。因为它是一个比例,这意味着将每个 flex 项的设置为 400000 的效果和 1 的时候是完全一样的。
现在在上一个规则下添加:
1 | article:nth-of-type(3) { |
现在刷新,会看到第三个 < article> 元素占用了两倍的可用宽度和剩下的一样 — 现在总共有四个比例单位可用。 前两个 flex 项各有一个,因此它们占用每个可用空间的1/4。 第三个有两个单位,所以它占用2/4或这说是1/2的可用空间。
还可以指定 flex 的最小值。 尝试修改现有的 article 规则:
1 | article { |
这表示“每个flex 项将首先给出200px的可用空间,然后,剩余的可用空间将根据分配的比例共享“。 尝试刷新,会看到分配空间的差别。
弹性盒子的真正价值可以体现在它的灵活性/响应性,如果调整浏览器窗口的大小,或者增加一个 < article> 元素,这时的布局仍旧是好的。
1 | flex: 缩写与全写 |
第一个就是上面所讨论过的无单位比例。可以单独指定全写 flex-grow 属性的值。
第二个无单位比例 — flex-shrink — 一般用于溢出容器的 flex 项。这指定了从每个 flex 项中取出多少溢出量,以阻止它们溢出它们的容器。 这是一个相当高级的弹性盒子功能,我们不会在本文中进一步说明。
第三个是上面讨论的最小值。可以单独指定全写 flex-basis 属性的值。
我们建议不要使用全写属性,除非你真的需要(比如要去覆盖之前写的)。使用全写会多写很多的代码,它们也可能有点让人困惑。
水平和垂直对齐
还可以使用 弹性盒子的功能让 flex 项沿主轴或交叉轴对齐。
在css中添加代码规则:
1 | div { |
刷新一下页面,就会看到相关内容垂直水平居中了
align-items
控制 flex 项在交叉轴上的位置。
默认的值是stretch
,其会使所有 flex 项沿着交叉轴的方向拉伸以填充父容器。如果父容器在交叉轴方向上没有固定宽度(即高度),则所有 flex 项将变得与最长的 flex 项一样长(即高度保持一致)。我们的第一个例子在默认情况下得到相等的高度的列的原因。
在上面规则中我们使用的 center 值会使这些项保持其原有的高度,但是会在交叉轴居中。这就是那些按钮垂直居中的原因。
也可以设置诸如flex-start
或flex-end
这样使flex
项在交叉轴的开始或结束处对齐所有的值。
可以用align-self
属性覆盖align-items
的行为。比如
1 | button:first-child { |
默认值是flex-start
,这会使所有 flex 项都位于主轴的开始处。
也可以用 flex-end 来让 flex 项到结尾处。
center 在 justify-content 里也是可用的,可以让 flex 项在主轴居中。
值 space-around 是很有用的——它会使所有 flex 项沿着主轴均匀地分布,在任意一端都会留有一点空间。
还有一个值是 space-between,它和 space-around 非常相似,只是它不会在两端留下任何空间。
CSS里的一种简单的垂直居中布局的方法了,例如代码:
1 | .vertical-container { |
flex 项排序
弹性盒子也有可以改变 flex 项的布局位置的功能,而不会影响到源顺序(即 dom 树里元素的顺序)。这也是传统布局方式很难做到的一点。
代码也很简单,将下面的 CSS 添加到示例代码下面。
1 | button:first-child { |
所有 flex 项默认的 order 值是 0。
order 值大的 flex 项比 order 值小的在显示顺序中更靠后。
相同 order 值的 flex 项按源顺序显示。所以假如你有四个元素,其 order 值分别是2,1,1和0,那么它们的显示顺序就分别是第四,第二,第三,和第一。
第三个元素显示在第二个后面是因为它们的 order 值一样,且第三个元素在源顺序中排在第二个后面。
flex 嵌套
弹性盒子也能创建一些颇为复杂的布局。设置一个元素为flex项目,那么他同样成为一个 flex 容器,它的孩子(直接子节点)也表现为 flexible box 。