轉載自:http://www.tuicool.com/articles/quQVv2
伸縮盒模型(flexbox)是一個新的盒子模型,主要優化了UI佈局。作爲實際佈局的第一個CSS模塊(浮動真的應該主要用來製作文本圍繞圖片這樣的效果),它使很多任務容易多。Flexbox的功能主要包手:簡單使用一個元素居中(包括水平垂直居中),可以讓擴大和收縮元素來填充容器的可利用空間,可以改變源碼順序獨立佈局,以及還有其他的一些功能。
Flexbox一直都存在。它最開始作爲Mozilla XUL的一個功能,被用來製作程序界面,如Firefox的工具欄,就多次使用這個屬性。該規範最近才達到穩定,在主要的瀏覽器對新的版本有相當完整的支持。
然而有一些事項需要注意。在IE中規範更改了他的語法,因此你將需要使用一個稍微不同的語法。Chrome當前版本仍然需要添加前綴“-webkit-”,而Firefox和Safari仍然還在使用最老版本的語法。Firefox已經更新爲最新的規範,但是,在實際項目中目前最好還先別使用最新的規範,直到它被認爲沒有bug了或者更穩定了,在使用。在這之前,Firefox還是使用最老的語法規範。
當你給一直元素使用了Flexbox模塊,那麼他的子元素就會指定的方向在水平或者縱向方向排列。這些子元素會按照一定的比例進行擴展或收縮來填補容器的可用空間。
案例:水平和垂直居中(網頁設計的聖盃)
網頁設計師都很希望元素能夠居於頁面的中心——是的,可能通過選擇器確定父元素的高或者讓擺脫IE6(第二可能將不存在)。使用Flexbox,這是非常簡單的。讓我們先創建一個基本的HTML模板,想讓一個標題顯示在中心位置。最後,一旦我們添加所有的樣式,他最後的樣子像 案例 演示的一樣水平垂直居中。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"/> <title>Centering an Element on the Page</title> </head> <body> <h1>OMG, I’m centered</h1> </body> </html>
這裏沒有什麼特別之處,甚至沒一個div容器。一切魔力都在CSS之中:
html {
height: 100%;
}
body {
display: -webkit-box; /* 老版本語法: Safari, iOS, Android browser, older WebKit browsers. */
display: -moz-box; /* 老版本語法: Firefox (buggy) */
display: -ms-flexbox; /* 混合版本語法: IE 10 */
display: -webkit-flex; /* 新版本語法: Chrome 21+ */
display: flex; /* 新版本語法: Opera 12.1, Firefox 22+ */
/*垂直居中*/
/*老版本語法*/
-webkit-box-align: center;
-moz-box-align: center;
/*混合版本語法*/
-ms-flex-align: center;
/*新版本語法*/
-webkit-align-items: center;
align-items: center;
/*水平居中*/
/*老版本語法*/
-webkit-box-pack: center;
-moz-box-pack: center;
/*混合版本語法*/
-ms-flex-pack: center;
/*新版本語法*/
-webkit-justify-content: center;
justify-content: center;
margin: 0;
height: 100%;
width: 100% /* needed for Firefox */
}
/*實現文本垂直居中*/
h1 {
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
-webkit-box-align: center;
-moz-box-align: center;
-ms-flex-align: center;
-webkit-align-items: center;
align-items: center;
height: 10rem;
}
在上面的CSS中已經包括了不同的版本,從仍然需要的老版本到最新版本和混合版本的語法。這可能看起來讓人困惑,不同的語法適應不同的版本,在文章末尾創建對應的語法查詢表格。
在我們的例子中並不是所有的CSS都包括在裏面,因爲我已經去掉了額外的樣式,您可能知道如何使用以節省空間。
讓我們看看需要將標題顯示在頁面中心需要的CSS樣式。首先,要給html和body元素設置一個height爲“100%”並且移去所有的margin。這使h1的容器佔用瀏覽器的窗口的所有高度。在Firefox瀏覽器中,還需要設置一個width爲100%來完成相應的效果。現在我們只需要讓所有東西居中。
啓用Flexbox
因爲body元素包含了想要居中的標題元素,所以我們將他的display屬性值設置爲“flex”:
body {
display: flex;
}
主要作用是讓元素body使用flexbox佈局,而不是普通的塊佈局。在文檔流中的所有子元素(即不是絕對定位的元素)現在都變成了伸縮項目。
在IE10中使用的語法是“display:-ms-flexbox”,而老版本的Firefox和Webkit內核的瀏覽器需要使用“display:-prefix-box”(其中prefix是“moz”或者“webkit”)。你可以到文章末尾查看各種版本語法對照的表格。
這個時候,我們的元素都具有伸縮特性。那麼他們具有哪些優勢:他們可以相對於可用的空間展示他們的大小和位置;他們可以水平或垂直居中,甚至可以改變文檔流順序。
水平居中
接下來,我們希望我們的h1元素水平居中。你可能會說沒什麼大不了的,有比設置寬度並定義margin爲auto設置更簡單的方法。我們只要讓伸縮容器使用他們的伸縮項目居中。默認情況之下,伸縮項目是水平排列,因爲只需要給伸縮項目設置“justify-content”屬性,讓他們沿着主軸方向居中:
body {
display: flex;
justify-content: center;
}
在IE10中,這個屬性稱作“flex-pack”,在老的瀏覽器中它稱爲“box-pack”(再一次需要使用瀏覽器的私有前綴)。其他的值還有“flex-start”、“flex-end”、“space-between”和“space-around”。在IE10和老的規範中,他們分別是“start”、“end”、“justify”和“distribute”(在老的規範中不支持“distribute”)。“flex-start”表示左對齊(如果書寫模式是“rtl”表示右對齊),“flex-end”表示右對齊,“space-between”表示伸縮項目平均分佈佈局軸上,“space-around”均勻分佈在佈局軸上,而且第一個伸縮項目前和最後一個伸縮項目後的空間爲中間伸縮項目間距的一半。
顯示設置元素在主軸上的對齊方式,你可以使用“flex-flow”屬性。默認值爲“row”,這和我們剛纔得到效果相同。如果想讓伸縮項目沿着側軸(垂直於主軸)排列,可以將“flex-flow”設置爲“column”。如果我們將它添加到我們的實例中,你將看到的元素是垂直居中,而不是水平居中。當row和column添加後綴“-reverse”將會反向排列(flex-flow:row-reverse或者flex-flow:column-reverse),但這些屬性並沒有運用到我們例子中,因爲我們只有一個項目。
各種版本規範對這些屬性的解析都略有差異,詳細的可以查看文章末尾的表格。另一個大家要記在心裏的就是“flex-flow”屬性和“writing-mode”有直接的關係。即,當使用“writing-mode:vertical-rl”時轉向垂直文佈局(如傳統的中文、日文和韓文排版本民,也就是豎排),flex-flow:row將垂直排列伸縮項目,和column將水平排列伸縮項目。
垂直居中
定義垂直居中和定義水平居中一樣的容易。我們只需要使用適當的屬性控制伸縮項目沿着側軸的排列方向。那是什麼?側軸基本上是與主軸垂直的另一個軸。因此,如果伸縮項目水平對齊,那麼側軸就是垂直對齊。我們可以通過align-item來設置(在IE10中使用flex-align,在老的瀏覽器使用box-align)。
body {
/*記住,在IE10和其他老版本瀏覽中要使用其他版本的規範 */
display: flex;
justify-content: center;
align-items: center;
}
這就是flexbox製作居中的所有樣式。我們也可以使用“flex-start”(start)和flex-end(end)值,以及baselineT和stretch。我們來看另一個完成的 案例
使用flexbox製作的一個簡單的水平垂直居中效果。 更大窗口瀏覽
你可以注意到了,h1元素的文本也在內部垂直居中。這裏沒使用margin或者line-height,但是我們再次使用了flexbox,讓文本變成了一個匿名伸縮項目(在這個案例中,行文本是h1內的元素)。無論h1元素有多高,文本將永遠垂直居中。
h1 {
/* 記住,在IE10和其他老版本瀏覽中要使用其他版本的規範 */
display: flex;
align-items: center;
height: 10rem;
}
伸縮尺寸
如果製作元素居中,flexbox肯定可以實現,而且非常的爽。但是有更多的時候不只是要這樣的效果。讓我們來看看伸縮項目擴大和收縮適合伸縮容器的可用空間。用的瀏覽器打開這個 案例 。
一個使用flexbox創建的交互式幻燈片, 更大窗口瀏覽
HTML和CSS類似於前一個示例。使用相同的方法,把所有元素在頁面中居中顯示。此外,我們想讓標題(header元素內)保持一樣的尺寸,其他五個盒子(section元素)根據瀏覽器寬度自動調整大小。因此我們要使用一個新的屬性“flex”。
section {
/* removed other styles to save space */
-prefix-box-flex: 1; /* old spec webkit, moz */
flex: 1;
height: 250px;
}
我們做的是讓每個section元素佔有1flex單元。因爲我們還沒有給五個section元素明確的設置寬度,而每個section元素都有相同的寬度。把“header”設置了一個寬度(277px),因爲他不是伸縮性的。我們把body剩下的寬度計算到每個section元素中。現在,我們來改變瀏覽器窗口大小,section元素將會擴展或收縮。
在這個例子中,我們已經設置了一個一樣的高度,但是使用同樣的方法也可以實現伸縮性。我們可能不會總是希望所有元素是相同的大小,所以讓我來做一個更大的。在懸浮狀下,我們設置元素爲2flex單元。
section:hover {
-prefix-box-flex: 2;
flex: 2;
cursor: pointer;
}
現在可用的空間除以6,而在懸浮狀態是佔有2份。注意:一個元素的2flex單元並不一定就是1flex單元寬度的兩倍。它只獲得了添加兩倍比例到他的可用空間的首先寬度。在我們的示例中,首先寬度是0(默認狀態下)。
獨立的源順序
我們最後要介紹的一個技巧,研究如何在佈局中實現源順序獨立。當我們點擊盒子時,我們想把元素移動到所有盒子元素的左邊,也就是直接移到標題的後面。我們可以使用”order”屬性來實現。默認情況下,伸縮項目的order值是0,他們是按照文檔流順序排列。
讓我們選擇的元素移動到第一的位置,我們必須要設定一個較低的order值。我選擇了“-1”。我們也需要把head元素的order設置爲“-1”。這樣選擇的元素纔不會移動到標題的前面。
header {
-prefix-box-ordinal-group: 1; /* old spec; must be positive */
-ms-flex-order: -1; /* IE 10 syntax */
order: -1; /* new syntax */
}
section[aria-pressed="true"] {
/* Set order lower than 0 so it moves before other section elements,
except old spec, where it must be positive.
*/
-prefix-box-ordinal-group: 1;
-ms-flex-order: -1;
order: -1;
-prefix-box-flex: 3;
flex: 3;
max-width: 370px; /* Stops it from getting too wide. */
}
在舊的規範中,設置順序(box-ordinal-group)屬性值只接受一個正整數。因此,我們需要給每個元素設置order值爲2,和選擇的元素設置order爲1。如果你想知道上面例子中aria-pressed=”true”是什麼?它是一個WAI-ARIR屬性和屬性值,當用戶點擊其中某個section元素時,就會自動加上。
這個屬笥是用來告訴用戶該元素激活了。如果你想了解更多有關於WAI-ARIA的信息,可以點擊 Gez Lemon寫的 Introduction to WAI-ARIA 。因爲當用點擊後添加這個屬性,在這個示例中需要一個簡單的js文件才能正常工作,但flexbox本身並不需要它,它只是用來應用用戶交互的。
但願,這些能讓給帶來一些靈感,和足夠的讓你得到flexbox的入門知識,讓你在你的設計中嘗試使用flexbox。
語法的變更
正如你可能已經注意到了在這篇文章中,語法距離第一次實現flexbox已經有好幾次的改變。下面的表格讓我更好的瞭解各版本之間的變更。
規範版本
規範版本 | IE | Opera | Firefox | Chrome | Safari |
---|---|---|---|---|---|
標準版本 | 11? | 12.10+ * | Behind flag |
21+ ( -webkit- ) |
|
混合版本 |
10 ( -ms- ) |
||||
老版本 |
3+ ( -moz- ) |
<21 ( -webkit- ) |
3+ ( -webkit- ) |
開啓flexbox:讓一個元素變成伸縮容器
規範版本 | 屬性名稱 | 塊級伸縮容器 | 內聯伸縮容器 |
---|---|---|---|
標準版本 |
display |
flex |
inline-flex |
混合版本 |
display |
flexbox |
inline-flexbox |
老版本 |
display |
box |
inline-box |
主軸對齊方式:指定伸縮項目沿主軸對齊方式
規範版本 | 屬性名稱 | start | center | end | justify | distribute |
---|---|---|---|---|---|---|
標準版本 |
justify-content |
flex-start |
center |
flex-end |
space-between |
space-around |
混合版本 |
flex-pack |
start |
center |
end |
justify |
distribute |
老版本 |
box-pack |
start |
center |
end |
justify |
N/A |
側軸對齊方式:指定伸縮項目沿側軸對齊方式
規範版本 | 屬性名稱 | start | center | end | baseline | stretch |
---|---|---|---|---|---|---|
標準版本 |
align-items |
flex-start |
center |
flex-end |
baseline |
stretch |
混合版本 |
flex-align |
start |
center |
end |
baseline |
stretch |
老版本 |
box-align |
start |
center |
end |
baseline |
stretch |
單個伸縮項目側軸對齊方式
規範版本 | 屬性名稱 | auto | start | center | end | baseline | stretch |
---|---|---|---|---|---|---|---|
標準版本 |
align-self |
auto |
flex-start |
center |
flex-end |
baseline |
stretch |
混合版本 |
flex-item-align |
auto |
start |
center |
end |
baseline |
stretch |
老版本 | N/A |
伸縮項目行對齊方式:指定伸縮項目行在側軸的對齊方式
規範版本 | 屬性名稱 | start | center | end | justify | distribute | stretch |
---|---|---|---|---|---|---|---|
標準版本 |
align-content |
flex-start |
center |
flex-end |
space-between |
space-around |
stretch |
混合版本 |
flex-line-pack |
start |
center |
end |
justify |
distribute |
stretch |
老版本 | N/A |
這個只有伸縮項目有多行時才生效,這種情況只有伸縮容器設置了flex-wrap爲wrap時,並且沒有足夠的空間把伸縮項目放在同一行中。這個將對每一行起作用而不是每一個伸縮項目。
顯示順序:指定伸縮項目的順序
規範版本 | 屬性名稱 | 屬性值 |
---|---|---|
標準版本 |
order |
|
混合版本 |
flex-order |
<number> |
老版本 |
box-ordinal-group |
<integer> |
伸縮性:指定伸縮項目如何伸縮尺寸
規範版本 | 屬性名稱 | 屬性值 |
---|---|---|
標準版本 |
flex |
none | [ <flex-grow> <flex-shrink> ?
|| <flex-basis> ] |
混合版本 |
flex |
none | [ [ <pos-flex> <neg-flex> ?
] || <preferred-size> ] |
老版本 |
box-flex |
<number> |
flex屬性在微軟的草案與新標準或多或少不一樣。主要的區別在於,它們都轉換成標準縮寫版本,他們的屬性值爲:flex-grow、flex-shrink和flex-basis。他們的值也使用同樣的方式在速記。然而,flex-shrink(以前稱爲負flex)的默認值爲1。這意味着伸縮項目默認不能收縮。以前,空間不足使用flex-shrink比例來收縮伸縮項目,但現在可以在flex-basis的基礎上配合flex-shrink來收縮伸縮項目。
伸縮流:指定伸縮容器主軸的伸縮流方向
規範版本 | 屬性名稱 | Horizontal | Reversed horizontal | Vertical | Reversed vertical |
---|---|---|---|---|---|
標準版本 |
flex-direction |
row |
row-reverse |
column |
column-reverse |
混合版本 |
flex-direction |
row |
row-reverse |
column |
column-reverse |
老版本 |
box-orient box-direction |
horizontal normal |
horizontal reverse |
vertical normal |
vertical reverse |
在舊的版本規範中,使用box-direction屬性設置爲reverse和在新的規範版本中設置row-reverse或column-reverse得到的效果相同。如果你想要的效果是row或column你可以省略不設置,因爲normal是默認的初始值。
當設置了direction爲reverse,主軸就就翻轉。意思是,當你使用“ltr”書寫模式的,當你指定row-reverse時,所有伸縮項目會從右向左排列。類似的,column-reverse將會使所有伸縮項目從下向上排列,來代替從上往下排列。
在老的規範版本中,需要使用box-orient來設置書寫模式的方向。當使用“ltr”模式時,horizontal可用在inline-axis,vertical可用block-axis。如果您使用的是一個自上而下的書寫模式,如東亞那些傳統的書寫模式,這些值就會翻轉。
換行:指定伸縮項目是否沿着側軸排列
規範版本 | 屬性名稱 | No wrapping | Wrapping | Reversed wrap |
---|---|---|---|---|
標準版本 |
flex-wrap |
nowrap |
wrap |
wrap-reverse |
混合版本 |
flex-wrap |
nowrap |
wrap |
wrap-reverse |
老版本 |
box-lines |
single |
multiple |
N/A |
wrap-reverse讓伸縮項目在側軸上進行start和end翻轉,所以,如果伸縮項目在水平排列,伸縮項目翻轉不會到一個新的線下面,他會翻轉到一個新的線上面。(簡單理解就是伸縮項目只是上下或前後翻轉順序)。
在寫本文的時候,在Firefox中並不支持flex-wrap或者box-lines屬笥。他不支持速記。
當前規範flex-flow是一個速記版本,他包括了換行flex-wrap和伸縮流flex-direction。在IE10中也支持這個版本規範。它目前還不支持Firefox瀏覽器,所以我建議避免使用它,僅使用flex-direction來指定伸縮流方向。
總結
嗯,這是一個伸縮容器。在這篇文章中,我介紹了一些flexbox所提供的功能。他具有源獨立性,可以伸縮調整伸縮尺寸適合容器以及調整他的的對齊方式,我肯定你能找到方法在你的網站或應用程序使用flexbox功能。現在語法終於定下來了,在這裏展示了所有的規範版本。所有主流瀏覽器都支持flexbox,至少最新版本的主流瀏覽器是這樣。
雖然一些瀏覽器使用老的語法規範,Firefox看上去也在向新語法規範靠近和IE11將使用最新版本的語法規範。目前Safari還沒有看到相關介紹,但這是一個顯而易見的考慮,Chrome在和Blink與webkit分裂之前採用了最新的語法。目前,使用上面表格展示的各種語法,你會得到你需要的flexbox效果。
CSS佈局正在變得越來越強大,Flexbox是第一個走出泥沼的。我們發現自己在這些年來,第一次使用提表格佈局,然後是基於浮動的佈局。IE10已經支持早期草案提出的網格佈局規範,這有利於頁面佈局,還有Regions,他們將會徹底改變我們如何處理內容流佈局。
如果你只需要支持現代瀏覽器或者提供一個優雅降級的方案,那麼今天你就可以使用Flexbox。在不久的將來,Flexbox佈局模塊的各個屬性都可以使用,這樣我們可以使用最好的工具來完成工作。Flexbox正變成一個極好的工具。