Warning:
This wiki has been archived and is now read-only.

Css3-flexbox

From HTML5 Chinese Interest Group Wiki
Jump to: navigation, search

介紹

伸縮布局模型

一個設有 ‘display:flex’ 或 ‘display:inline-flex’ 的元素是一個伸縮容器,伸縮容器的子元素被稱為為伸縮項目,這些子元素使用伸縮布局模型來排版。

與布局計算偏向使用書寫模式方向的塊布局與行內布局不同,伸縮布局偏向使用伸縮流方向。為了讓描述伸縮布局變得更容易,本章節定義一系列相對於伸縮流的術語。‘flex-flow’ 的值決定了這些術語如何對應到物理方向(頂/右/底/左)、物理軸(垂直/水平)、物理大小(寬度/高度)。

Error creating thumbnail: Unable to save thumbnail to destination

圖 2. 一個 ‘row’ 伸縮容器中各種方向與大小術語的示意圖。

主軸、主方向

使用者代理沿著一個伸縮容器的主軸配置伸縮項目主軸主方向的延伸。

主始、主結

伸縮項目的配置從容器的主始邊開始,往主結邊結束。

主長度、主長度屬性

伸縮項目的在主方向的寬度或高度就是項目的主長度伸縮項目主長度屬性是 ‘width’ 或 ‘height’ 屬性,由哪一個對著主方向決定。

側軸、側方向

主軸垂直的軸稱作側軸,是側方向的延伸。

側始、側結

填滿項目的伸縮行的配置從容器的側始邊開始,往側結邊結束。

側長度、側長度屬性

伸縮項目的在側方向的寬度或高度就是項目的側長度伸縮項目側長度屬性是 ‘width’ 或 ‘height’ 屬性,由哪一個對著側方向決定。

伸縮容器 ― ‘display’ 值 ‘flex’ 與 ‘inline-flex

名稱: display
新值: flex | inline-flex

flex

這個值讓元素產生塊級伸縮容器盒。

inline-flex

這個值讓元素產生行內級伸縮容器盒。

伸縮容器會為其內容建立新的伸縮格式化上下文。除了使用伸縮排版而不塊排版以外,伸縮格式化上下文與塊格式化上下文根元素相同 ― 浮動不會闖入伸縮容器,且伸縮容器的邊界不與其內容的邊界折疊。

伸縮容器不是塊容器,因此有些設計用來控制塊布局的屬性在伸縮布局中不適用。特別是:

  • 多欄模組的所有 ‘column-*’ 屬性在伸縮容器上沒有作用。
  • float’ 與 ‘clear’ 在伸縮項目上沒有作用。
  • 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’ 值,以取代這條敘述。
範例二

伸縮項目範例:

<div style="display: flex">

    <!-- 伸縮項目:塊級子元素 -->
    <div id="item1">塊</div>

    <!-- 伸縮項目:浮動元素 ― 使用者代理會忽略浮動 -->
    <div id="item2" style="float: left;">浮動</div>

    <!-- 伸縮項目:包著行內內容的無名塊盒 -->
    無名項目 3

    <!-- 伸縮項目:行內子元素 -->
    <div id="item4">span</div>

    <!-- 伸縮項目:<span> 變成 'display: block',所以沒有行內塊現象。-->
    <span>
        項目 5
        <div id=not-an-item>項目 5</div>
        項目 5
    </span>
</div>

有些 ‘display’ 會觸發無名盒的生成,舉例來說,使用者代理會在單獨的 ‘table-cell’ 盒周圍生成 ‘table’ 與 ‘table-row’ 元素[CSS21] 這種修復必須在伸縮容器的子元素變成伸縮項目「之前」發生 ― 舉例來說,若有兩個相鄰的 ‘display: table-cell’ 子元素,兩個元素周圍的無名表格包裹盒會變成伸縮項目

注:本規範預期讓未來生成無名容器(如 ‘display:ruby’)或會攪動盒樹(‘display:run-in’)的顯示型態造成的變化在決定伸縮項目之前發生。

伸縮項目的邊界

相鄰伸縮項目的邊界不折疊。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
新初始值: auto
新計算值: 指定的百分比率或絕對長度或關鍵字

