CSS——弹性盒子布局(display: flex)
我们经常听说一种布局:Flexbox
或者是弹性布局
,它的全称叫做弹性盒子布局(Flexible Box Layout)
,那么它到底该如何实现呢?从我们熟悉的 display 属性开始。给元素添加 display: flex,该元素变成了一个弹性容器(flex container),它的直接子元素变成了弹性子元素(flex item)。那么最简单的弹性盒子布局就完成了,它具有以下的效果:
- 弹性容器像块元素一样填满可用宽度(注意,这里只是弹性容器,即添加了display: flex的元素),高度由自身内容决定,但是弹性子元素不一定填满其弹性容器的宽度。
- 弹性子元素默认是在同一行按照从左到右的顺序并排排列。
- 弹性子元素高度相等,该高度由它们的内容决定。
当然,我们可以手动的设置它们的宽高,但是在Flexbox布局中,弹性是其最突出的属性,所有一般我们不建议这样做。在大致了解了它最显著的作用之后,下面我们来进行细致深入的学习。
基础概念
Flexbox布局中,有两根重要的轴线——主轴&副轴,其属性几乎都是围绕着这两根轴线来描述的。默认情况下,主轴是水平的,它的起点为最左侧,终点为最右侧,对应的,有一根与之垂直相交的副轴,它的起点是最上侧,终点是最下侧。当然,这些方向可以改变,我们稍后介绍。
相关属性
-
flex-direction
作用:决定主轴的方向(弹性子元素的排列方向)row
(默认值):水平,起始在左端row-reverse
:水平,起始在右端column
:竖直,起始在上沿column-reverse
:竖直,起始在下沿
-
flex-wrap
作用:决定直接子元素是否换行以及如何换行nowrap(默认)
:不换行wrap
:换行,第一行在上方wrap-reverse
:换行,第一行在下方
-
flex-flow
作用:前面两个属性的简写,默认值为row nowrap
-
justify-content
作用:决定弹性子元素在主轴上的对齐方式flex-start(默认值)
:左对齐flex-end
:右对齐center
:居中space-between
:两端对齐,弹性子元素之间的间隔相等space-around
:弹性子元素两侧的间隔相等,相邻之间的间隔会叠加
-
align-content
作用:决定多行/列弹性子元素在交叉轴上的的对齐方式 (前提是要开启flex-wrap)stretch(默认值)
:每行元素将会被拉伸,直至撑满整个交叉轴,每行/列之间的间隔相等flex-start
:与交叉轴起点对齐flex-end
:与交叉轴终点对齐center
:在交叉轴上居中对齐space-between
:与交叉轴两端对齐,弹性子元素之间的间距相等space-around
:弹性子元素两侧的间隔相等,相邻之间的间隔会叠加
-
flex-items
作用:决定单行/列弹性子元素在交叉轴上的对齐方式- stretch(默认值):如果没有设置高度/高度设置为auto,那么将撑满整个盒子
- flex-start、flex-end、center属性值的效果同上
- baseline:项目的第一行文字的基线对齐(效果如下,紫色是盒子)
-
flex-basis
作用:指定子元素未受flex-grow或flex-shrink影响时的初始大小
取值:<length>或<percent>,初始值是auto
(此时会检查元素是否设置了width属性。如果有,则使用 width 的值作为 flex-basis 的值;如果没有,则用元素内容自身的大小。如果 flex-basis 的值不是 auto,width 属性会被忽略) -
flex-grow
作用:每个弹性子元素的 flex-basis 值计算出来后,它们(加上子元素之间的外边距)加起来会占据一定的宽度。加起来的宽度不一定正好填满弹性容器的宽度,可能会有留白。多出来的留白(或剩余宽度)会按照 flex-grow(增长因子)的值分配给每个弹性子元素。
取值:非负,初始值是0(此时元素的宽度不会超过flex-basis的宽度,不参与分配)
示例:flex-grow 的值越大,元素的“权重”越高,也就会占据更大的剩余宽度。一个 flex-grow: 2 的子元素增长的宽度为 flex-grow: 1 的子元素的两倍,如下图:
-
flex-shrink
作用: flex-shrink 属性与 flex-grow 遵循相似的原则。计算出弹性子元素的初始主尺寸后,它们的累加值可能会超出弹性容器的可用宽度。如果不用 flex-shrink,就会导致溢出,每个子元素的 flex-shrink 值代表了它是否应该收缩以及相应的收缩比例以防止溢出。(在开启了flex-wrap
之后会忽略此属性)
取值:非负,初始值为1(为 0 时,不会缩小)效果:
- 如果元素A的flex-shrink为0,而其他的元素都为0,那么A不会缩小
- 如果元素A的flex-shrink为2,元素B的flex-shrink为1,那么A的缩小的部分的长度是B的缩小部分的长度的2倍
示例:如下图:
代码:
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>flex-shrink缩放</title><style>* {padding: 0;margin: 0;box-sizing: border-box;}body {padding: 1em;}#content {display: flex;width: 500px;}#content div {flex-basis: 120px;border: 3px solid rgba(0, 0, 0, 0.2);}.box {flex-shrink: 2;}.box1 {flex-shrink: 1;}.result {margin-top: 20px;}p {line-height: 1.5em;}</style>
</head><body><p>容器宽度为 500px, 弹性子元素的flex-basic 是120px</p><p>A, B, C 设置 flex-shrink:2, D 和 E 设置 flex-shrink:1</p><p>根据js打印输出可知,A、B、C缩小的长度是D、E缩小长度的2倍</p><div id="content"><div class="box" id="A" style="background-color:red;">A</div><div class="box" style="background-color:lightblue;">B</div><div class="box" style="background-color:yellow;">C</div><div class="box1" id="D" style="background-color:brown;">D</div><div class="box1" style="background-color:lightgreen;">E</div></div><div class="result"></div><script>const A = document.getElementById("A");const A_width = getComputedStyle(A).width;const D = document.getElementById("D");const D_width = getComputedStyle(D).width;const content = document.getElementById("content");const content_width = getComputedStyle(content).width;const result = document.querySelector(".result");result.innerHTML = `A, B, C 缩放之后的长度是${A_width},<br />E缩放之后的长度是${D_width}, <br />容器宽度是${content_width}`</script></body></html>
-
flex
作用:flex-grow
、flex-shrink
、flex-basis
三个属性的简写
取值:- 单值语法:值必须是以下之一:
- 一个
<flex-grow>
的有效值:此时简写会扩展为flex: <flex-grow> 1 0
。 - 一个
<flex-basis>
的有效值:此时简写会扩展为flex: 1 1 <flex-basis>
。 - 关键字
none
或者全局关键字(见后面)
之一。
- 一个
- 双值语法:
- 第一个值必须是一个
flex-grow
的有效值。 - 第二个值必须是以下之一:
- 一个
flex-shrink
的有效值:此时简写会扩展为flex: <flex-grow> <flex-shrink> 0
。 - 一个
flex-basis
的有效值:此时简写会扩展为flex: <flex-grow> 1 <flex-basis>
。
- 一个
- 第一个值必须是一个
- 三值语法:值必须按照以下顺序指定:
- 一个
flex-grow
的有效值。 - 一个
flex-shrink
的有效值。 - 一个
flex-basis
的有效值。
- 一个
全局关键字:
-
initial
元素会根据自身宽高设置尺寸。它会缩短自身以适应 flex 容器,但不会伸长并吸收 flex 容器中的额外自由空间来适应 flex 容器。相当于将属性设置为"flex: 0 1 auto"。 -
auto
元素会根据自身的宽度与高度来确定尺寸,但是会伸长并吸收 flex 容器中额外的自由空间,也会缩短自身来适应 flex 容器。这相当于将属性设置为 “flex: 1 1 auto”. -
none
元素会根据自身宽高来设置尺寸。它是完全非弹性的:既不会缩短,也不会伸长来适应 flex 容器。相当于将属性设置为"flex: 0 0 auto"。
注意:
-
flex
属性与以往的简写属性不同,推荐使用简写形式,因为这样可以尽可能避免多次分开书写导致的布局不一致,并且可以提高对浏览器的兼容性。 -
<'flex-grow'>
定义 flex 项目的 flex-grow 。负值无效。省略时默认值为 1。 (初始值为 0) -
<'flex-shrink'>
定义 flex 元素的 flex-shrink 。负值无效。省略时默认值为1。 (初始值为 1) -
<'flex-basis'>
定义 flex 元素的 flex-basis 属性。若值为0,则必须加上单位,以免被视作伸缩性。省略时默认值为 0。(初始值为 auto)
简记:
采用逻辑推断的方法,初始值肯定会从安全性的角度考虑,所以,元素尽量不要随意放大,所以flex-grow属性初始为0;容器会尽量容纳下所有的元素,所以flex-shrink属性初始值为1;为了以元素自身为主导,flex-basis初始值为auto。而所谓的默认值,是在flex简写的写法中被省略时补充的值,以上规则能够体现出来。
- 单值语法:值必须是以下之一:
-
order
作用:将弹性子元素从兄弟节点中移动到指定位置,覆盖源码顺序,值越小,位置越靠前
取值:整数,初始值是0
注意:慎重使用,因为视觉布局与源码顺序差别太大会影响网站的可访问性。在大多数浏览器里使用 Tab 键浏览元素的顺序与源码保持一致,如果视觉上差别太大就会令人困惑。视力受损的用户使用的大部分屏幕阅读器也是根据源码的顺序来的。 -
align-self
作用:跟弹性容器的 align-items 属性效果相同,但是它能单独给弹性子元素设定不同的对齐方式。
取值与效果:auto 为初始值,会以容器的 align-items 值为准。其他值会覆盖容器的设置。align-self属性支持的关键字与 align-items 一样:flex-start、flex-end、center、stretch 以及 baseline。
结尾
感谢大家支持,如有错误,恳请指出,希望与大家共同进步!