原文:What Happens When You Create A Flexbox Flex Container?,by Rachel Andrewcss
按我想法的话,CSS 网格布局(grid)和弹性布局(Flexbox)应该同时出现才对,这样网页布局方案就变得完整了。事实是,弹性布局先出现,由于使用弹性布局建立类网格(grid-type)系统比使用浮动更加便捷,因而咱们便获得了许多基于 Flexbox 的网格系统。实际上,Flexbox 的优点并非用来建立网格系统,这也是为何有时咱们在用它建立网格系统时,感受很费劲的缘由。算法
我准备开一个小系列的文章,花点时间解密一下 Flexbox——就像过去我在讲解 Grid 同样。咱们将看到 Flexbox 的设计目的,它真正作得好的地方,以及为何咱们不选择它做为布局方法。本文中将会介绍当咱们在使用 display: flex
的时候,到底发生了什么?app
为了使用弹性布局,咱们须要先有一个元素充当 Flex 容器的角色。容器使用 display: flex
声明:ide
📷See the Pen Smashing Flexbox Series 1: display: flex; by Rachel Andrew布局
display: flex
到底作了什么呢?在 Display Module Level 3 规范中,定义每 display 属性值由两部分组成:内部显示模型(inner display model)和外部显示模型(outer display model)。咱们使用 display: flex
的时候,实际定义的是 display: block flex
。Flex 容器的外部显示类型是 block
,在文档流(normal flow)中表现为块级元素(block level element),内部显示类型是 flex
,因此容器的直接子元素将参与弹性布局。flex
固然,咱们还可使用 display: inline-flex
定义 Flex 容器,与上面声明相似,它实际定义的是 display: inline flex
。Flex 容器表现的像个行内元素,其直接子元素将参与弹性布局。ui
📷See the Pen Smashing Flexbox Series 1: display: inline-flex; by Rachel Andrewflexbox
理解了元素的外部显示模型和内部显示模型,对理解元素及其子元素在页面中的表现行为很是有帮助。你能够将这种思路带入到任意其余类型的盒子中:这个元素的表现特征为什么?它的子元素呢?答案是跟外部显示模型和内部显示模型有关。spa
定义好 Flex 容器后,一些初始值就开始起做用了。在咱们没有设置任何其余属性的状况下,全部的 Flex 项目 会排列为一行。之因此如此,是由于 flex-direction
的初始值是 row
。设计
flex-direction
属性设置的是主轴(main axis)的方向,取值除了 row
以外,还包括:
column
row-reverse
column-reverse
这些排列在一行的 Flex 项目,始于内联维度(inline dimension)的起始边缘(start edge)、按照在源码中出现的结构顺序,依次排列。在规范中,这个“起始边缘”被称为 main-start
:
main-start
位于内联维度的起始端
若是使用的是 column
,则 Flex 项目从块维度(block dimension)起始边缘开始排列,从而造成一列。
main-start
位于块维度的起始端
若是使用的是 row-reverse
,则 main-start
和 main-end
的位置就调换了。所以,Flex 项目会一个个按照与以前相反的顺序排列。
main-start
位于内联维度的终端
column-reverse
的做用于此相似。须要知道的是,这些值没有“改变 Flex 项目的顺序”,顺序变了只是表征而已,改变的实际上是 Flex 项目从哪开始布局,也就是说改变的是 main-start
的位置。所以,Flex 项目按照反序显示,由于它们是沿着容器 的另外一边开始布局的。
还有一个比较重要的点,就是 Flex 项目的排列顺序上的不一样只是纯视觉上的。咱们只是要求 Flex 项目从结束边缘(end edge)开始显示,对于屏幕阅读器(screen reader)或是当你按 Tab 键切换元素的时候,结果顺序仍是在源码中出现的顺序。
上面多此重复按下 Tab 键,能够观察按钮被 focus 的顺序与在源码中出现的顺序同样,与显示顺序无关。
咱们已经讲了弹性布局里一个很是重要的特性:主轴方向能从行切换到列。理解这种轴切换,能使咱们更好地理解网格布局中对齐的工做原理。网格属于二维布局,咱们几乎可使用在弹性布局中一样的方式设置 Grid 项目在两个轴上的对齐效果。
咱们已经解释了主轴,也就是 flex-direction
属性值定义的那个方向。交差轴(cross axis)是另外一个维度。若是你设置了 flex-direction: row
,主轴是沿着行的,而交差轴沿着列向下。若是设置的是 flex-direction: column
,则主轴沿着列向下,而交差轴则沿着行。这就是咱们要介绍的弹性布局的另外一个重要特性,两个轴的方向与屏幕的物理 维度没有关系,咱们没有讨论从左到右的行,或从上到下的列,是由于状况并不是老是如此。
上面在讲行和列的时候,提到了内联和块维度。本文使用英文书写的,是水平书写格式(译注:原文是英文,不过如今中文书写格式也与英文同样)。也就是当你为 Flexbox 指定为 row
排列方式的话,会获得水平排列的 Flex 项目。这种状况下,main-start
在左边——也就是英文句子开始的地方。
像在阿拉伯这样的语言方向从右向左的国家,那么起始边缘始于右边。
See the Pen Smashing Smashing Flexbox Series 1: row with rtl text by Rachel Andrew
当我只是建立了一个 Flex 容器的时候,Flexbox 的初始值代表 Flex 项目从右边开始,向左排列显示。内联方向(inline direction)的起始边缘就是咱们使用的书写模式下句子开始的地方。
垂直书写模式(vertical writing mode)下的行是垂直的,由于在垂直语言环境下行就是垂直的,文本也是垂直显示的。咱们在 Flex 容器上设置 writing-mode: vertical-lr
就能看到效果。这时候,当你设置 flex-direction
为 row
的时候,就能看到在垂直方向上显示的 Flex 项目。
See the Pen Smashing Smashing Flexbox Series 1: row with a vertical writing mode by Rachel Andrew
所以,行能够是水平显示,main-start
在左边或右边,固然也能够是垂直的,main-start
在顶部。当你习惯于水平排列思惟,看到垂直书写模式下设置了 flex-direction: row
的 Flex 容器中的项目 是垂直排列的,可能感受很奇怪,不过人家确实是在行的方向上排列的。
要让 Flex 项目在块维度上布局的话,为 flex-direction
设置 column
或 column-reverse
。在英语环境下,咱们看见 Flex 项目从 Flex 容器顶部开始、依次往下布局排列的。
在垂直书写模式下,块维度是横跨页面的,相似于此种模式下块元素的排列方式。若是设置了 vertical-lr
,则块元素是从左到右排列的。
See the Pen Smashing Smashing Flexbox Series 1: column in vertical-lr writing mode by Rachel Andrew
但不论块元素是在什么方向显示排列的,若是 flex-direction
设置 column
的话,那么就是在块维度上布局的。
理解了行和列在不一样的书写模式中,表如今不一样的物理方向上,对理解 Grid 和 Flexbox 中的一些术语很是有用。咱们没有在 Grid 和 Flexbox 中提到“从左到右”或是“从上到下”是由于咱们没有作任何文档书写模式的假设。咱们如今的 CSS 正在变得更加兼容书写模式,若是你想了解更多表现行为于此相似的其余属性和值的话,能够阅读我写的文章Logical Properties and Values。
好了,咱们来总结一下:
main-start
位于在给定书写模式下句子起始的地方main-start
位于给定书写模式下块元起始布局的地方使用 display: flex
后,还会有其余一些事情发生。在这个系列的以后的文章里,我会好好讲解一下对齐。本文中,咱们先来看下使用 display: flex
后,使用的一些默认值。
注意: 对齐属性最开始起源于 Flexbox 规范。但正如 Flexbox 规范中解释的那样,Box Alignment 规范最终将取代 Flexbox 规范中定义的这些属性。
justify-content
的初始值是 flex-start
,就像咱们在 CSS 中这样声明了:
.container {
display: flex;
justify-content: flex-start;
}
复制代码
这就是为何 Flex 项目是从容器的起始边缘开始排列的缘由。而 row-reverse
则是调换了起始边缘与结束边缘,结束边缘变为主轴开始的地方。
当你看见以 justify-
前缀开头的属性时,说明它是控制 Flexbox 主轴上对齐的。justify-content
操做主轴对齐,全部 Flex 项目在开始处对齐。
除了 flex-star
,justify-content
还可以使用的值包括:
flex-end
center
space-around
space-between
space-evently
(在 Box Alignment 中添加)这些值用于分配 Flex 容器可用空间(available space)。这是项目移动和间隔的缘由。若是使用了 justify-content: space-between
,可用空间在项目之间平均分配,固然了,前提是有空间可供分配。若是 Flex 容器空间过窄(全部项目 布局完成后没有额外的空间了),justify-content
就不起任何做用了。
咱们能够设置 flex-direction
为 column
看下,此时 Flex 容器由于没有设置 height
,因此不存在剩余空间,justify-content: space-between
也不会起做用。若是你设置一个足够高的 height
,待全部项目 布局好后,由于还有剩余空间,就会看到效果。
See the Pen Smashing Flexbox Series 1: column with a height by Rachel Andrew
Flex 项目还能够在只有一行的 Flex 容器上,执行交叉轴对齐。这种对齐控制的是盒子们在这跟线上的对齐方式。下例中,有一个盒子的内容比其余的要多,而后其余盒子像被通知了同样伸展(stretch)到一样的高度。这是 align-items
属性初始值 stretch
在起做用:
See the Pen Smashing Guide to Layout: clearfix by Rachel Andrew
当你看见以 align-
前缀开头的属性时,说明它是控制 Flexbox 交叉轴上对齐的。align-items
操做交叉轴对齐,全部 Flex 项目在弹性线(flex line)内对齐。
除了 stretch
,align-items
还能够取的值包括:
flex-start
flex-end
center
baseline
若是不想要盒子伸展到最高那个的高度,能够设置 align-items: flex-start
。让项目在交叉轴的起始边缘对齐。
See the Pen Smashing Flexbox Series 1: align-items: flex-start by Rachel Andrew
Flex 项目是有初始设置的,以下:
flex-grow: 0
flex-shrink: 1
flex-basis: auto
就是说项目默认不会扩展(grow)来填充主轴上的可用空间。若是给 flex-grow
设置了一个正值,那么项目就会扩展剩余的空间。
项目的 flex-shrink
属性处置值为正值 1,表示能收缩(shrink)。也就是说,当 Flex 容器比较窄的时候,在没有任何溢出发生的状况下,项目会变得尽量小。这是一个明智的行为,通常来讲,咱们但愿盒子里的内容不要溢出。
为了默认可以获得很好地布局,flex-basis
初始值使用了 auto
。我会在之后的系列文章中解释这个属性的行为。你能够暂时把它认为是“大小刚恰好”(big enough to fit the content)。从页面表现上看的话,就是内容较多的那个项目分配到的空间会比内容少的要多。
See the Pen Smashing Flexbox Series 1: initial values of flex items by Rachel Andrew
这就是使用 Flexbox 带来的灵活性、设置了 flex-basis
为 auto
,在没有给项目设置额外大小限制的状况下爱,Flex 项目 有一个基础尺寸(base size)max-content
。这个宽度是指项目中的内容在彻底没有折行的状况下的长度。而后每一个项目会 在占据的基础尺寸的基础上,按比例拿走一部分空间,这在 flexbox 规范中有详情描述。
“注意: Flex shrink 因子分配负空间的时候,是在 Flex 项目的基础尺寸的基础之上增长的。最终分配的负空间多少,是根据因子值,按比例分配到每一个项目头上的。在大一点的项目 没有显著收缩以前,小的项目是不会收缩到零的。”
大一点的项目被抽取的空间相对(自身)来讲是少的。你能够比较下面两张图,第一张图里每一个项目 的内容量差很少,因此看起来差很少是同样宽的。在第二张图里,第三项目的内容比较多,结果看到它分配到了更多的空间。
内容多的项目分配到了更多的空间
Flexbox 在咱们没有使用更多属性的前提下,尽量的提供给咱们一个合理的布局结果。与一刀切平均分配每一个项目 同样的宽度、致使可能出现有内容多项目被挤压的很是高的状况不一样的是,弹性布局会给内容多的项目 分配更多的显示空间。这种行为是弹性布局最佳的使用场景。 弹性布局最擅长于以一种灵活和内容感知的方式——沿着一个轴——放置一组项目。本文到此只是稍微接触了一些皮毛,在本系列后面的文章中我会适当地讲解这些算法。
本文中,咱们讲解了弹性布局中使用到的一些初始值,解释了当咱们声明了 display: flex
的时候,实际发生了什么。一路分析下来,发现东西仍是不少的,文中涉及到几个属性牵涉到弹性布局的许多关键特性。
弹性布局如此灵活:默认状况下,它试图对内容作出正确选择——压缩或拉伸 Flex 项目以得到最佳的可读性。弹性布局还支持书写模式(writing mode):行和列的方向与所使用的书写模式相关。经过选择空间的分布方式,弹性布局容许将 Flex 项目做为一个组在主轴上对齐;咱们还能够在一个伸缩线(flex line)中对齐项目,在交叉轴上以彼此联系的方式移动 Flex 项目。重要的是,弹性布局能感知 Flex 项目的内容大小,会尝试在没有设置其余额外属性的状况下,来合理的分配空间给各个 项目。在之后的文章中,咱们将更深刻地讨论这些知识点,并作进一步分析什么时间以及为何去选择使用弹性布局。
(完)