auto

當使用在伸縮項目的最小主長度屬性的時候,本關鍵字代表最小主長度是最小內容長度。
注:CSS 工作組預計在定義 ‘min-content’ 關驗字(書寫模式附錄 D)的規範足夠成熟時,在這種情況讓 ‘auto’ 計算為 ‘min-content’。
否則,(除非一個的未來規範描述別的行為)本關鍵字計算為 ‘0’。

排序與方向

伸縮容器的內容可以用任何方向與任何順序進行布局,這讓網頁作者輕鬆地達到之前需要複雜、不牢靠的 ‘float’ 與 ‘clear’ 屬性才可以實現的效果。這個功能透過 ‘flex-direction’、‘flex-wrap’ 與 ‘order’ 屬性呈現。

伸縮流的方向 ― ‘flex-direction’ 屬性

名称: flex-direction
取值: row | row-reverse | column | column-reverse
初始: row
适用于: 伸縮容器
继承:
百分比: (不適用)
媒介: 視覺
计算值: 同指定值
动画:

flex-direction’ 屬性可以用來設定伸縮容器的主軸的方向,這也決定了使用者代理配置伸縮項目的方向。

row

伸縮容器的主軸與當前書寫模式的行內軸(文字布局的主要方向)同向。主始主結方向分別等同於當前書寫模式方向。

row-reverse

除了主始主結方向交換以外同 ‘row’。

column

伸縮容器的主軸與當前書寫模式的塊軸(塊布局的主要方向)同向。主始主結方向分別等同於當前書寫模式方向。

column-reverse

除了主始主結方向交換以外同 ‘column’。

伸縮行換行 ― ‘flex-wrap’ 屬性

名称: flex-wrap
取值: nowrap | wrap | wrap-reverse
初始: nowrap
适用于: 伸縮容器
继承:
百分比: (不適用)
媒介: 視覺
计算值: 同指定值
动画:

flex-wrap’ 屬性控制伸縮容器是單行還是多行並控制側軸的指向,這決定 了新的一行堆放的方向。

nowrap

伸縮容器為單行側始方向等同於當前書寫模式側軸的那一邊,而側結方向是側始的相反方向。

wrap

伸縮容器為多行側始方向等同於當前書寫模式側軸的那一邊,而側結方向是側始的相反方向。

wrap-reverse

除了側始側結方向交換以外同 ‘wrap’。

伸縮方向與換行 ― ‘flex-flow’ 縮寫

名称: 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; }
/* 主軸與行內方向相反(右到左)。
   新行換行向上。 */
注:請注意 ‘flex-flow’ 決定的方向取決於書寫模式。舉例來說,在日文豎排裡,‘row’ 伸縮容器從上到下配置其內容。

顯示順序 ― ‘order’ 屬性

預設狀態下,使用者代理會用伸縮項目出現在來源文件的次序配置這些伸縮項目。‘order’ 屬性可以用來改變這個順序。

名称: order
取值: <number>
初始: 0
适用于: 伸縮項目與伸縮容器的絕對定位子元素
继承:
百分比: (不適用)
媒介: 視覺
计算值: 同指定值
动画:

order’ 屬性透過將元素分到有序號的組以控制元素出現的順序。在伸縮布局中,‘order’ 屬性控制伸縮項目在伸縮容器裡的順序。

伸縮容器會從序號最小的組開始布局,在同一個組裡的項目依在來源文件裡的次序布局,這也影響了著畫次序 [CSS21],正如同在文件中元素已經改變次序一般。

order’ 屬性必不可影響非視覺媒介(像是語音)裡的次序。這讓網頁作者可以用具有邏輯次序的內容滿足線性呈現內容的非視覺媒介與非 CSS 使用者代理,同時用 ‘order’ 重新排列內容的視覺順序。

範例四

下圖的簡單標籤介面中,一個使用中的模板總是顯示在最前面:

flex-order-example.png

這可以由以下 CSS 實作(僅顯示部份相關程式碼):

