返回

CSS Flexbox布局的语法规则

2020-03-06

W3C于2009年提出了一种用于CSS布局的新方案:Flexbox,它可以简便、完整、响应式地实现各种页面布局。目前已经得到了各大浏览器和系统的支持,这意味着,现在就能很安全地使用这项功能了。本文将介绍这一布局方案的语法规则。

Flexbox的问世

Flexbox是Flexible Box的缩写,直译过来就是灵活的盒子,我们习惯称其为弹性布局,为盒状模型提供灵活的布局规则,它是W3C于2009年提出的一种用于CSS布局的新方案,在此之前,使用CSS进行布局只能依赖displaypositionfloat属性,对于一些场合的布局非常不方便,比如块状元素的垂直居中布局。

好在CSS3的Flexbox出世,给我们提供了更加便利的布局策略,而且到目前为止得到了各大浏览器和系统的支持,这将促使Flexbox成为未来的主流布局方案。

@-IMAGE

Flexbox的概念

所谓布局,是指在一个父元素内的各个子元素的排列显示方式,我们将父元素称为容器(container),各个子元素称为项目(item),布局其实就是对各个子元素进行排列显示。Flex布局中,有对父元素进行定义的属性,也有对子元素定义的属性。

@-IMAGE

我们通过下图查看Flex布局背后的思想,这也是我们日后写代码时脑海中需要建立的布局基准和概念。Flex概念中存在两个相互垂直的轴:主轴(main axis)和侧轴(cross axis)。图中main start和main end分别为主轴的起始点和结束点,cross start和cross end分别是侧轴的起始点和结束点。

@-IMAGE

项目在主轴方向上所占据的尺寸称为main size,在侧轴方向上占据的尺寸称为cross size。

注意:主轴并非始终是水平方向的,这取决于flex-direction属性(参见下文),相应的侧轴也并非总是垂直方向的,但它们始终相互垂直。 item默认沿主轴排列布局,确定了主轴,也就确定了item在container中的布局方向,Flexbox是单向布局概念,可以将item想像为主要沿水平行或垂直列布置。

实际上,我觉得将主轴与侧轴想像成我们常用的二位坐标图可能更加容易理解。在二位坐标图中的两个轴线分别为x轴和y轴,那么对应的就是主轴和侧轴,你可以让item沿x轴布局,也可以沿y轴布局,这取决于flex-direction的设置值。

@-IMAGE

容器(Container)的属性

display

任何可作为容器的元素都可以使用Flex布局,使用Flex布局的第一步是将container的display属性设置为flex

div{ display: flex; }
span{ display: inline-flex; }
.box{ display: flex; }
.container{ display: flex; }
……

Webkit内核的浏览器需要添加-webkit前缀。

.container{ 
    display: -webkit-flex; 
    display: flex; 
}

容器采用Flex布局后,子元素的float、clear和vertical-align属性都将失效。

flex-direction

确定container的主轴方向(水平或垂直),也即item在container中的布局方向。

.container{
    flex-direction: row | row-reverse | column | column-reverse;
}

@-IMAGE

  • row (默认): 主轴水平,起点位于左端,item从左向右排列布局
  • row-reverse: 主轴水平,起点位于右端,item从右向左排列布局
  • column: 主轴垂直,起点位于上端,item从上向下排列布局
  • column-reverse: 主轴垂直,起点位于下端,item从下向上排列布局

flex-wrap

默认情况下,item都将尝试被放在一条直线上,如果排列不下,可以通过flex-wrap设置处理方式。

.container{
    flex-wrap: nowrap | wrap | wrap-reverse;
}

@-IMAGE

  • nowrap (默认): 单行排列且不换行,可能导致container溢出

@-IMAGE

  • wrap: 多行排列可换行,item从上到下多行显示

@-IMAGE

  • wrap-reverse: 多行排列可换行,item从下向上多行显示

@-IMAGE

flex-flow

flex-flow属性是flex-direction属性和flex-wrap属性的简写形式,默认值为row nowrap

.container {
    flex-flow: <flex-direction> || <flex-wrap>;
}

justify-content

该属性定义了item在主轴上的对齐方式,当所有item都按照要求排列好后,它可以帮助分配剩余的可用空间;当item的排列发生溢出时,它还对item的对齐方式施加一些控制。

.container {
    justify-content: flex-start | flex-end | center | space-between | space-around | space-evenly;
}

@-IMAGE

  • flex-start (默认): 从主轴起始点开始排列
  • flex-end: 从主轴结束点开始排列
  • center: 居中排列
  • space-between: 第一个item位于主轴起始点,最后一个item位于主轴结束点,其余item均匀分布,间隔相等
  • space-around: item均匀分布,每个item都有相等的间隔,比如第一个和最后一个item距离container有1个单位的间隔,那么中间的item之间都会有2个单位的间隔距离,你可以想象成每个item都具备相同的margin属性
  • space-evenly: item均匀分布,并且距离主轴起始点和结束点的间隔与任意两个item之间的间隔都相等

另外,justify-content属性还有一些其他值,但是要注意浏览器对这些值的兼容性和支持不够完整,这些属性不常用,且安全性不足,有兴趣的可以去这里研究一下。

.container {
    justify-content: start | end | left | right ... + safe | unsafe;
}

需要注意的是,浏览器对这些值的支持是有细微差别的。例如,space-between从未得到Edge的支持,并且start end left right在Chrome中也没有得到支持。MDN有详细的图表。目前最安全的值是flex-startflex-endcenter

