一份有关CSS flexbox布局的综合指南。本指南介绍了有关flexbox的所有内容,重点介绍了父元素(flex容器)和子元素(flex项)的所有不同属性。它还包括了历史,示例,模式和浏览器支持情况。
背景
Flexbox布局(Flexible Box)模块(作为2017年10月的W3C候选建议书)旨在提供一种更有效的方式来布置,对齐和分配容器中各个元素之间的空间,即使它们的大小未知或动态(因此使用了 “ flex”一词)。
Flex 布局的主要思想是使容器能够更改其子元素的宽度/高度(以及顺序),以更好地填充可用空间(主要是适应各种显示设备和屏幕尺寸)。 一个Flex容器会扩大子元素以填充可利用的空余空间,或收缩它们以防止溢出。
最重要的是,与常规布局(基于垂直的块和基于水平的内联块)相反,FlexBox布局与方向无关。尽管这些常规布局在页面上效果很好,但是它们缺乏灵活性(没有双关语)来支持大型或复杂的应用程序(尤其是在方向更改,调整大小,拉伸,缩小等方面)。
注意:Flexbox布局最适合应用于组件和小规模布局,而Grid布局则用于较大规模的布局。
基础与术语
由于Flexbox是一个完整的模块,而不是单个属性,因此它涉及很多东西,包括它的整个属性集。其中一些用于设置在容器上(父元素,称为“flex容器”),而另一些用于设置在子元素上(称为“flex Items”)。
如果“常规”布局同时基于块和内联流方向布局,则Flex布局基于“flex-flow 方向”布局。请查看规范中的该图,解释flex布局背后的主要思想。
子元素将沿主轴(从 main-start 到 main-end)或交叉轴(从 cross-start 到 cross-end)布置。
- main axis(主轴) — 一个Flex容器的主轴是沿着 flex 元素放置的方向延伸的轴。需要注意的是,它不一定是水平的。它取决于
flex-direction
属性(请参见下文)。 - main-start | main-end — 主轴的开始和结束被称为 main start 和 main end。flex元素从 main-start 到 main-end 放置在容器中。
- main size — Flex 元素的宽或高,以主轴方向上的尺寸为准。
- cross axis(交叉轴) — 垂直于主轴的轴称为交叉轴。其方向取决于主轴方向。
- cross-start | cross-end — Flex线上填充元素,并从Flex容器的 cross-start 侧开始向 cross-end 侧放置。
- cross size — Flex 元素的宽或高,以交叉轴方向上的尺寸为准。
父元素(flex container)属性
display
这定义了一个flex容器;它是inline
还是 block
元素,具体取决于给定的值。它为其所有直接子级启用flex上下文。
.container {
display: flex; /* or inline-flex */
}
请注意,CSS columns
对flex容器无效。
flex-direction
这样就定义了主轴,从而确定了flex元素在flex 容器中的布局方向。Flexbox是(指定 flex-wrap 选项除外)单向布局概念。 可以将flex元素想像为主要布置在水平行或垂直列中。
.container {
flex-direction: row | row-reverse | column | column-reverse;
}
- row(默认):与文本方向相同。
- row-reverse:与文本方向相反。
- column:表现和
row
相同,但是从上到下。 - column-reverse:表现和
row-reverse
相同,但是从下到上。
文本方向参考,CSS direction
flex-wrap
默认情况下,所有Flex元素都尝试放在同一行上。您可以通过这个属性(
flex-wrap
)对此进行更改,允许Flex元素根据需要进行换行。
.container {
flex-wrap: nowrap | wrap | wrap-reverse;
}
- nowrap (默认):所有Flex元素都将在同一行上。
- wrap :flex 元素被打断到多个行中。
- wrap-reverse:和 wrap 的行为一样,但是 cross-start 和 cross-end 互换。
参考这些示例,flex-wrap demo
flex-flow
flex-flow
属性是 flex-direction
和flex-wrap
的简写,同时定义了flex容器的主轴和横轴。默认值为 row nowrap
·。
.container {
flex-flow: column wrap;
}
justify-content
这个属性定义了flex 元素沿主轴的对齐方式。 当一行上的所有flex 元素都非flex,或者是flex但已达到最大大小时,它有助于分配剩余的可用自由空间。 当项目溢出线时,它还对flex 元素的对齐方式施加一些控制。
.container {
justify-content: flex-start | flex-end | center | space-between | space-around | space-evenly | start | end | left | right ... + safe | unsafe;
}
- flex-start (默认):从
flex-direction
起始位置开始排列。 - flex-end:从
flex-direction
末尾位置开始排列。 - start :从
writing-mode
起始位置开始排列。 - end:从
writing-mode
末尾位置开始排列。 - left:f元素一个挨一个在对齐容器得左边缘,如果属性的轴与内联轴不平行,则left的行为类似于
start
。 - left:元素一个挨一个在对齐容器得右边缘,如果属性的轴与内联轴不平行,则right的行为类似于
start
。 - center:元素在每行上居中排列。
- space-between:元素在每行上均匀排列。相邻元素间距离相同。每行第一个元素与行首对齐,每行最后一个元素与行尾对齐。
- space-around:元素在每行上均匀排列。相邻元素间距离相同。每行第一个元素到行首的距离和每行最后一个元素到行尾的距离将会是相邻元素之间距离的一半。
space-evenly:元素的分布使得任意两个元素之间的间距(以及到边缘的间距)相等。
需要注意的是,浏览器对这些属性的支持有一些细微的差别。 例如,某些版本的Edge不支持
space-between
,而Chrome目前没有实现start/end/left/right
。 MDN有详细的图表。 最安全的值是flex-start
,flex-end
和center
。还有两个关键字可以和这些值配对使用:
safe
和unsafe
。使用safe
可以确保你无论使用哪个值,都不会以无法滚动的形式使元素溢出容器(如:超出屏幕顶部)呈现造成数据丢失。
align-content
这个属性设置了当 Flex 容器有多余空间时,多行元素如何在交叉轴上对齐。类似于
justify-content
规定元素如何在主轴上对齐一样。注意: 该属性对单行弹性盒子模型无效。(即:带有 flex-wrap: nowrap
)。
.container {
align-content: flex-start | flex-end | center | space-between | space-around | space-evenly | stretch | start | end | baseline | first baseline | last baseline + ... safe | unsafe;
}
- flex-start/start:所有行从容器的起始边缘开始填充。(比较受支持的)flex-start遵循flex-direction,而start遵循
writing-mode
方向。 - flex-end/end:所有行从容器的结束边缘开始填充。(比较受支持的)flex-start遵循flex-direction,而start遵循
writing-mode
方向。 - center:所有行朝向容器的中心填充。
- space-between:所有行在容器中平均分布。相邻两行间距相等。容器的垂直轴起点边和终点边分别与第一行和最后一行的边对齐。
- space-between:所有行在容器中平均分布。相邻两行间距相等。容器的垂直轴起点边和终点边分别与第一行和最后一行的距离是相邻两行间距的一半。
- space-evenly:所有行沿垂直轴均匀分布在对齐容器内。每对相邻的项之间的间距,主开始边和第一项,以及主结束边和最后一项,都是完全相同的。
- stretch:拉伸所有行来填满剩余空间。剩余空间平均地分配给每一行。
这里同样有safe
和unsafe
修饰符配合其他关键字使用。效果与justify-content
描述的类似。
子元素(flex items)属性
order
默认情况下,felx 元素是按源文件书写顺序排列。但是,order属性可以控制它们在flex容器中出现的顺序。
.item {
order: 5; /* default is 0 */
}
flex-grow
flex-grow
定义了flex 元素在必要时的增长系数。它接受无单位的数值作为比例。它决定了flex 元素在flex 容器内部占用多少可用空间。
如果flex 元素的 flex-grow
设置为1,则容器中的剩余空间将平均分配给所有子项。 如果其中一个子项的值为2,则剩余空间将占其他子项的两倍(或者至少会尝试)。
.item {
flex-grow: 4; /* default 0 */
}
不支持负数。
flex-shrink
flex-shrink
属性指定了 flex 元素的收缩规则。
flex 元素仅在默认宽度之和大于容器的时候才会发生收缩,其收缩的大小是依据 flex-shrink
的值。
.item {
flex-shrink: 3; /* default 1 */
}
负值是不被允许的。
flex-basis
flex-basis
定义了剩余空间分配之前元素的默认大小。该值可以是一个<length>
(如:20%, 5rem 等)或是关键字。
auto
关键字的含义是“参考的 width
或height
属性”。
注意: 当一个元素同时被设置了 flex-basis (除值为 auto 外) 和 width (或者在 flex-direction: column 情况下设置了height) , flex-basis 具有更高的优先级。
content
关键字的含义是“根据flex元素的内容调整大小”—此关键字尚未得到很好的支持,因此很难测试,也很难知道其兄弟属性 max-content
,min-content
和fit-content
的表现。
注意:由于最初规范中没有包括这个值,在一些早期的浏览器实现的flex布局中,content值无效,可以利用设置(width 或 height) 为 auto达到同样的效果.
简史:
- 最初,
flex-basis:auto
的含义是 “参照我的width和height属性”.- 在此之后,
flex-basis:auto
的含义变成了自动尺寸, 而main-size
变成了 “参照我的 width 和height 属性”。实际执行于 bug1032922。- 然后呢, 这个更改又在 bug 1093316 中被撤销了, 所以 “auto” 变回了原来的含义; 而一个新的关键字 ‘content’ 变成了自动尺寸。 (bug 1105111 包括了增加这个关键字).
.item {
flex-basis: | auto; /* default auto */
}
如果设置为0,则不考虑内容周围的多余空间。如果设置为auto,则多余的空间将根据其flex-grow值进行分配。
参考此图
flex
flex
是flex-grow
,flex-shrink
和flex-basis
组合的简写。第二个和第三个参数(flex-shrink
和flex-basis
)是可选的。默认值为0 1 auto
,但是如果您将其设置为单个数字值,则类似于1 0
。
.item {
flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
}
建议您使用此简写属性,而不是设置单个属性。简写可以智能地设置其他值。
flex语法
flex 属性可以指定1个,2个或3个值。
单值语法: 值必须为以下其中之一:
双值语法: 第一个值必须为一个无单位数,并且它会被当作<flex-grow>
的值。第二个值必须为以下之一:
- 一个无单位数:它会被当作
<flex-shrink>
的值。 - 一个有效的宽度值: 它会被当作
<flex-basis>
的值。
三值语法:
- 第一个值必须为一个无单位数,并且它会被当作
<flex-grow>
的值。 - 第二个值必须为一个无单位数,并且它会被当作
<flex-shrink>
的值。 - 第三个值必须为一个有效的宽度值, 并且它会被当作
<flex-basis>
的值。
align-self
align-self
允许为单个弹性项目覆盖默认对齐方式(或由align-items
指定的对齐方式)。请参阅align-items
文档以了解可用值。
.item {
align-self: auto | flex-start | flex-end | center | baseline | stretch;
}
请注意,float
,clear
和vertical-align
对flex 元素没有影响。
Flexbox 前缀
Flexbox需要一些供应商特殊前缀来支持尽可能多的浏览器。它不仅包含带有供应商前缀的前置属性,实际上还存在完全不同的属性和值名称。这是因为Flexbox规范已随着时间而变化,形成了“旧”,“补间”和“新”几个版本。
解决此问题的最佳方法可能是我们再编写时使用新的(也是最终的)语法,然后通过Autoprefixer编译CSS添加前缀,这样可以很好地处理情况。
另外,这里有一个Sass @mixin,可以帮助您完成一些前缀操作,还可以让您知道需要做什么:
@mixin flexbox() {
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
}
@mixin flex($values) {
-webkit-box-flex: $values;
-moz-box-flex: $values;
-webkit-flex: $values;
-ms-flex: $values;
flex: $values;
}
@mixin order($val) {
-webkit-box-ordinal-group: $val;
-moz-box-ordinal-group: $val;
-ms-flex-order: $val;
-webkit-order: $val;
order: $val;
}
.wrapper {
@include flexbox();
}
.item {
@include flex(1 200px);
@include order(2);
}
Bugs
Flexbox 当然也有一些bug。我见过的最好的(Flex)bug 收集网站是Philip Walton 和 Greg Whitworth的Flexbugs。它是一个追踪Flex bug 的开源库。
浏览器支持情况
按Flexbox的“版本”划分:
- (new) 表示规范中的最新语法(例如: display:flex;)
- (tweener) 表示2011年以来出现的一种奇怪的非官方语法(例如: display:flexbox;)
- (old ) 表示2009年的旧语法(例如: display:box;)
Chrome | Safari | Firefox | Opera | IE | Edge | Android | iOS |
---|---|---|---|---|---|---|---|
20- (old) 21+ (new) | 3.1+ (old) 6.1+ (new) | 2-21 (old) 22+ (new) | 12.1+ (new) | 10 (tweener) 11+ (new) | 17+ (new) | 2.1+ (old) 4.4+ (new) | 3.2+ (old) 7.1+ (new) |
Blackberry浏览器10+支持新语法。
其他资源
Flexbox in the CSS specifications
Flexbox at MDN
Flexbox at Opera
Diving into Flexbox by Bocoup
Mixing syntaxes for best browser support on CSS-Tricks
Flexbox by Raphael Goetter (FR)
Flexplorer by Bennett Feely
写于 2020年08月10日Css 8317
如非特别注明,文章皆为原创。
转载请注明出处: https://www.liayal.com/article/5f30e5047ff0f07e0ea449b8
记小栈小程序上线啦~搜索【记小栈】或【点击扫码】体验
ClariS01-06 2021
大佬tql