.tabs {
	display: flex;
}
.tabs > .current {
	order: -1; /* 比喻設值 0 要小 */
}
除非有別的規範說明,本屬性在不是伸縮項目或伸縮容器的絕對定位子元素
Error creating thumbnail: Unable to save thumbnail to destination
的元素上沒有效果。
範例五

很多 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>
</div>
<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'属性,在辅轴上进行堆叠。每一行至少包含一个伸缩项目,除非伸缩盒容器本身是空的。
<code>示例7

该示例展示4个按钮,但并不水平排列。

<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>
</div>

由于容器的宽度是300px,仅能支持3个项目在同一行上。这3个项目占用了240px,剩余60px的空间。由于'flex-wrap'属性指定了一个多行的伸缩盒容器(因为使用了'wrap'关键字),伸缩盒容器会多创建一个行来放置最后一个项目。

[图]

图4:多行伸缩盒容器的渲染示例</code>

当内容被分布到多行时,每一行独立地进行布局。可伸缩长度以及'justify-content'和'align-self'属性每次仅作用于单独一行上的项目。

当一个伸缩盒容器有多行时,每一行的辅轴长度指定为可容纳该行中的伸缩盒项目(在依据'align-self'属性进行对齐之后)的最小值,并且这些行依据'align-content'属性在伸缩盒容器中进行对齐。当一个伸缩盒容器只有一行(即使是一个多行的伸缩盒容器)时,这一行的辅轴长度为伸缩盒容器的辅轴长度,同时'align-content'属性无效。行的主轴长度始终和伸缩盒容器的主轴长度相同。

<code>示例8

这一示例与上一示例相同,唯一的区别是伸缩盒项目拥有'flex: auto'样式。第一行剩余60px的空间,且所有项目有相同的可伸缩性,因此这一行上的3个项目均获得20px的额外宽度,变为100px宽。剩余的一个项目放置在其独立的行中,因此会扩展至整个度,即300px。

[图]

图5:与上一示例相同,但使用'flex: auto'样式</code>


伸縮性 ― ‘flex’ 屬性

'flex'缩写

名称: flex
取值: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
初始: 独立参考每个属性
适用于: 伸缩盒项目
继承: 独立参考每个属性
百分比: (不適用)
媒介: 视觉媒体
计算值: 独立参考每个属性
动画: 独立参考每个属性

'flex'属性指定可伸缩长度的部件:扩展比率收缩比率,以及伸缩基准值。当一个元素是伸缩盒项目时,'flex'属性将作为计算值,用于决定元素的主尺寸,代替其主尺寸属性。如果元素不是伸缩盒项目,则'flex'属性无效。

<'flex-basis'>组件用于设置伸缩基准值,在根据可伸缩比率计算出剩余空间的分布之前,其初始值为伸缩盒项目主尺寸。如果该值被省略,则其伸缩基准值默认为'0%'。注意该值与伸缩基准值的初始值不同,其初始值为'auto'。当<'flex-basis'>的值为0时,必须指定一个单位。无单位的0值可以被解析为一个可伸缩比率,也可以导致该声明无效。

<'flex-grow'>和<'flex-shrink'>组件设置扩展比率收缩比率,当根据可伸缩容器中的其它伸缩盒项目分配了剩余空间后,这两个组件可用于计算该伸缩盒项目可扩展或收缩的大小。如果该值被省略,其值被设置为1。注意该值与'flex-grow'的初始值不同,其初始值为'0'。

關鍵字 ‘none’ 的計算值為 ‘0 0 auto’。

Error creating thumbnail: Unable to save thumbnail to destination

圖 6. 一個顯示「絕對」伸縮(以零為基準值開始)與「相對」伸縮(以項目的內容大小為基準值開始)差異的圖解。

flex属性的常见值

本章节不具备规范意义。

下表总结了flex属性常见值的效果:

flex: initial

与'flex: 0 1 auto'相同。该值根据'width/height'属性设置元素的尺寸,当剩余空间为正值时,元素无法伸缩,但当空间不足时,元素可收缩至其minimum值(如果用于伸缩基准值的'width/height'属性值为'auto',则会根据其内容来决定元素尺寸)。对齐相关的属性以及值为'auto'的margin属性可用于控制伸缩盒容器中的伸缩盒项目的对齐。