还有两个附加的值与这些值配对使用:safeunsafe。使用safe确保无论执行哪种类型的定位,都不能将item推送到无法显示内容的屏幕外(例如,在顶部)。

align-items

该属性定义item在侧轴上如何排列和对齐。

.container {
    align-items: stretch | flex-start | flex-end | center | baseline;
}

@-IMAGE

  • stretch(默认): 如果未设置item的高度或者高度值是auto,则拉伸item以填充container
  • flex-start: item都以侧轴起始点对齐布局
  • flex-end: item都以侧轴结束点对齐布局
  • center: item都以侧轴中心点对齐布局
  • baseline: item都以文字基线对齐

另外还有一些其他取值,start end self-start self-end safe unsafe,与上述常用的取值有些细微差别,如果你需要使用这些值,需要考虑安全性和浏览器的支持程度,你可以参考Browser compatibility中的内容。

align-content

该属性定义了当多行item在侧轴方向有多余空间时的对齐和排列方式,它与justify-content相似,区别在于justify-content是定义在主轴方向上。

前面曾介绍过的属性align-items定义的是单个item在单个侧轴上的对齐方式,align-content定义的是当有多个侧轴(即多行)时,每个侧轴在容器内的对齐方式,因此如果item只有一行,则align-content没有任何效果。

.container {
    align-content: flex-start | flex-end | center | space-between | space-around | space-evenly | stretch;
}

@-IMAGE

  • stretch(默认): 拉伸以占据所有空间
  • flex-start: 第一行与侧轴起始点对齐,其余行依次排列
  • flex-end: 第一行与侧轴结束点对齐,其余行依次排列
  • center: 多行依次排列,整体中心与侧轴中心对齐
  • space-between: 多行之间间隔相等,平均分布,第一行与容器起始点对齐,最后一行与容器结束点对齐
  • space-around: 多行均匀分布,每行都具有一定的间隔单位(可以想象成每行都有一个padding-top和padding-bottom一样),因此第一行和最后一行与container的距离是行与行之间距离的一半
  • space-evenly: 多行均匀分布,所有间隔都相等

项目(item)属性

除了定义在container上的一系列属性外,还可以给item单独定义一些属性让布局更加灵活多变。

order

从名字上就能判断出这个属性是用来排序的,默认情况下,item按照源代码书写顺序排列,但通过order属性可以控制它们在container中的出现顺序。

.item {
    order: <integer>; /* default is 0 */
}

@-IMAGE

默认值是0,数值越小,排列越靠前。

flex-grow

该属性定义了item在需要扩大时的能力,它是一个无单位的比例值,决定了item在需要分配container剩余空间时能得到的比例,默认值为0,代表即使有剩余空间也不会扩大。负数为无效值。

.item {
    flex-grow: <number>; /* default 0 */
}

@-IMAGE

假如所有item的flex-grow都设置为1,则container中的剩余空间将平均分配给各item。如果其中一个item的值为2,则它被分配到的剩余空间将是其他item的两倍(当无法整分时系统也会尝试接近两倍)。

flex-shrink

该属性定义了item在container空间不足时需要收缩的能力。默认值为1,代表空间不足时该item将缩小。负数为无效值。

.item {
  flex-shrink: <number>; /* default 1 */
}

@-IMAGE

假如所有item的flex-shrink属性都为1,当空间不足时所有item按照相同比例缩小。如果其中一个item的值为0,则当空间不足时值为0的item不会缩小。

flex-basis

该属性定义了item在分配多余空间之前在主轴方向上所占据的空间,浏览器根据这个属性,计算主轴方向是否有多余空间。默认值为auto,代表本来大小,多余空间将根据其flex-grow值进行分配。它还有一个content的值,代表基于item中的内容来定义大小,但content值还未得到广泛支持,暂时不建议使用。

.item {
    flex-basis: <length> | auto; /* default auto */
}

flex

该属性是flex-grow, flex-shrinkflex-basis的简写,默认值为0 1 auto。其中flex-shrinkflex-basis是可选的。

.item {
    flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
}

该属性有两个快捷值,分别为auto(等同于1 1 auto)和none(等同于0 0 auto)。

官方建议我们优先使用简写属性,浏览器会自动推算相关联的值。

align-self

该属性允许item有与其他item不一样的对齐方式,设置该属性即覆盖了container的align-items属性值,表示不依从container定义的对齐规则。默认值为auto,表示遵守container的align-items属性设定,如果没有父元素,则等同于stretch。

.item {
    align-self: auto | flex-start | flex-end | center | baseline | stretch;
}

@-IMAGE

该属性中除了auto外,其余设定值都与container的align-items属性值相同。

结语

以上为FlexBox布局的语法规则,截止到目前,大部分属性值都可以安全的使用,FlexBox的布局能满足日常大部分应用需求,填补了CSS中垂直居中的长期烦恼,在布局后台模版时尤其变的简单明了。

想要考察一下自己对Flex掌握情况,可以去Flexbox Froggy玩个小游戏。

最后再次强调:使用FlexBox布局后,item的float,clear和vertical-align均无效。

    [参考文档]

谢谢捧场,点个赞呗

本文链接地址:https://uixor.com/article/1475290610406658049

请本着遵守国家法律法规,尊重他人劳动成果的原则在转载处注明文章来源,如有冒犯他人权益,请 联系我