FlexBox——CSS Flexible Box Layout Module

Clloz · · 279次浏览 ·

前言

flexbox(CSS Flexible Box Layout Module)是CSS3新增的特性,是一种新的弹性盒模型布局,这是一种在二维层面上的布局模型,它不仅可以让我们方便的分配空间给盒子中的元素,甚至是分配给元素的周围,同时也提供了在二维方向上对齐元素的功能,弹性盒模型布局让我们在实现响应式的页面的时候能够更方便更自如的实现功能。

CSS中的布局模式

CSS2.2规范里出现了四种布局模式(layout mode):

  • 块布局:用来布置文件。块布局包含以文档为中心的功能,例如 浮动元素或将其放置在多列上的功能。
  • 行内布局:用来布置文本。
  • 表格布局:用来布置表格。
  • 定位布局:用来对那些与其他元素无交互的定位元素进行布置。

布局模式其实是一种基于盒子与其兄弟和祖辈盒子的交互方式来确定盒子的位置和大小的算法,浏览器根据文档中元素的CSS属性来确定用哪种布局。为了应对新的需求,在CSS3里面新增了两种新的布局:
– 弹性盒子布局:用来布置那些可以顺利调整大小的复杂页面。
– 网格布局:用来布置那些与一个固定网格相关的元素。

flex布局已经进入Candidate Recommendation (CR)阶段,grid布局目前还处在Working Draft (WD)工作草案阶段,属于实验性API。

浮动,display和position属性都会影响布局模式。

弹性布局模式

CSS3引入新的布局模式自然是因为已有的布局模式不能适应页面的发展,CSS2中的四种布局方式在目前的复杂页面上,尤其是大量页面需要响应式的适配各种设备,实现起来比较复杂,这样的需求自然引出了弹性布局的模式。弹性布局表面上看和块布局相似,但是失去了块布局中的一些属性,比如float,clear和vertical-align,相对的,弹性布局获得了分配空间和设置对齐方式的极大灵活性。我们通过设置元素的display: flex或者diplay: inline-flex来初始化一个弹性容器(flex container),弹性容器中的流内(in-flow)子元素称之为弹性项目(flex items),在这个弹性容器中:

  • 可以沿任何流动方向布置(向左,向右,向下,甚至向上!)
  • 可以在样式层中反转或重新排列其显示顺序(即,视觉顺序可以独立于源和语音顺序)
  • 可沿单个(主)轴线性布局或沿二级(交叉)轴包裹成多条线
  • 可以“弯曲”它们的尺寸以响应可用空间
  • 可以在二级(十字架)上相对于其容器或彼此对齐
  • 可以沿主轴动态折叠或不折叠,同时保留容器的交叉大小

我们在CSS2中解除了IFC和BFC,flex容器同样生成一个flex formatting context,和BFC相似,不过用弹性布局代替了块布局。在FFC中,容器的margin不会和内容的margin发生塌陷(collapse),在FFC中,float,clear,vertical-align,::first-line and ::first-letter都是无效的。容器中的空白符不会显示,相当于添加了display: none的文本节点一样。

flex布局

设置了displayflex或者inline-flex的元素就成为了一个弹性容器,理解flex布局就要理解flexible box的基本概念,在容器中有两根轴,水平的主轴(main axis)和垂直的交叉轴(cross axis)。主轴的开始位置(与边框的交叉点)叫做main start,结束位置叫做main end;交叉轴的开始位置叫做cross start,结束位置叫做cross end。项目默认沿主轴排列。弹性容器活弹性项目主轴空间叫做main size,占据的交叉轴空间叫做cross size。

主轴和交叉轴不是绝对的,并不是水平的轴就是主轴,这取决于你的flex-direction属性。

flex

容器(flex container)

容器有6个属性:

  • flex-direction
  • flex-wrap
  • flex-flow
  • justify-content
  • align-items
  • align-content

flex-direction

flex-direction决定了容器主轴的方向,也就是决定了flex items在容器里如何排列,flexbox是单向布局概念,可以理解为item在水平行或垂直列中排列。
flex-direction可以取下面四个值:

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

flex-direction

  • row(默认值):主轴为水平方向,起点在左端。
  • row-reverse:主轴为水平方向,起点在右端。
  • column:主轴为垂直方向,起点在上沿。
  • column-reverse:主轴为垂直方向,起点在下沿。