flex: auto

与'flex: 1 1 auto'相同。该值使元素可伸缩,并根据'width/height'属性设置其伸缩基准值。如果所有项目均属于'flex: auto'或'flex: none',则在项目尺寸决定后,剩余空间会被平分给'flex: auto'的项目。

flex: none

与'flex: 0 0 auto'相同。该值使元素不可伸缩,并根据'width/height'属性决定其尺寸。元素以一般算法决定尺寸,但依旧可以使用可伸缩布局的对齐功能,可以将所有项目设置为'flex: none'并使用值为'auto'的margin属性或使用对齐相关属性。其效果与'initial'类似,但即使在空间溢出的情况下,可伸缩盒项目也不能收缩。

flex: <正数>

与'flex: <正数> 1 0%'相同。该值使元素可伸缩,并将伸缩基准值设置为0,导致该项目会根据设置的比率占用可伸缩盒容器的剩余空间。如果一个可伸缩盒容器里的所有项目都使用此模式,则它们的尺寸会根据可伸缩比率进行设置。
例7:

可伸缩性允许元素直接占用可用空间,同时可选地根据其内容来决定大小:

<!DOCTYPE html>
<style>
    div { display:flex; outline:1px solid silver; }
    p { flex:auto; margin:1em; background:gold; }
</style>
<div>
    <p>"flexing"</p>
    <p>allows the items to get bigger</p>
    <p>or</p>
    <p>smaller</p>
</div>

在此例中,四个段落的伸缩基准值均是他们包含的文字的长度。而因为它们的扩展比率均被设置为'1',剩下的空间(从可伸缩盒容器的宽度中减去四个段落的伸缩基准值以及边距)将被平分给四个段落。下图显示了当伸缩基准值汪同时,拥有相同的可伸缩性的元素,最终依旧可能有不同的尺寸。

wp7zxxyu.gif

在默认情况下,可伸缩盒项目不会收缩至比它们的最小内容尺寸(其中最长的单词的长度,或固定尺寸的元素)更小。如果需要改变这一行为,可设置'min-width'或'min-height'属性。

對齊

在一个可伸缩容器的内容完成伸缩,且所有可伸缩项的大小确定后,它们可以在可伸缩容器中进行对齐。

'margin'属性可以用来对齐这些项,这类似于在块布局的行为,但要更加强大。伸缩盒项目同时也识别盒对齐标准中的对齐相关的属性,这些属性可用于简单地使用基于关键字的对齐方式,且在主轴辅轴上均可使用。这些属性创造了很多常见的对齐方式,包括一些在CSS 2.1中很难实现的布局,比如水平和垂直居中。

注:由于对齐相关的属性是在盒对齐标准中定义的,可伸缩盒则重新定义了相关属性,以避免两个标准间产生规范依赖从而减缓本标准的进步速度。在盒对齐标准完成并定义这些属性用于其他类型的布局模式时的效果前,本标准定义的这些属性将只用于可伸缩盒。

用 ‘auto’ 邊界對齊

本章节不具规范意义。具有规范意义的边距对可伸缩项的影响方式在可伸缩盒布局算法一章中定义。

在可伸缩项目上,以'auto'为值的边距,非常类似于普通流中的自动边距。

  • 在计算伸缩基准值和伸缩长度时,自动边距相当于'0'。
  • 在使用'justify-content'和'align-self'控制对齐前,所有正值的空间会在对应维度上被自动的边距平均分配。
  • 在溢出的元素上,基于边距的对齐没有作用。
注:需要注意的是,如果空间被自动的边距平均分配了,则对齐相关的属性在这一维度上没有作用,因为边距偷走了伸缩后所有可用的空白空间。
例10:

一种比较常见的使用auto作为margin属性的值的场景是,将可伸缩项分为多个独立的“组”。以下示例展示了使用这一方案来实现一个常用的UI模式--一个包含多个动作按钮的横条,其中一部分在左边,另一部分在右边。

图7 Sample rendering of the code below.

  • About |
  • Projects |
  • Interact
  • Login
