8.2
主轴对齐 ―「justify-content」属性
8.3
侧轴对齐 ―「align-items」与「align-self」属性
8.4
堆栈伸缩行 ―「align-content」属性
8.5
伸缩容器的基线
9
伸缩布局算法
9.1
起始设定
9.2
决定一行长度
9.3
决定主轴长度
9.4
决定侧轴长度
9.5
主轴对齐
9.6
侧轴对齐
9.7
决定可伸缩长度
10
伸缩容器中的分页
11
一致性
12
属性列表
13
致谢
本章节不具有规范叙述
CSS 2.1 定义了四种布局模式 ― 由一个盒与其兄弟、祖先盒的关系决定其尺寸与位置的算法:
-
块布局 ― 为了呈现文档而设计出来的布局模式
-
行内布局 ― 为了呈现文本而设计出来的布局模式
-
表格布局 ― 为了用格子呈现 2D 数据而设计出来的布局模式
-
定位布局 ― 为了非常直接地定位元素而设计出来的布局模式,定位元素基本与其他元素毫无关系
本模块引入了新的布局模式:
伸缩布局
,是为了呈现复杂的应用与页面而设计出来的。
本章节不具有规范叙述
伸缩布局只与块布局有非常微薄的相似之处。伸缩布局不具有
浮动
或是
多栏
等等在块布局中可以用的复杂、面向文本/文档的属性,换来的是简单、强大的分配空间与对齐内容的工具,是 Web 应用与复杂的页面所需要的。一个伸缩容器的内容:
-
可以以任何
伸缩方向
(向左、向右、向下,甚至是向上!)配置
-
可以在样式层(也就是视觉顺序可以跟源码、语音顺序无关)
调换
、
重排
显示顺序
-
可以沿着单一(
主
)轴线性配置或是沿着第二(
侧
)轴
折行
-
可以因为可用空间的存在
扩展内容的尺寸
-
可以沿着容器或彼此
对齐
-
可以在保持
侧轴长度
不变之下动态
折叠
或反折叠
这时一个产品型录的例子,每个商品有品名、相片、描叙、购买按钮。设计师希望每个产品栏有相同的尺寸,相片要在文字叙述之上,而且不管商品的描叙有多长购买按钮要沿着底部对齐。伸缩布局让这个设计的很多部分的实现起来很简单:
-
产品型录可以用伸缩布局,让商品栏水平排列成一行一行,并让每一行的商品栏有相同的高度。每一个商品栏本生是一个竖排的伸缩容器,里面内容垂直排列。
-
在每一个商品栏里,源码里的内容以逻辑顺序排列:品名、叙述、相片,这为语音、非 CSS 浏览器提供了一个恰当的顺序。在一个视觉浏览器上,可以用「
order
」属性来把相片从内容的后面挪到顶部,并用「
align-self
」将相片水平置中。
-
不管每一个商品的叙述有多高,购买按钮上的
「
auto
」外边距
让按钮总是在商品栏里置底。
<style>
#deals {
display: flex; /* 应为是伸缩布局每一个商品有同样高度 */
flex-flow: row wrap; /* 让商品折行 */
.sale-item {
display: flex; /* 用伸缩布局配置每一个商品的描述 */
flex-flow: column; /* 垂直配置商品的内容 */
.sale-item > img {
order: -1; /* 将图像挪到其他内容之前(视觉顺序) */
align-self: center; /* 在侧轴(水平向)置中图像 */
.sale-item > button {
margin-top: auto; /* 自动顶端外边距让按钮置底 */
</style>
<section id='deals'>
<section class='sale-item'>
<h1>电脑初学者配备</h1>
<p>如果你的钱不够多,这是你可以买到的最好的电脑。
<li>电脑
<li>屏幕
<li>键盘
<li>鼠标
<img src='images/computer.jpg'
alt='你可以得到:一台白色的电脑与其他配备。'>
<button>下单!</button>
</section>
<section class='sale-item'>
</section>
</section>
Error creating thumbnail: Unable to save thumbnail to destination
电脑初学者配备
如果你的钱不够多,这是你可以买到的最好的电脑。
Error creating thumbnail: Unable to save thumbnail to destination
只能打印 ASCII art。
未包含墨水和纸。
图 1. 上面代码的可能渲染结果。
本模块扩展了「diplay
」属性 [CSS21],加了新的块级、行内级的显示形态,并定义了一种新的格式化上下文与控制其布局的属性。本模块也定义了「min-width
」与「min-height
」的新的初始值。本模块定义的所有属性皆不适用于「::first-line
」与「::first-letter
」伪元素。
本规范遵守 [CSS21] 的 CSS 属性定义常规。不在本规范定义的取值型态由层级样式表等级 2 更新版本 1 定义 [CSS21],其他 CSS 模组可扩充这些取值型态 ― 举例来说,同时使用 [CSS3VAL] 与本模组会扩充本规范使用的 <length>
取值型态的定义。
本规范定义的所有属性,除了在取值栏位列出的特定属性可使用的取值以外,还接受「inherit
」关键字作为属性值。为了规范的可读性不重复将该值列进取值栏位。
伸缩布局盒模型和术语
一个设有「display:flex
」或「display:inline-flex
」的元素是一个伸缩容器,伸缩容器的子元素被称为伸缩项目,这些子元素使用伸缩布局模型来排版。
与布局计算偏向使用书写模式方向的块布局与行内布局不同,伸缩布局偏向使用伸缩流的方向。为了让描述伸缩布局变得更容易,本章节定义一系列相对于伸缩流的术语。「flex-flow
」的值决定了这些术语如何对应到物理方向(上/右/下/左)、物理轴(垂直/水平)、物理大小(宽度/高度)。
Error creating thumbnail: Unable to save thumbnail to destination
图 2. 一个「row
」伸缩容器中各种方向与大小术语的示意图。
主轴、主轴方向
用户代理沿着一个伸缩容器的
主轴配置
伸缩项目,
主轴是
主轴方向的延伸。
主轴起点、主轴终点
伸缩项目的配置从容器的
主轴起点边开始,往
主轴终点边结束。
主轴长度、主轴长度属性
侧轴、侧轴方向
侧轴起点、侧轴终点
填满项目的伸缩行的配置从容器的侧轴起点边开始,往侧轴终点边结束。
侧轴长度、侧轴长度属性
display
flex | inline-flex
「flex
」
「inline-flex
」
伸缩容器会为其内容建立新的伸缩格式化上下文(flex formatting context)。除了使用伸缩排版而不块排版以外,伸缩格式化上下文与块级格式化上下文(block formatting context)根元素相同 ― 浮动不会闯入伸缩容器,且伸缩容器的边界不与其内容的边界叠加。
伸缩容器不是块容器,因此有些设计用来控制块布局的属性,在伸缩布局中不适用。特别是:
- 多栏(column)模块的所有「
column-*
」属性在伸缩容器上没有作用。
- 「
float
」与「clear
」在伸缩项目上没有作用。(However, the ‘float’ property still affects the computed value of ‘display’ on children of a flex container, as this occurs before flex items are determined.)
- 「
vertical-align
」在伸缩项目上没有作用。
若元素「display
」的指定值是「inline-flex
」且元素是一个浮动或绝对定位元素,则「display
」的计算值是「flex
」。也就是 CSS 2.1 章节 9.7 的表格增修「指定值」是「inline-flex
」、「计算值」是「flex
」的一行。
一个
伸缩容器的内容具有零个以上的
伸缩项目 ― 伸缩容器的每一个子元素(除了需要盒修复的元素之外)
Error creating thumbnail: Unable to save thumbnail to destination
都会成为一个
伸缩项目,且用户代理会将任何直接在伸缩容器里的连续文字块包起来成为匿名
伸缩项目。然而,若匿名
伸缩项目仅包含空白,则用户代理不会渲染该伸缩项目,如同将之视为「
display: none
」。
伸缩项目为其内容建立一个新的伸缩格式化上下文,这个格式化上下文的种类由项目「display
」的值决定。用户代理使用 CSS 2.1 章节 9.7 的表格决定伸缩项目「display
」的计算值。CSS 工作组预计会在未来的规范里引入伸缩容器的新的「display
」值,以取代这条叙述。
伸缩项目范例
Error creating thumbnail: Unable to save thumbnail to destination
:
<div style="display: flex">
<!-- 伸缩项目:块级子元素 -->
<div id="item1">块</div>
<!-- 伸缩项目:浮动元素 ― 用户代理会忽略浮动 -->
<div id="item2" style="float: left;">浮动</div>
<!-- 伸缩项目:包着行内内容的匿名块盒 -->
匿名项目 3
<!-- 伸缩项目:行内子元素 -->
<div id="item4">span</div>
<!-- 伸缩项目:<span> 变成 'display: block',所以没有行内块现象。-->
<div id=not-an-item>项目 5</div>
</span>
有些「display
」值会触发匿名盒的生成,举例来说,用户代理会在单独的「table-cell
」盒Error creating thumbnail: Unable to save thumbnail to destination
周围生成「table
」与「table-row
」元素。[CSS21] 这种修复必须在伸缩容器的子元素变成伸缩项目「之前」发生 ― 举例来说,若有两个相邻的「display: table-cell
」子元素,两个元素周围的匿名表格包裹盒会变成伸缩项目。
注:本规范预期让未来生成匿名容器(如「display:ruby
」)或会搅动盒树(「display:run-in
」)的显示型态造成的变化在决定伸缩项目之前发生。
绝对定位的伸缩子元素
伸缩容器的绝对定位子元素不参与伸缩布局的重新排序步骤之后的所有步骤。但是,若「left
」和「right
」的值均为「auto
」或者「top
」和「bottom
」的值均为「auto
」,则这些属性的使用值由绝对定位子元素的静态位置Error creating thumbnail: Unable to save thumbnail to destination
得来,如下:
若「left
」和「right
」的值均为「auto
」,则用户代理必须将绝对定位子元素在主轴起点方向Error creating thumbnail: Unable to save thumbnail to destination
或侧轴起点方向的外边(在水平轴上的那一个x)对齐到静态位置。若「top
」和「bottom
」的值均为「auto
」,则用户代理必须将绝对定位子元素在主轴起点方向或是侧轴起点方向的外边(在垂直轴上的那一个y)对齐到静态位置。
对于主轴方向Error creating thumbnail: Unable to save thumbnail to destination
:
- 若伸缩容器里没有伸缩项目,则静态位置由伸缩容器上的「
justify-content
」的值来决定,位置为假设一个大小为零的伸缩项目在此伸缩容器里的时候的位置。
- 否则,若绝对定位子元素的前一个伸缩项目不存在或者前一个伸缩项目与后一个伸缩项目在同一行,则静态位置是后一个伸缩项目在主轴起点边的外边。
- 否则,静态位置是前一个伸缩项目在主轴终点边的外边。
对于侧轴方向:
- 若绝对定位子元素的前一个伸缩项目存在,则静态位置是该项目所在伸缩行的侧轴起点边。
- 否则,静态位置是第一行伸缩行
Error creating thumbnail: Unable to save thumbnail to destination
的侧轴起点边。
注:这个定义的意图是要让静态位置差不多是一个匿名 0x0 的流内、
以「flex-start
」对齐的伸缩项目参与伸缩布局后的位置,主要的差别在于假想项目周围由「
justify-content: space-around
」与「
justify-content: space-between
」分配的空间被抑制了:假想项目跟下一个真项目(如果存在)间的空白,又或是假想项目跟前一个真项目(如果下一个真项目不存在)间的空白(被抑制了)
Error creating thumbnail: Unable to save thumbnail to destination
。
伸缩项目的外边界
相邻伸缩项目的边界不会叠加。「auto
」边界吸收在该方向多余的空间,因此可以用来对齐或是将相邻的伸缩项目隔开 ― 参见《用「auto
」边界对齐》。
伸缩项目的绘制
对于一个伸缩项目,就算「position
」是「static
」,不是「auto
」的「z-index
」值也会创建一个堆叠上下文。除此之外,伸缩项目的绘制与常规流中的块级元素无异。
注:注:一个伸缩项目的子嗣元素,就算定位在伸缩元素之外,仍参与伸缩项目建立的堆叠上下文。
伸缩容器的绝对定位子元素不是伸缩项目,但是这些子元素在原本盒子树的常规位置留下了「占位符」。这些占位符是宽、高、行高皆为「0
」的匿名行内盒,且占位符会成为伸缩项目。
伸缩容器绝对定位子元素的静止位置(当「top
」/「right
」/「bottom
」/「left
」属性为「auto
」时的位置)是对应的占位符在用户代理进行伸缩布局之后的最后位置。
注:在大部分情况下,上面叙述说明了绝对定位子元素对伸缩布局没有影响,但是当伸缩容器设有「justify-content: space-between
」或「justify-content: space-around
」 的时候则是例外,在这种情况下包着占位符的匿名伸缩项目会产生两个间隔空间(没有这个匿名项目的话只有一个),会造成两个「真」项目中间有两倍宽的间隔。
在伸缩项目上设定「visibility: collapse
」会让项目变成叠加伸缩项目,效果与表格栏或是表格列上的「visibility: collapse
」类似 ― 用户代理不会渲染叠加元素,但是项目会留下一个「支撑」使得伸缩行的侧轴长度维持稳定。因此,若伸缩容器只有一行伸缩行,动态叠加项目或取消叠加不会对伸缩容器的侧轴长度造成影响,也不会造成其他页面布局「摇晃」。但是,在叠加项目之后用户代理「会」重做伸缩行断行,所以具有多个伸缩行的伸缩容器的侧轴长度可能会变。
虽然用户代理不渲染叠加伸缩项目,这些项目还是会出现在格式化结构中,因此与「display: none
」项目不同 [CSS21],只靠元素出现在格式化结构就有的效果(如递增计数器或是运行动画、转场)在叠加项目上仍然有效。
为了计算「支撑」的尺寸,用户代理先假设项目未叠加并进行伸缩布局,然后将叠加项目用具有原来项目所在的伸缩行的侧轴长度的「支撑」替换并重新进行伸缩布局。《伸缩布局算法》有「visibility: collapse
」如何与伸缩布局互动的规范性叙述。
注:请注意在任何伸缩项目上使用「visibility: collpase
」会让用户代理执行伸缩布局算法的时候重复最费时的几个步骤。若项目不会需要动态叠加、取消叠加,本规范建议网页作者继续使用「display: none
」来隐藏项目,因为对于布局引擎来说这样比较有效率。
伸缩项目的默认最小长度
为了让伸缩项目有合理的最小长度,本规范为 CSS 2.1 定义的「min-width
」与「min-height
」属性增加一个新的「auto
」值作为这些属性的初始值。[CSS21]
min-width, min-height
新初始值:
新计算值:
指定的百分比或绝对长度抑或关键词
「auto
」
当使用在伸缩项目的最小主轴长度属性的时候,本关键词代表最小主轴长度是最小内容长度,以帮助确保项目够大到足以容纳其内容。
注:CSS 工作组预计在定义「
min-content
」关键词(
书写模式附录 D)的规范足够成熟时,在这种情况让「
auto
」的计算值成为「
min-content
」。
译者按,例如:
<div style="min-width: auto; width: 0">内容</div> <!-- 此时min-width计算值为「0」-->
<div style="display: flex;"><div style="min-width: auto; width: 0">内容</div></div> <!-- 此时min-width的计算值就是内容的最小宽度。-->
否则,(除非未来规范描述别的行为)本关键字的计算值为「0
」。
注:请注意虽然基于内容的最小尺寸通常可以避免内容重叠或是内容溢出伸缩项目,但在某些情况这是不适当的:
如果要在文档的主要内容区域使用伸缩布局,最好也设置相对于字体的最小宽度,如「min-width: 12em
」。基于内容的最小宽度会导致网页里有大型表格或图像的时候,整个内容区域扩展以至于溢出窗口,使得一行文本过长、难读。
请也注意在含有大量内容的项目上设置基于内容的最小尺寸会让布局引擎必须遍历项目的所有内容方可找到项目的最小尺寸,而在网页作者设置明确的最小值时不须要这种遍历程序。(然而,对于含有小量内容的伸缩项目,这种遍历并不会造成效能问题。)
排序与方向
伸缩容器的内容可以用任何方向与任何顺序进行布局,这让网页作者轻松地达到之前需要复杂、不牢靠的「float
」与「clear
」属性才可以实现的效果。这个功能透过「flex-direction
」、「flex-wrap
」与「order
」属性呈现。
网页作者不应该使用这些技术替代正确的文档排序,因为这会破坏文档的无障碍性。
flex-direction
row
| row-reverse
| column
| column-reverse
(不适用)
「flex-direction
」属性可以用来设定伸缩容器的主轴的方向,这也决定了用户代理配置伸缩项目的方向。
「row
」
「row-reverse
」
「column
」
「column-reverse
」
flex-wrap
nowrap
| wrap
| wrap-reverse
nowrap
(不适用)
「flex-wrap
」属性控制伸缩容器是单行还是多行,也决定了侧轴方向 ― 新的一行的堆放方向。
「nowrap
」
「wrap
」
「wrap-reverse
」
flex-flow
<「
flex-direction
」>
|| <「
flex-wrap
」>
参见各属性
参见各属性
(不适用)
参见各属性
「flex-flow
」属性是同时设定「flex-direction
」与「flex-wrap
」属性的缩写,两个属性决定了伸缩容器的主轴与侧轴。
一些合法伸缩流的例子:
Error creating thumbnail: Unable to save thumbnail to destination
div { flex-flow: row; }
/* 初始值。主轴是行内方向,
没有换行。 */
Error creating thumbnail: Unable to save thumbnail to destination
div { flex-flow: column wrap; }
/* 主轴是块的方向,换行往行
内方向。在英文页面里,主
轴是上往下,往右换行。 */
Error creating thumbnail: Unable to save thumbnail to destination
div { flex-flow: row-reverse wrap-reverse; }
/* 主轴与行内方向相反(右到左)。
新行换行向上。 */
默认状态下,用户代理会用伸缩项目出现在源文档的次序配置这些伸缩项目。「order
」属性可以用来改变这个顺序。
order
<number>
(不适用)
「order
」属性透过将元素分到有序号的组以控制元素出现的顺序。在伸缩布局中,「order
」属性控制伸缩项目在伸缩容器里的顺序。
伸缩容器会从序号最小的组开始布局,在同一个组里的项目依在源文档里的次序布局,这也影响了着画次序 [CSS21],正如同在文件中元素已经改变次序一般。
「order
」属性必不可影响非视觉媒介(像是语音)里的次序。这让网页作者可以用具有逻辑次序的内容满足线性呈现内容的非视觉媒介与非 CSS 用户代理,同时用「order
」重新排列内容的视觉顺序。
除非有别的规范说明,本属性在不是伸缩项目的元素上没有效果。
下图显示了一个使用中的模板总是在最前面的简单卷标接口:
这可以由以下 CSS 实作(仅显示部份相关程序代码):
.tabs {
display: flex;
.tabs > .current {
order: -1; /* 比预设值 0 要小 */
很多 Web 页面在 HTML 里有很相似的构造,在上面有一个标题,下面一个批注,一个内容区块跟一个或两个在中间的额外字段。一般来说,内容出现在页面原始码的前面(在额外的字段之前)比较好。然而,这让很多一般的设计很难达成,像是把字段摆在内容区块的两边。多年以来这种俗称「圣杯布局」的两个额外字段的布局已经有很多种方法完成了,然而「order
」让这种布局轻而易举。以下面的页面程序代码草图与预期布局为例:
Error creating thumbnail: Unable to save thumbnail to destination
<!DOCTYPE html>
<header>...</header>
<div id='main'>
<article>...</article>
<nav>...</nav>
<aside>...</aside>
<footer>...</footer>
这种布局可以很简单地由伸缩布局达成:
#main { display: flex; }
#main > article { flex:1; order: 2; }
#main > nav { width: 200px; order: 1; }
#main > aside { width: 200px; order: 3; }
更棒的是,预设下这些字段是等高的,而且主要内容会根据屏幕大小尽可能宽。另外,也可以跟媒体查询结合,在窄屏幕的状况下使用垂直布局:
@media all and (max-width: 600px) {
/* 要放三个字段太窄了 */
#main { flex-flow: column; }
#main > article, #main > nav, #main > aside {
/* 回到文件顺序 */
order: 0; width: auto;
(用多行伸缩容器实现智能换行就当作是给读者的习题。)
注:CSS 工作组预计在未来的布局模式(如网格线布局)中也让「
order
」有类似的效果。
伸缩容器可以是单行的,也可以是多行的,这由「flex-wrap
」属性决定:
- 单行的伸缩容器会将其所有子元素在单独的一行上进行布局,即便这可能导致内容溢出。
- 多行的伸缩窗口会将其伸缩项目配置在多个伸缩行上,这类似于文本的排列:当文本过宽导致一行无法容纳时,内容会断开并移至新的一行。当用户代理创建新的伸缩行时,这些伸缩行会根据「
flex-wrap
」属性沿着侧轴进行堆叠。除非伸缩容器本身是空的,每一个伸缩行至少包含一个伸缩项目。
在本示例中的四个按钮如果完全并排会放不下。
<style>
#flexbox {
display: flex;
flex-flow: row wrap;
width: 300px;
.item {
width: 80px;
</style>
<div id="flexbox">
<div class='item'>1</div>
<div class='item'>2</div>
<div class='item'>3</div>
<div class='item'>4</div>
由于容器的宽度是 300px,同一行上仅能放得下三个项目,这三个项目占用了 240px,剩余空间为 60px。由于「flex-wrap
」属性让伸缩容器变为多行伸缩容器(因为使用了「wrap
」关键字),伸缩容器会多创建一个伸缩行来放置最后一个项目。
Error creating thumbnail: Unable to save thumbnail to destination
图 4. 多行伸缩容器的渲染示例。
用户代理将内容分布到不同的行之后,每一行单独进行布局:可伸缩长度的计算以及「justify-content
」、「align-self
」的效果计算每次仅考虑单独一个伸缩行上的项目。
当一个伸缩容器有多个伸缩行时,每一行的侧轴长度为可容纳该行中的所有伸缩项目(依据「align-self
」属性进行对齐之后)的最小值,这些伸缩行依据「align-content
」属性在伸缩容器中进行对齐。当伸缩容器(单行或多行)只有单独一行伸缩行时,这一行的侧轴长度为伸缩容器的侧轴长度,在这种情形下「align-content
」属性没有效果。一行的主轴长度始终和伸缩容器内容盒的主轴长度相同。
这一示例与上一示例相同,唯一的区别是伸缩项目拥有「flex: auto
」样式。因为第一行的剩余空间为 60px 且所有项目有相同的可伸缩性,所以三個項目均額外獲得寬度 20px 而變為寬度 100px。由于剩余的项目自己单独在一行伸缩行中,它会扩展到整个伸缩行,即宽度 300px。
Error creating thumbnail: Unable to save thumbnail to destination
图 5. 与上一示例相同,但所有项目设有「flex: auto
」。
伸缩布局决定性的特性是让伸缩项目「可伸缩」,也就是让伸缩项目的宽度或高度自动填充剩余的空间。这可以以「flex
」属性完成。一个伸缩容器会等比地按照各伸缩项目的扩展比率分配剩余空间,也会按照收缩比率缩小各项目以避免溢出。
none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
参见各属性
参见各属性
(不适用)
参见各属性
参见各属性
「flex
」属性可以用来指定可伸缩长度的部件:扩展比率、收缩比率,以及伸缩基准值。当一个元素是伸缩项目时,「flex
」属性将代替主轴长度属性决定元素的主轴长度。若元素不是伸缩项目,则「flex
」属性没有效果。
<'flex-grow'>
此
<number>
部件可以用来设置「
flex-grow
」
长写并指定
扩展比率,也就是剩余空间是正值的时候此
伸缩项目相对于伸缩容器里其他
伸缩项目能分配到空间比例。若省略了此部件,则它会被设为「
1
」。
<'flex-shrink'>
<'flex-basis'>
Error creating thumbnail: Unable to save thumbnail to destination
图 6. 一个显示「绝对」伸缩(以零为基准值开始)与「相对」伸缩(以项目的内容大小为基准值开始)差异的图解。这三个项目的伸缩比例分别是「1
」、「1
」、「2
」。
「none
」
关键字「
none
」的计算值为「
0 0 auto
」。
「flex
」的各部件的初始值等同于「flex: 0 1 auto
」。
用户代理必须将一个前面没有两个伸缩比例的无单位零解读成一个伸缩比例。为避免用户代理错误解读或是写出不合法的宣告,网页作者必须为是零的 <flex-basis>
部件指定一个单位或是在前面摆两个伸缩比例。
本章节不具备规范意义。
下表总结了「flex
」属性常见值的效果:
「flex: 0 auto
」
「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 0px
」相同。该值使元素可伸缩,并将
伸缩基准值设置为零,导致该项目会根据设置的比率占用伸缩容器的剩余空间。如果一个伸缩容器里的所有项目都使用此模式,则它们的尺寸会正比于指定的伸缩比率。
默认状态下,伸缩项目不会收缩至比其最小内容尺寸(最长的英文词或是固定尺寸元素的长度)更小。网页作者可以靠设置「min-width
」或「min-height
」属性来改变这个默认状态。(参见《伸缩项目的默认最小长度》。)
可伸缩性的部件
网页作者也可以用单独的长写属性控制可伸缩性的各个部件。
注:本规范鼓励网页作者使用「
flex
」缩写来控制可伸缩性,而不是使用单独的属性,因为「
flex
」缩写会在最
常见的情景正确的重置未指定的部件值。
flex-grow
<number>
(不适用)
是,除了在「0
」与其他值之间转变以外。
「flex-grow
」属性可以用来设置扩展比率。负值不合法。
flex-shrink
<number>
(不适用)
是,除了在「0
」与其他值之间转变以外。
「flex-shrink
」属性可以用来设置收缩比率。负值不合法。
flex-basis
<'width'>
相对与伸缩容器的内-主轴长度
除了将长度边为绝对长度以外,同指定值。
是,只要「width
」是可动画的。
「flex-basis
」属性可以用来设置伸缩基准值。负长度不合法。
除了会去截取主轴长度属性的「auto
」值以外,在横向书写模式中,「flex-basis
」的值的解出方法与「width
」相同 [CSS21]:若「flex-basis
」的值是一个百分比,则此百分比由伸缩项目的包含快(也就是伸缩容器)解出,且若该包含块的尺寸不明确,则解出结果未定义。同样的,除非「box-sizing
」[CSS3UI] 等等的其他属性指定了别的行为,「flex-basis
」决定内容盒的尺寸。
在一个伸缩容器的内容完成伸缩,而所有伸缩项目的大小确定后,伸缩项目可以在可伸缩容器中进行对齐。
「margin
」属性可以用来对齐这些项,这类似于在块布局的行为,但要更加强大。伸缩项目同时也识别盒对齐标准中的对齐相关的属性,这些属性提供了基于关键字的对齐方式,在主轴和辅轴上均可使用。这些属性让一些如包括水平、垂直居中等等在 CSS 2.1 中很难实现的布局成为小菜一碟。
注:虽然对齐相关的属性是在《盒对齐》规范中定义的,但是《可伸缩盒布局》为避免对《盒对齐》产生依赖从而减缓标准的进步速度,在这里重新定义了相关属性。在《盒对齐》完成并定义这些属性用于其他类型的布局模式时的效果前,本标准定义的这些属性将只用于伸缩布局。
用「auto
」外边距对齐
本章节不具规范意义。外边距对伸缩项目的影响的规范叙述在《可伸缩布局算法》一章。
在伸缩项目上,以「auto
」为值的外边距,非常类似于普通流中的自动外边距:
- 在计算伸缩基准值和伸缩长度时,自动外边距相当于「
0
」。
- 在使用「
justify-content
」和「align-self
」控制对齐前,所有正值的空间会在对应维度上被自动外边距平均分配。
- 在已要溢出的元素上,自动外边距没有作用,元素会往 “尾”/“脚” 边溢出。
注:需要注意的是,如果空间被自动外边距平均分配了,则对齐相关的属性在这一维度上没有作用,因为外边距偷走了伸缩后所有的可用空间。
一种比较常见的使用 「auto
」作为「margin
」属性的值的场景是,将伸缩项目分为多个独立的 “组”。以下示例展示了使用这一方案来实现一个常用的UI模式 ― 一个包含多个动作按钮的横条,其中一部分在左边,另一部分在右边。
图7 下面是代码示例。
<style>
nav > ul {
display: flex;
nav > ul > #login {
margin-left: auto;
</style>
<li><a href=/about>关于</a>
<li><a href=/projects>项目</a>
<li><a href=/interact>交互</a>
<li id='login'><a href=/login>登入</a>
下图展示了在有溢出的情况下,使用「auto
」值作为「margin
」,以及使用对齐相关属性控制跨轴的对齐时的差异。
图8 左图中的元素使用边距进行居中,而右图的则使用「align-self
」进行居中。如果该列放在页面的左边,则边距的行为会更符合预期,因为那个较长的元素将保持完全可读。在其他情况下,真正的居中行为会产生更好的效果。
justify-content
flex-start | flex-end | center | space-between | space-around
flex-start
可伸缩容器
(不适用)
「justify-content
」属性用于在主轴上对齐伸缩项目。这一行为会在所有可伸缩长度及所有自动边距均被解释后进行。当一行上的所有伸缩项目都不能伸缩或可伸缩但是已经达到其最大长度时,这一属性才会对多余的空间进行分配。当项目溢出某一行时,这一属性也会在项目的对齐上施加一些控制。
flex-start
flex-end
center
伸缩项目向一行的中间位置靠齐。该行的
伸缩项目将相互对齐并在行中居中对齐,同时第一个项目与该行的在
主轴起点的边的距离等同与最后一个项目与该行在
主轴终点的边的距离(如果剩余空间是负数,则保持两端溢出的长度相等)。
space-between
space-around
伸缩项目会平均地分布在行里,两端保留一半的空间。如果剩余空间是负数,或该行只有一个
伸缩项目,则该值等效于「
center
」。在其它情况下,
伸缩项目在确保两两之间的空白空间相等,同时第一个元素前的空间以及最后一个元素后的空间为其他空白空间的一半下平均分布。
Error creating thumbnail: Unable to save thumbnail to destination
图9 通过伸缩容器中的三个不同颜色的项目,展示五种「justify-content
」关键字的效果。
align-items
flex-start | flex-end | center | baseline | stretch
stretch
可伸缩容器
(不适用)
align-self
auto | flex-start | flex-end | center | baseline | stretch
(不适用)
如果值为「auto
」,则计算值为父元素的「align-items
」值,否则为指定值。
伸缩项目可以在伸缩容器的当前行的侧轴上进行对齐,这类似于「justify-content
」属性,但是是另一个方向。「align-items
」可以用来设置伸缩容器中包括匿名伸缩项目的所有项目的对齐方式。「align-self
」则用来在单独的伸缩项目上覆写默认的对齐方式。(对于匿名伸缩项目,「align-self
」的值永远与其关联的伸缩容器的「align-items
」的值相同。)
若伸缩项目的任一个侧轴上的外边距为「auto
」,则「align-self
」没有效果。
如果「align-self
」的值为「auto」,则其计算值为元素的父元素的「align-items
」值,如果该元素没有父元素,则计算值为「stretch
」。对齐属性值的定义如下:
「flex-start」
「flex-end」
「center」
「baseline」
「stretch」
如果
侧轴长度属性的值为「
auto
」,则此值会使项目的外边距盒的尺寸在遵照「
min/max-width/height
」属性的限制下尽可能接近所在行的尺寸。
注:注意:如果伸缩伸缩的高度有限制,此可能导致
伸缩项目的内容溢出该项目。
伸缩项目在
侧轴起点边的外边距会紧靠住该行在
侧轴起点的边。
Error creating thumbnail: Unable to save thumbnail to destination
图10 通过伸缩容器中的四个不同颜色的项目,展示五种「align-items
」关键字效果
align-content
flex-start | flex-end | center | space-between | space-around | stretch
stretch
多行伸缩容器
(不适用)
当伸缩容器的侧轴还有多余空间时,「align-content
」属性可以用来调准伸缩行在伸缩容器里的对齐方式,这与调准伸缩项目在主轴上对齐方式的「justify-content
」属性类似。请注意本属性在只有一行的伸缩容器上没有效果。各属性值的意义如下:
「flex-start」
各行向伸缩容器的起点位置堆叠。伸缩容器中第一行在
侧轴起点的边会紧靠住伸缩容器在
侧轴起点的边,之后的每一行都紧靠住前面一行。
「flex-end」
各行向伸缩容器的结束位置堆叠。伸缩容器中最后一行在
侧轴终点的边会紧靠住该伸缩容器在
侧轴终点的边,之前的每一行都紧靠住后面一行。
「center」
各行向伸缩容器的中间位置堆叠。各行两两紧靠住同时在伸缩容器中居中对齐,保持伸缩容器在
侧轴起点边的内容边和第一行之间的距离与该容器在
侧轴终点边的内容边与第最后一行之间的距离相等。(如果剩下的空间是负数,则行的堆叠会向两个方向溢出的相等距离。)
「space-between」
各行在伸缩容器中平均分布。如果剩余的空间是负数或伸缩容器中只有一行,该值等效于「
flex-start
」。在其它情况下,第一行在
侧轴起点的边会紧靠住伸缩容器在
侧轴起点边的内容边,最后一行在
侧轴终点的边会紧靠住伸缩容器在
侧轴终点的内容边,剩余的行在保持两两之间的空间相等的状况下排列。
「space-around」
各行在伸缩容器中平均分布,在两边各有一半的空间。如果剩余的空间是负数或伸缩容器中只有一行,该值等效于「
center
」。在其它情况下,各行会在保持两两之间的空间相等,同时第一行前面及最后一行后面的空间是其他空间的一半的状况下排列。
「stretch」
各行将会伸展以占用剩余的空间。如果剩余的空间是负数,该值等效于「
flex-start
」。在其它情况下,剩余空间被所有行平分,扩大各行的侧轴尺寸。
注:注意:只有多行的伸缩容器才会在侧轴上有多余的空间以供对齐,因为仅包含一行的伸缩容器中,唯一的一行会自动伸展填充全部的空间。
Error creating thumbnail: Unable to save thumbnail to destination
图11 展示「align-content
」各关键字对多行的伸缩容器的效果。
伸缩容器的基线
一个伸缩容器的基线由以下步骤决定:
伸缩布局算法
本章节涵盖了具有规范性的算法,详述伸缩容器与其内容布局的准确行为。算法以容易阅读的方式呈现,并不一定是最有效率的算法。用户代理可使用任何想用的算法,但是产生结果必须与这里的算法一致。
注:本章节的目标读者为实作者。除非某网页作者具有追根究柢的企图心,了解神秘的 CSS 布局的渴望,否则网页作者应该可以从各个单独的属性解释找到要查的东西。
在以下算法中,明确尺寸是指不需要靠测量内容决定的大小:例:<length>、初始包含块的大小、一个靠明确尺寸决定的 <percentage>。不明确尺寸是指不明确的大小。
以下各小节描述了布局一个伸缩容器与其内容的算法。
生成匿名伸缩项目:依《伸缩项目》小节的描述。
根据「order
」重新排序伸缩项目。有最小(负值最大)「order
」的伸缩项目排在第一个。若有多个项目有相同的「order
」值,这些项目照文件顺序排。这个步骤影响了伸缩项目生盒树成的盒子的顺序,也影响了后面的算法如何处理各项目。
决定一行长度
- 决定伸缩项目可用的主、侧轴空间。对于主、侧两个方向,若伸缩容器的在那个方向具有明确尺寸,使用该长度。否则,从该方向中伸缩容器的可用空间中减去边界、边框与边距并使用该值。这个结果可能是无限大。
决定各项目的「伸缩基准长度」与「假定主轴长度」:
- 若项目具有明确伸缩基准值,该值为伸缩基准长度。
- 否则,若伸缩容器的主轴与项目的行内轴平行,使用可用空间与项目的伸缩基准值,除非项目的书写模式与伸缩容器的书写模式垂直(在这种情况下使用垂直流中的盒的规则 [CSS3-WRITING-MODES]),将伸缩基准值的「
auto
」视为是「max-content
」。若伸缩基准直是「fill-available
」或「fit-content
」,且伸缩容器的主轴长度以「min-content
」或「max-content
」限制决定大小,则也使用该限制决定项目的长度。伸缩基准长度为项目的 measure。
- 否则,使用可用空间与项目的伸缩基准值(若项目不可伸缩)或「
auto
」,除非项目的书写模式与伸缩容器的书写模式垂直(在这种情况下使用垂直流中的盒的规则 [CSS3-WRITING-MODES]),将伸缩基准值的「auto
」视为是「max-content
」。若伸缩基准直是「auto
」、「fill-available
」或「fit-content
」,且伸缩容器的侧轴长度以「min-content
」或「max-content
」限制决定大小,则也使用该限制决定项目的长度。伸缩基准长度为项目的 max-content extent。
- 项目的伸缩基准长度截至其最大、最小值(透过主轴长度属性)即为假定主轴长度。
- 决定伸缩容器的主轴长度:使用其主轴长度属性。在本计算中,伸缩容器的最小内容主轴长度是所有伸缩容器里伸缩项目的「最小内容长度贡献」的最大值,伸缩容器的最大内容主轴长度是所有伸缩容器里伸缩项目的「最大内容长度贡献」的和。一个项目的「最小/最大内容长度贡献」是当项目以「
min-content
」或「max-content
」限制决定大小时,项目的外-假定主轴长度。在这个计算中,用户代理会将「auto
」边界视为「0
」。
决定主轴长度
搜集伸缩项目成伸缩行:
- 若伸缩容器为单行,则搜集所有弹性项目至单个伸缩行。
- 否则,从第一个未搜集进来的项目开始,搜集尽可能多的连续伸缩项目直到伸缩容器的内主轴长度不够或遇见强制中断(不过至少搜集一个)进一个伸缩行。CSS2.1「
page-break-before/after
」[CSS21] 或 CSS3「break-before/after
」[CSS3-BREAK] 属性设有分段中断时,用户代理会强制断点的发生。
在本步骤中,伸缩项目的长度是外-假定主轴长度。
重复直到收集了所有伸缩项目。
注:除非主轴长度为零的项目在伸缩容器的开头,这些项目不可能是一个行开头。尽管前一行的最后一个非零项目已经「填满」了前一行,「尽可能收集」会把主轴长度为零的项目搜集进前一行的尾端。
决定可伸缩长度:决定所有伸缩项目的可伸缩长度以找到项目主轴长度的使用值,并由伸缩项目的主轴长度决定其「假定侧轴长度」。
决定侧轴长度
计算各伸缩行的侧轴长度。
若伸缩容器仅有单一行(尽管容器是多行伸缩容器),则伸缩行的侧轴长度是伸缩容器的内-侧轴长度。
否则,对于各伸缩行:
- 搜集所有行内轴与主轴平行,且「
align-self
」是「baseline
」,且侧轴的边界都不为「auto
」。找出项目基线与假定外-侧轴起点边的最大距离,找出项目基线与假定外-侧轴终点边的最大距离,并将两个值相加。
- 在所有没被前一个步骤搜集的项目中,找出最大的外-假定侧轴长度。
- 伸缩行侧轴长度的使用值事前两步骤找到的值中较大的那一个。
处理「align-content: stretch
」。若伸缩容器具有明确的侧轴长度,且「align-content
」,且伸缩行侧轴长度的总和小于伸缩容器的内-侧轴长度,则给各伸缩行增加相同的侧轴长度,使得侧轴长度的总和刚好与伸缩容器的内-侧轴长度相等。
叠加「visibility: collapse
」项目。若有「visibility: collapse
」的伸缩项目,记下项目所在的行的侧轴长度为项目的支撑长度,并从头开始重新布局。
在第二轮布局中,当进行搜集伸缩项目成伸缩行步骤的时候,将已叠加项目的主轴长度当作是零。在该步骤之后的剩下的算法步骤里,完全忽略已叠加的项目(将这些视为「display: none
」),但是在计算各伸缩行的侧轴长度的步骤之后,若有任何一行的侧轴长度小于在该行所有已叠加的项目里最大的支撑长度,将该行的侧轴长度设为该支撑长度。
在第二轮布局中跳过本步骤
决定各伸缩项目侧轴长度的使用值。若伸缩项目设有「align-self: stretch
」,且其侧轴长度属性是「auto
」,且其侧轴边界都不是「auto
」,则外-侧轴长度的的使用值是其伸缩行的侧轴长度截至最大、最小值(透过侧轴长度属性)的结果。否则,侧轴长度的使用值是项目的假定侧轴长度。
分配剩下的空间。对于各伸缩行:
- 若剩下的空间为正且在这行中至少有一个主轴边界是「
auto
」,将剩下的空间平均分配给这些边界。否则,将所有「auto
」边界设为零。
- 按照「
justify-content
」进行沿着主轴的项目对齐。
- 决定侧轴「
auto
」边界。若某个伸缩项目有「auto
」侧轴边界,且其(将「auto
」边界视为零)外-侧轴长度小于其伸缩行的侧轴长度,将长度的差异平均分配给「auto
」边界。
- 沿着侧轴对齐所有的伸缩项目:若项目的两个侧轴边界都不为「
auto
」,按照「align-self
」对齐该伸缩项目。
决定伸缩容器侧轴长度的使用值:
- 若侧轴长度属性有明确大小,使用该值。
- 否则,使用各伸缩行的侧轴长度的总和。
- 对齐所有伸缩行:按照「
align-content
」对齐所有伸缩行。
决定可伸缩长度
使用以下步骤决定伸缩行里项目的可伸缩长度:
- 决定使用哪个伸缩比例。先求目标行里所有项目外-假定主轴长度的总和。若总和小于伸缩容器的内主轴长度,则在本算法之后的部份使用扩展比率。否则,使用收缩比率。
- 决定不可伸缩项目的大小。对于任何伸缩比率为零的项目,设项目主轴长度的使用值为项目的假定主轴长度。
- 确认可否配置空间。若所有目标行里的伸缩项目都要不是被冻结要不是伸缩比率为零,则结束本算法。
- 计算可配置空间。先求目标行里所有项目外-伸缩基准长度的总和,将伸缩容器的内主轴长度剪掉总和,即为可配置空间。
配置正比于伸缩比例的空间。若可配置空间的正负号与选择伸缩比率的正负号相同,配置正比于项目伸缩比率的空间到可伸缩项目主轴长度里:
若可配置空间为正
找出项目扩展比率与目标行里项目的扩展比率总和的比率。将项目的主轴长度设为伸缩基准长度加可配置空间里占有的部份(使用前面算出的比率)。
若可配置空间为负
对于每一个在目标行的项目,将收缩比率乘上外-伸缩基准长度,将这个值记为正规化收缩比率。找出项目正规化收缩比率与目标行里项目的正规化收缩比率总和的比率。将项目的主轴长度设为伸缩基准长度减可配置空间里占有的部份(使用前面算出的比率)。请注意得到的内主轴长度可能是负的 ― 下一个步骤会校正这个问题
修复最大、最小违规。将项目的主轴长度截至其最大、最小值(透过主轴长度属性)。若项目的主轴长度变小,则这是最大违规。若项目的主轴长度变大,则这是最小违规。
总违规事前一个步骤所有调整的总和(截至其最大、最小后的长度 - 未截至其最大、最小后长度)。若总违规为:
冻结所有最小违规,重设所以其它项目到进入本算法的大小,并回到本算法的步骤 2。
冻结所有最大违规,重设所以其它项目到进入本算法的大小,并回到本算法的步骤 2。
伸缩容器中的分页
align-content
flex-start | flex-end | center | space-between | space-around |
stretch
stretch
multi-line flex containers
align-items
flex-start | flex-end | center | baseline | stretch
stretch
flex containers
align-self
auto | flex-start | flex-end | center | baseline | stretch
flex items
display