containerdirection属性会影响rowrow-reverse的表现,当directionltr的时候表现为上述,当为rtl的时候则相反

flex-wrap

flex-wrap

默认情况下flex items排在一条直线上,你可以通过flex-wrap属性来设置项目的换行方式。

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

flex-wrap有三个值:
(1) nowrap(默认):不换行。

flex-wrap1

(2) wrap:项目换行,按顺序从上到下排列。

flex-wrap2

(3) wrap-reverse:项目换行,按顺序从下到上排列。

flex-wrap3

flex-flow

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

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

justify-content

该属性定义了项目在主轴上的对齐方式。

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

justify-content

该属性一共可以取6个值:

  • flex-start (default): 项目向start line对齐排列,首项与start line对齐
  • flex-end: 项目向end line对齐排列,首项在与end line对齐
  • center: 项目居中对齐
  • space-between: 项目均匀分布在主轴上,首项与start line对齐,末项与end line对齐
  • space-around: 项目均匀地分布在主轴上,每个项目的环绕空间相等。注意不是绝对的“平均”,由于每个项目两侧的空间相等,所以第一个项目的左边和最后一个项目右边的空间只有其他间隔的一半。
  • space-evenly: 所有空白空间均匀地分布在项目之间,任意两个项目之间的间隔都相等(包括首尾与边缘的间隔)

start lineend line不是固定的,这取决于你的containerflex-directiondirection两个属性。

align-items

这个属性定义了项目沿交叉轴布局的默认行为,类似于交叉轴上的justify-content属性。

align-items

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

该属性可以取五个值:

  • flex-start: 项目的croess-start方向的margin边缘对齐cross-start line
  • flex-end: 项目的croess-end方向的margin边缘对齐cross-end line
  • center: 项目在交叉轴上居中对齐
  • baseline: 项目的content里的第一行文字的基线对齐
  • stretch (default): 项目未设置高度或者高度为auto则items会占满整个容器的高度

flex-startflex-end依然不是绝对的,当我们的主轴为column的时候,directionflex-direction依然会影响align-items的表现。

align-content

align-items适用于当我们只有一行或者一列items的情况,当我们拥有多行或者多列items的时候就需要align-content属性,它相当于justify-content在交叉轴上的扩展,我们可以把每一行(每一列)想象成一个item,他们在交叉轴上的排列就可以类比justify-content在主轴上的效果。

align-content

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

该属性可以取六个值:

  • flex-start: 每一行向交叉轴起点对齐
  • flex-end: 每一行向交叉轴终点对齐
  • center: 在交叉轴居中对齐
  • space-between: 行均匀的分布在交叉轴上,第一行位于交叉轴的起点,最后一行位于交叉轴的终点
  • space-around: 空白空间均匀分布在行之间,首行和末行与边沿之间的空白是行与行之间空白的一半
  • stretch (default): 所有的行占满全部交叉轴,第一行位于交叉轴起点,占满的方式是增加每一行与下一行或者边沿的空白空间,首行与边沿除外。

依然要注意flex-startflex-end不是绝对的。当flex items只有一行的时候,该属性无效。

项目(flex item)

容器内的每一个in-flow元素都是一个flex item,每个项目都有六个属性:

  • order
  • flex-grow
  • flex-shrink
  • flex-basis
  • flex
  • align-self

order

order属性定义项目的排列顺序。数值越小,排列越靠前,默认为0。

order

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

flex-grow

该属性定义了flex item放大的能力,它接受一个无比的值作为一个比例。它规定了项目应占用的Flex容器内可用空间量。
如果所有项目都flex-grow设置为1,则容器中的剩余空间将平均分配给所有子项。如果其中一个孩子的值为2,则剩余空间将占用其他空间的两倍(或者至少会尝试)。

flex-grow

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

负数无效。

flex-shrink

该属性定义了flex item的缩小能力,默认为1,即如果空间不足,该项目将缩小。

shrink

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

如果所有项目的flex-shrink属性都为1,当空间不足时,都将等比例缩小。如果一个项目的flex-shrink属性为0,其他项目都为1,则空间不足时,前者不缩小。

负数无效。

flex-basis

该属性定义了在分配空余空间之前一个项目的默认大小,当我们设置一个具体的值的时候(比如20%,5em,100px等),那么元素的默认大小就是这个值,如果没有设置具体的值,那么这个属性默认是auto,当属性为auto的时候,会根据元素的主轴长度属性来定义元素的默认大小,如果主轴长度属性也是auto的话,那么flex item就会根据content来设置大小。当主轴长度属性和flex-basis同时存在的时候,生效的是flex-basismin-widthmax-width能对flex-basis产生限制。