<style>
nav > ul {
	display: flex;
}
nav > ul > #login {
	margin-left: auto;
}
</style>
<nav>
	<ul>
		<li><a href=/about>About</a>
		<li><a href=/projects>Projects</a>
		<li><a href=/interact>Interact</a>
		<li id='login'><a href=/login>Login</a>
	</ul>
</nav>
救命11:

下图展示了在有溢出的情况下,使用'auto'值作为margin,以及使用对齐相关属性控制跨轴的对齐时的差异。

About
Authoritarianism
Blog
About
Authoritarianism
Blog

图8 左图中的元素使用边距进行居中,而右图的则使用'align-self'进行居中。如果该列放在页面的左边,则边距的行为会更符合预期,因为那个较长的元素将保持完全可读。在其他情况下,真正的居中行为会产生更好的效果。

主軸對齊 ― ‘justify-content’ 屬性

名称: justify-content
取值: flex-start | flex-end | center | space-between | space-around
初始: flex-start
适用于: 可伸缩盒容器
继承:
百分比: (不適用)
媒介: 视觉媒体
计算值: 指定值
动画:

'justify-content'属性用于在主轴上对齐伸缩盒项目。这一行为会在所有可伸缩长度及所有自动边距均被解释后进行。通常情况下,当一行上的所有伸缩盒项目都不能伸缩或已经达到其最大值时,这一属性可协助对多余的空间进行分配。当元素溢出某行时,这一属性同样会在对齐上施加一些控制。

flex-start

伸缩盒项目将向行起始位置收束。该行的第一个伸缩盒项目主起始位置的边距边界将与该行的主起始位置的边界对齐,同时所有后续的伸缩盒项目与其前一个项目对齐。

flex-end

伸缩盒项目将向行结束位置收束。该行的第一个伸缩盒项目主结束位置的边距边界将与该行的主结束位置的边界对齐,同时所有后续的伸缩盒项目与其前一个项目对齐。

center

伸缩盒项目将向行的中间位置收束。该行的伸缩盒项目将相互对齐并在行中居中对齐,同时第一个元素与行的主起始位置的边距等同与最后一个元素与行的主结束位置的边距(如果剩余空间是负数,则保持两端相等长度的溢出)。

space-between

伸缩盒项目会平均地分布在行里。如果最左边的剩余空间是负数,或该行只有一个伸缩盒项目,则该值等效于'flex-start'。在其它情况下,第一个元素的边距边界与行的主起始位置的边界对齐,同时最后一个元素的边距边界与行的主结束位置的边距对齐,而剩余的伸缩盒项目则平均分布,并确保两两之间的空白空间相等。

space-around

伸缩盒项目会平均地分布在行里,两端保留一半的空间。如果最左边的剩余空间是负数,或该行只有一个伸缩盒项目,则该值等效于'center'。在其它情况下,伸缩盒项目则平均分布,并确保两两之间的空白空间相等,同时第一个元素前的空间以及最后一个元素后的空间为其他空白空间的一半。
Error creating thumbnail: Unable to save thumbnail to destination

图9 通过一个伸缩盒容器中的三个不同颜色的项目,展示5种'justify-content'关键字效果.

側軸對齊 ― ‘align-items’ 與 ‘align-self’ 屬性

名称: align-items
取值: flex-start | flex-end | center | baseline | stretch
初始: stretch
适用于: 可伸缩盒容器
继承:
百分比: (不適用)
媒介: 视觉
计算值: 指定值
动画:
名称: align-self
取值: auto | flex-start | flex-end | center | baseline | stretch
初始: auto
适用于: 伸缩盒项目
继承:
百分比: (不適用)
媒介: 视觉
计算值: 如果值为'auto',则计算值为父元素的'align-items'值,否则为指定值
动画:

伸缩盒项目可以在伸缩盒容器的当前行的侧轴上进行排列,这类似于'justify-content'属性,但在垂直的方向上。'align-items'用于设置伸缩盒容器中的所有项目的对齐方式,包括匿名伸缩盒项目。'align-self'则允许在独立的伸缩盒项目上覆写默认的对齐方式。(对于匿名伸缩盒项目,'align-self'的值永远与其关联的伸缩盒窗口的'align-items'的值相同。)

如果'align-self'的值为'auto',则其计算值为元素的父元素的'align-items'值,如果其没有父元素,则计算值为'stretch'。有以下对齐方式:

'flex-start'

伸缩盒项目侧轴起始位置的边距边界紧靠住该行的侧轴起始边界。

'flex-end'

伸缩盒项目侧轴结束位置的边距边界紧靠住该行的侧轴结束边界。

'center'

伸缩盒项目的边距盒在该行的侧轴上居中放置。(如果伸缩行的尺寸小于伸缩盒项目的尺寸,则会向两个方向溢出相同的长度)。

'baseline'

如果伸缩盒项目的行内轴与侧轴为同一条,则该值怀'flex-start'等效。 其它情况下,该值将参与基线对齐。所有参与该对齐方式的伸缩盒项目将按一定方式排列,首先将它们的基线进行对齐,随后其中基线至其侧轴起始位置的边距边界距离最长的那个项目将紧靠住该行的侧轴起始边界。

'stretch'

如果指定侧轴大小的属性值为'auto',则其值会使项目的边距盒的尺寸尽可能接近所在行的尺寸,但同时会遵照'min/max-width/height'属性的限制。
注:注意:如果伸缩盒窗口的高度被限制,则该值可能导致伸缩盒项目的内容溢出该项目。
伸缩盒项目的侧轴起始位置的边距边界紧靠住该行的侧轴起始边界。
Error creating thumbnail: Unable to save thumbnail to destination

图10 通过一个伸缩盒容器中的四个不同颜色的项目,展示5种'align-items'关键字效果

堆疊伸縮行 ― ‘align-content’ 屬性

名称: 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'各关键字对多行的伸缩盒容器的效果

伸縮容器的基線

一個伸縮容器的基線由以下步驟決定:

  • 若任一個在伸縮容器第一行(經過 ‘order’ 重新排序之後) 的伸縮項目align-self’ 的計算值是 ‘baseline’,則伸縮容器的基線是那些伸縮項目的基線。
  • 否則,若伸縮容器有一個以上的伸縮項目,且第一個伸縮項目(經過 ‘order’ 重新排序之後)的基線與伸縮容器的主軸平行,則伸縮容器的基線是其第一個伸縮項目的基線。
  • 否則,伸縮容器的基線是其內容盒的「後」端。

伸縮布局演算法

本章節涵蓋了具有規範性的演算法,詳述伸縮容器與其內容布局的準確行為。演算法以容易閱讀的方式呈現,並不一定是最有效率的演算法。使用者代理可使用任何想用的演算法,但是產生結果必須與這裡的演算法一致。

注:本章節的目標讀者為實作者。除非某網頁作者具有追根究柢的企圖心,了解神秘的 CSS 布局的渴望,否則網頁作者應該可以從各個單獨的屬性解釋找到要查的東西。

在以下演算法中,明確尺寸是指不需要靠測量內容決定的大小:例:<length>、初始包含塊的大小、一個靠明確尺寸決定的 <percentage>。不明確尺寸是指不明確的大小。

以下各小節描述了布局一個伸縮容器與其內容的演算法。

起始設定

  1. 生成無名伸縮項目:《伸縮項目》小節的描述。
  2. 根據 ‘order’ 重新排序伸縮項目。有最小(負值最大)‘order’ 的伸縮項目排在第一個。若有多個項目有相同的 ‘order’ 值,這些項目照文件順序排。這個步驟影響了伸縮項目生盒樹成的盒子的順序,也影響了後面的演算法如何處理各項目。