主轴长度属性指的是flex item在主轴方向上的大小,当横轴是主轴的时候指的是元素的width,当主轴是纵轴的时候指的是元素的height。

需要注意的是,当flex-grow不为0,设置flex-basis0auto会产生不同的效果(当item中有content的时候),当flex-basis0的时候,不会考虑环绕元素的空白,而是元素根据flex-grow全部分完所有空间。而flex-basisauto的时候,会把空白的空间按照flex-grow的值分配给每个item,此时item的实际宽度(或者高度)就是content的宽度 + 分配的空间。效果W3C文档给出如下图:

flex-basis

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

经过测试,对item的大小起作用的优先级 max-width = max-width > content > flex-basis > width,flex-basis只是一个默认值以便浏览器用以计算空白空间,实际项目的大小还要根据剩余的空间以及flex-grow或者flex-shrink来计算,如果空间不够了就会缩小,空间超过则会放大。

flex

flex属性是flex-grow, flex-shrinkflex-basis的简写,默认值为0 1 auto。后两个属性可选。关键字「none」的计算值为「0 0 auto」。当flex-grow被省略时取值为1flex-shrink被省略时取值1flex-basis被省略是取值0 。这里的省略值与我们上面提到的三个属性的默认值是不同的,这样的设计是为了让这个简写属性能够更好的匹配我们的常用情景。

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

flex的常见属性:

  • 「flex: initial」:与「flex: 0 1 auto」相同。(这也就是初始值。)根据「width」/「height」属性决定元素的尺寸。(如果项目的主轴长度属性的计算值为「auto」,则会根据其内容来决定元素尺寸。)当剩余空间为正值时,伸缩项目无法伸缩,但当空间不足时,伸缩项目可收缩至其最小值。网页作者可以用对齐相关的属性以及「margin」属性的「auto」值控制伸缩项目沿着主轴的对齐方式。
  • 「flex: auto」:与「flex: 1 1 auto」相同。根据「width」/「height」属性决定元素的尺寸,但是完全可以伸缩,会吸收主轴上剩下的空间。如果所有项目均为「flex: auto」、「flex: initial」或「flex: none」,则在项目尺寸决定后,剩余的正空间会被平分给是「flex: auto」的项目。
  • 「flex: none」:与「flex: 0 0 auto」相同。根据「width」/「height」属性决定元素的尺寸,但是完全不可伸缩。其效果与「initial」类似,但即使在空间不够而溢出的情况下,伸缩项目也不能收缩。
  • 「flex: positive-number」:与「flex: positive-number 1 0」相同。该值使元素可伸缩,并将伸缩基准值设置为零,导致该项目会根据设置的比率占用伸缩容器的剩余空间。如果一个伸缩容器里的所有项目都使用此模式,则它们的尺寸会正比于指定的伸缩比率。

align-self

align-self属性允许单个项目有与其他项目不一样的对齐方式,可覆盖align-items属性。默认值为auto,表示继承父元素的align-items属性,如果没有父元素,则等同于stretch。

align-self

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

example

See the Pen Demo Flexbox 1 by CSS-Tricks (@css-tricks) on CodePen.0

总结

flex布局其实在我看来主要解决了我们原来的四种布局方式不灵活的地方,有时我们需要一些固定宽度的元素,但想保持元素间的间隔是自适应的,实现器来可能就比较麻烦,有了flex布局我们能够更灵活的安排空白空间,不仅能控制我们的元素,同时能控制包裹在元素周围的空白空间,flex布局的文档目前已经处在Candidate Recommendation候选建议书阶段了,应该说大部分功能都已经确定了,想要更好的掌握这种布局还有许多细节需要把握,想看文档的点击这里,有一个学习flex布局的游戏Flexbox Zombies可以尝试一下。

参考文章:
A Complete Guide to Flexbox
[翻译]Flex Basis与Width的区别
flex设置成1和auto有什么区别


Clloz

人生をやり直す

发表评论

电子邮件地址不会被公开。 必填项已用*标注

我不是机器人*

EA PLAYER &

历史记录 [ 注意:部分数据仅限于当前浏览器 ]清空

      00:00/00:00