決定一行長度

  1. 決定伸縮項目可用的主、側空間。對於主、側兩個方向,若伸縮容器的在那個方向具有明確尺寸,使用該長度。否則,從該方向中伸縮容器的可用空間中減去邊界、邊框與邊距並使用該值。這個結果可能是無限大。
  2. 決定各項目的「伸縮基準長度」「假定主長度」

    • 若項目具有明確伸縮基準值,該值為伸縮基準長度
    • 若伸縮基準值是 ‘auto’ 又或伸縮基準值取決於項目的可用空間,且伸縮容器以最小內容或最大內容限制決定大小(例:進行自動表格布局的時候 [CSS21]),則也使用該限制決定項目的大小。伸縮基準長度為這個過程在主軸最後的大小。
    • 否則,若伸縮基準值是 ‘auto’ 又或伸縮基準值取決於項目的可用空間,且可用的主軸空間為無限大,又伸縮容器的主軸與項目的行內軸平行,則使用垂直流中的盒的規則布局該項目 [CSS3-WRITING-MODES]伸縮基準長度為項目的最大內容主長度。
    • 否則,使用項目的伸縮基準值當作主長度,並將 ‘auto’ 視為是 ‘max-content’ 之後,在可用空間裡進行布局。伸縮基準長度為這個過程在主軸最後的大小。

    項目的伸縮基準長度截至其最大、最小值(透過最大、最小主長度屬性)即為假定主長度

  3. 決定伸縮容器的主長度:使用其主長度屬性。在本計算中,伸縮容器的最小內容主長度是所有伸縮容器裡伸縮項目的「最小內容長度貢獻」的最大值,伸縮容器的最大內容主長度是所有伸縮容器裡伸縮項目的「最大內容長度貢獻」的和。一個項目的「最小/最大內容長度貢獻」是當項目以最小內容或最大內容限制決定大小時,項目的外-假定主長度。在這個計算中,使用者代理會將 ‘auto’ 邊界視為 ‘0’。

決定主長度

  1. 蒐集伸縮項目成伸縮行:
    • 若伸縮容器為單行,則蒐集所有彈性項目至單一個伸縮行。
    • 否則,從第一個尚未蒐集進來的項目開始,盡可能的蒐集伸縮項目直到伸縮容器的內主長度不夠或碰到強迫中斷(不過至少蒐集一個)進一個伸縮行。CSS2.1 ‘page-break-before/after[CSS21] 或 CSS3 ‘break-before/after[CSS3-BREAK] 屬性設有分段中斷時,使用者代理會將之視為強迫中斷。

    在本步驟中,伸縮項目的長度是外-假定主長度

    重複直到收集了所有伸縮項目。

    注:除非主長度為零的項目在伸縮容器的開頭,這些項目不可能是一個行開頭。儘管前一行的最後一個非零項目已經「填滿」了前一行,「盡可能收集」會把主長度為零的項目蒐集進前一行的尾端。
  2. 決定可伸縮長度決定所有伸縮項目的可伸縮長度以找到項目主長度的使用值。

決定側長度

  1. 決定每個項目的假定側長度將 ‘auto’ 當作 ‘fit-content’ 並使用主長度的使用值與可用空間進行布局以找到假定側長度。

  2. 計算各伸縮行的側長度。

    若伸縮容器僅有單一行(儘管容器是多行伸縮容器),則伸縮行的側長度是伸縮容器的內-側長度。

    否則,對於各伸縮行:

    1. 蒐集所有行內軸與主軸平行,且 ‘align-self’ 是 ‘baseline’,且側軸的邊界都不為 ‘auto’ 的所有項目。找出這些項目中基線與假定外-側始邊的最大距離,找出項目基線與假定外-側結邊的最大距離,並將兩個值相加。
    2. 在所有沒被前一個步驟蒐集的項目中,找出最大的外-假定側長度
    3. 伸縮行側長度的使用值是前兩步驟找到的值中較大的那一個。
  3. 處理 ‘align-content: stretch’ 。若伸縮容器具有明確的側長度,且 ‘align-content’,且伸縮行側長度的總和小於伸縮容器的內-側長度,則給各伸縮行增加相同的側長度,使得側長度的總和剛好與伸縮容器的內-側長度相等。
  4. 折疊 ‘visibility: collapse’ 項目。若有 ‘visibility: collapse’ 的伸縮項目,記下項目所在的行的側長度為項目的支撐長度,並從頭開始重新布局。

    在第二輪布局中,當進行蒐集伸縮項目成伸縮行步驟的時候,將已折疊項目的主長度當作是零。在該步驟之後的剩下的演算法步驟裡,完全忽略已折疊的項目(將這些視為 ‘display: none’ ),但是在計算各伸縮行的側長度的步驟之後,若有任何一行的側長度小於在該行所有已折疊的項目裡最大的支撐長度,將該行的側長度設為該支撐長度

    在第二輪布局中跳過本步驟

  5. 決定各伸縮項目側長度的使用值。若伸縮項目設有 ‘align-self: stretch’,且其側長度屬性是 ‘auto’,且其側軸邊界都不是 ‘auto’,則外-側長度的的使用值是其伸縮行的側長度截至最大、最小值(透過側長度屬性)的結果。否則,側長度的使用值是項目的假定側長度

主軸對齊

  1. 分配剩下的空間。對於各伸縮行:

    1. 若剩下的空間為正且在這行中至少有一個主軸邊界是 ‘auto’,將剩下的空間平均分配給這些邊界。否則,將所有 ‘auto’ 邊界設為零。
    2. 按照 ‘justify-content’ 進行沿著主軸的項目對齊。

側軸對齊

  1. 決定側軸 ‘auto’ 邊界。若某個伸縮項目有 ‘auto’ 側軸邊界:
    1. 若其(將 ‘auto’ 邊界視為零)外-側長度小於其伸縮行的側長度,將長度的差異平均分配給 ‘auto’ 邊界。
    2. 否則,若始或頭邊界(在側軸那邊的那一個)是 ‘auto’,將之設為零 ― 將相反邊的邊界設成一個會讓項目的外側長度等於其伸縮行的側長度的邊界。
  2. 沿著側軸對齊所有的伸縮項目:若項目的兩個側軸邊界都不為 ‘auto’ ,按照 ‘align-self’ 對齊該伸縮項目。
  3. 決定伸縮容器側長度的使用值:

    • 若側長度屬性有明確大小,使用該值。
    • 否則,使用各伸縮行的側長度的總和。
  4. 對齊所有伸縮行:按照 ‘[[#align-content align-content]]’ 對齊所有伸縮行。

決定可伸縮長度

使用以下步驟決定伸縮行裡項目的可伸縮長度:

  1. 決定使用哪個伸縮比例。先求目標行裡所有項目外-假定主長度的總和。若總和小於伸縮容器的內主長度,則在本演算法之後的部份使用擴展比率。否則,使用收縮比率
  2. 決定不可伸縮項目的大小。對於任何伸縮比率為零的項目,設項目主長度的使用值為項目的假定主長度
  3. 確認可否配置空間。若所有目標行裡的伸縮項目都要不是被凍結要不是伸縮比率為零,則結束本演算法。
  4. 計算可配置空間。先求目標行裡所有項目外-伸縮基準長度的總和,將伸縮容器的內主長度剪掉總和,即為可配置空間。
  1. 配置正比於伸縮比例的空間。若可配置空間的正負號與選擇伸縮比率的正負號相同,配置正比於項目伸縮比率的空間到可伸縮項目主長度裡:

    若可配置空間為正

    找出項目擴展比率與目標行裡項目的擴展比率總和的比率。將項目的主長度設為伸縮基準長度加可配置空間裡此項目佔有的部份(使用前面算出的比率)。

    若可配置空間為負

    對於每一個在目標行的項目,將收縮比率乘上外-伸縮基準長度,將這個值記為正規化收縮比率。找出項目正規化收縮比率與目標行裡項目的正規化收縮比率總和的比率。將項目的主長度設為伸縮基準長度減可配置空間裡此項目佔有的部份(使用前面算出的比率)。請注意得到的內主長度可能是負的 ― 下一個步驟會校正這個問題。

  2. 修復最大、最小違規。將項目的主長度截至其最大、最小值(透過主長度屬性)。若項目的主長度變小,則這是最大違規。若項目的主長度變大,則這是最小違規。
  3. 總違規事前一個步驟所有調整的總和(截至其最大、最小後的長度 - 未截至其最大、最小後長度)。若總違規為:

    離開演算法。

    凍結所有最小違規,重設所以其它項目到進入本演算法的大小,並回到本演算法的步驟 2。

    凍結所有最大違規,重設所以其它項目到進入本演算法的大小,並回到本演算法的步驟 2。

伸縮容器中的分頁

CSSOM