本文譯自 A Complete Guide to Flexbox
這里忍抽,針對本文介紹的屬性列個提綱:
伸縮容器屬性:
- display
- flex-direction
- flex-wrap
- flex-flow
- justify-content
- align-items
- align-content
伸縮項目屬性:
- order
- flex-grow
- flex-shrink
- flex-basis
- flex
- align-self
以后再布局時可以考慮用flexbox啦~~
背景
Flexbox 布局(Flexible Box)模塊(目前W3C上一次工作草案的叫法)旨在提供一種更高效的方式來布局鸭蛙、排列及分配容器中項目的空間劫恒,即便容器大小是未知或動態(tài)變化的(因此稱為“flex”)。
Flex布局的主要思想是使容器具備改變其子項目的寬度或高度的能力,以此充分填充可用空間(主要是為了適應(yīng)各種顯示設(shè)備和屏幕尺寸)。使用flex布局的容器能擴展其子項目來填滿可用空間,也能縮小他們以防止溢出容器赋铝。
Flex布局與常規(guī)布局相比插勤,最主要的是它是方向無關(guān)的(常規(guī)布局通常是塊級元素從上到下布局,行內(nèi)元素從左到右布局)革骨。盡管常規(guī)布局對于頁面布局十分好用农尖,但卻缺少對大型或復(fù)雜應(yīng)用的靈活性支持(尤其是當(dāng)涉及到取向改變,尺寸調(diào)整良哲,拉伸盛卡,收縮等場景時)。
注意:Flexbox布局主要適用于應(yīng)用的組件以及小規(guī)模的布局筑凫,對于那些較大規(guī)模的布局網(wǎng)格布局更適用滑沧。
基本概念&術(shù)語
Flexbox是一整個模塊,并非單一的一個屬性巍实,它涉及的東西比較多滓技,包括一系列屬性。其中一些屬性是用在容器(父元素棚潦,即伸縮容器)上的令漂,其他一些屬性則是用在子元素(伸縮項目)上的。
如果說常規(guī)布局是基于塊與行內(nèi)元素的流向的,那么flex布局則是基于“flex流向”的叠必。請看來自w3c規(guī)范中的這張圖荚孵,解釋了flex布局的主要思想:
![W3C flex](https://cdn.css-tricks.com/wp-content/uploads/2011/08/flexbox.png)
通常,伸縮項目的布局要么按照主軸(main axis)方向纬朝,從主軸起點(main-start)到主軸終點(main-end)收叶,要么按照交叉軸(cross axis)方向,從交叉軸起點(cross-start)到交叉軸終點(cross-end)。
- 主軸(main axis) - 伸縮容器的主軸玄组,是伸縮項目布局遵循的主要方向滔驾。注意:這個方向不一定是水平方向;它取決于“flex-direction”屬性的值(見下文);
- 主軸起點(main-start) | 主軸終點(main-end ) - 伸縮項目置于容器中,從主軸起點(main-start)到主軸終點(main-end);
- 主體大小(main size) - 伸縮項目的寬度或高度就是主體大小俄讹,不管主維度是哪個哆致。伸縮項目的主體大小要么是‘width’屬性,要么是‘height’屬性患膛,不管主維度是哪一個摊阀。
- 交叉軸(cross axis) - 與主軸垂直的軸稱為交叉軸(cross axis), 它的方向取決于主軸(main axis)的方向;
- 交叉軸起點(cross-start) | 交叉軸終點(cross-end) - 伸縮行填充著伸縮項目,并放置于伸縮容器中踪蹬,從伸縮容器交叉軸起點開始胞此,沿著交叉軸終點方向;
- 交叉方向大小(cross size) – 伸縮項目的寬度或高度就是交叉方向的大小,不管交叉維度是哪一個跃捣。交叉方向大小屬性要么是交叉軸維度的寬度要么是交叉軸維度的高度漱牵。
父元素(伸縮容器)屬性
display
display屬性用來定義伸縮容器,容器是行內(nèi)元素或者塊元素取決于給定的值疚漆,這個屬性開啟了容器內(nèi)所有直接子元素的flex上下文酣胀。
CSS:
.container {
display: flex; /*or inline-flex*/
}
注意:CSS columns對于伸縮容器沒有作用。
flex-direction
這個屬性建立了主軸方向娶聘,定義了伸縮項目在伸縮容器內(nèi)排列的方向闻镶。Flexbox是一個單一方向布局的概念⊥枭可以認(rèn)為伸縮項目或者沿水平方向或者沿垂直方向布局铆农。
CSS:
.container {
flex-direction: row | row-reverse | column | column-reverse;
}
- row(默認(rèn)值): 在‘ltr’排版中從左到右,‘rtl’排版中從右到左狡耻;
- row-reverse: 'ltr'中從右到左墩剖,‘ltr’中從左到右;
- column: 與row屬性一樣夷狰,但是是從頂部到底部涛碑;
- column-reverse: 與row-reverse一樣,但是是從底部到頂部孵淘。
flex-wrap
默認(rèn)情況下蒲障,伸縮項目會盡量排成一行。當(dāng)然,可以根據(jù)需要讓伸縮項目換行來改變它揉阎。此時庄撮,方向也很重要,它決定了下一行堆疊的方向毙籽。
CSS:
.container {
flex-wrap: nowrap | wrap | wrap-reverse;
}
- nowrap(默認(rèn)):單行模式/'ltr'中從左到右洞斯,'rtl'中從右到左;
- wrap: 多行模式/'ltr'中從左到右坑赡,'rtl'中從右到左
- wrap-reverse: 多行模式/'ltr'中從右到左烙如,'rtl'中從左到右;
flex-flow(適用于:伸縮容器毅否,也就是父元素)
這是'flex-direction'和 'flex-wrap'屬性的快捷形式亚铁,它同時定義了伸縮容器的主軸和交叉軸。默認(rèn)值是row nowrap螟加。
CSS:
flex-flow: <'flex-direction'> || <'flex-wrap'>
justify-content
justify-content定義了沿著主軸的排列方式徘溢。當(dāng)一行中的所有伸縮項目都不能再伸縮時,或者能伸縮但已經(jīng)達到了自身最大尺寸時捆探,這個屬性負責(zé)分配剩余的自由空間然爆。同時它也能在溢出時對排列元素進行一定的控制。
CSS:
.container {
justify-content: flex-start | flex-end | center | space-between | space-around
}
- flex-start(默認(rèn)值):伸縮項目朝著起點方向緊湊排列黍图;
- flex-end: 伸縮項目朝著終點方向緊湊排列曾雕;
- space-between: 伸縮項目在一行中平均分配,第一個項目在起點處助被,最后一個項目在終點處剖张;
- space-around: 伸縮項目兩側(cè)的空間保持相等,在一行中平均分配恰起。值得注意的是在視覺上修械,一個項目兩邊的空間是不相等的趾牧,因為所有項目都是在自身的兩邊分配了相等的空間检盼。第一個項目在容器邊緣分配得到一份空間,但是第二個項目的左邊會分得兩份空間翘单,因為它自身的也有一份分配的空間吨枉。
align-items
align-items定義了伸縮項目沿著交叉軸當(dāng)前方向的布局方式『逦撸可以把它看成交叉軸方向的justify-content版本貌亭。
CSS:
.container {
align-items: flex-start | flex-end | center | baseline | stretch;
}
- flex-start: 伸縮項目的起點放置在交叉軸線的起點上;
- flex-end: 伸縮項目的終點放置在交叉軸線的終點上认臊;
- center: 伸縮項目置于交叉軸線的中心圃庭;
- baseline: 伸縮項目按照他們的基線排列;
- stetch(默認(rèn)): 拉伸以填滿容器(仍然遵循min-width/max-width)
align-content
align-content定義了伸縮容器當(dāng)在交叉軸上有多余空間時的排列線,和主軸方向上justify-content排列伸縮項目類似剧腻。
注意:這個屬性在只有一行伸縮項目時無效拘央。
CSS:
.container {
algin-content: flex-start | flex-end | center | space-between | space-around | stretch;
}
- flex-start: 緊鄰容器起始排列描沟;
- flex-end: 緊鄰容器終點排列林艘;
- center: 排列在容器中間;
- space-between: 平均分配梢杭,第一行在容器起始處而最后一行在容器末尾處儒旬;
- space-around: 平均分配栏账,每行兩邊距離相等;
- stretch(默認(rèn)值): 拉伸項目來占據(jù)剩余空間栈源;
子元素屬性(伸縮項目)
order
默認(rèn)情況下挡爵,伸縮項目按照文檔流出現(xiàn)的先后順序排列。但order屬性可以控制在伸縮容器內(nèi)的顯示順序凉翻。
CSS:
.item {
order: <integer>;
}
flex-grow
flex-grow定義了伸縮項目必要時擴展的能力了讨。它接受一個無單位的值作為比例。它指定了伸縮容器內(nèi)伸縮項目能伸展的可用空間的大小制轰。
如果所有伸縮項目的flex-grow屬性設(shè)置為1前计,容器中剩余空間會被均等分配給所有子元素。如果一個子元素的flex-grow設(shè)置為2垃杖,那么它占據(jù)的剩余空間中會是其他子元素占據(jù)空間的兩倍男杈。
CSS:
.item {
flex-grow: <number>; /*default 0*/
}
負數(shù)無效。
flex-shrink
flex-shrink定義了伸縮項目根據(jù)需要收縮的能力调俘。
.item {
flex-shrink: <number>; /*default 1*/
}
負數(shù)無效伶棒。
flex-basis
定義了元素在剩余空間被分配之前的默認(rèn)大小。它的值可以是長度(例如20%彩库, 5rem等)肤无,也可以是關(guān)鍵詞。'auto'表明元素的大小取決于元素的寬度或高度屬性(臨時由main-size屬性決定)骇钦。'content'表明元素大小取決于伸縮項目內(nèi)容的大小-目前尚不支持宛渐,因此max-content,min-content,fit-content這些兄弟屬性較難測試和分析。
CSS:
.item {
flex-basis: <length> | auto; /*default auto*/
}
如果設(shè)置為0眯搭,內(nèi)容區(qū)域周圍的多余空間將不被考慮窥翩,如果設(shè)置為auto, 多余空間會基于flex-grow值來分配。參考下圖鳞仙。
flex
這是結(jié)合flex-grow,flex-shrink,flex-basis屬性的簡易寫法寇蚊。第二個屬性flex-shrink和第三個屬性flex-basis是可選的。默認(rèn)值是0 1 auto;
.item {
flex:none | [ <'flex-grow'> <'flex-shrink'> ? || <'flex-basis'> ]
}
推薦使用這個快捷形式的屬性棍好,比逐個設(shè)置屬性好用仗岸。它能自動設(shè)置所有屬性的值允耿。
align-self
允許默認(rèn)對齊方式(或者由align-items定義的對齊方式)能被單個伸縮項目覆蓋。
CSS:
.item {
align-self: auto | flex-start | flex-end | center | baseline | stretch;
}
注意:float,clear,vertical-align屬性對伸縮項目沒有作用扒怖。
Examples
我們先從一個非常簡單的例子開始右犹,解決一個最常見的問題:居中。使用flexbox你會發(fā)現(xiàn)簡直不能更容易了姚垃。
CSS:
.parent {
display: flex;
height: 300px; /*Or whatever*/
}
.child {
width: 100px; /*Or whatever*/
height: 100px; /*Or whatever*/
margin: auto; /*Magic! */
}
這依賴于一個特性:伸縮容器里的元素的margin值如果設(shè)置了'auto',能自動均衡容器中剩余的空間积糯。所以在垂直方向也設(shè)置了auto后掂墓,能使得伸縮項目在兩個軸線方向上都完美居中。
現(xiàn)在看成,讓我們來使用更多屬性君编。考慮有一個有6個條目的列表川慌,每一個都是固定大小的吃嘿,但他們可以被調(diào)整大小的。我們希望它們能平均地分布在水平軸上梦重,這樣當(dāng)我們調(diào)整瀏覽器時兑燥,依然能良好地顯示(不使用媒體查詢)。
.flex-container {
/*首先創(chuàng)建一個伸縮容器*/
display: flex;
/*然后定義伸縮流方向琴拧,并且伸縮項目能換行
* 記住這個設(shè)置等同于下面這兩個設(shè)置:
* flex-direction: row;
* flex-wrap: wrap;
*/
flex-flow: row wrap;
/*然后定義剩余空間如何分配*/
justify-content: space-around;
}
好了降瞳。剩下的僅僅是樣式的問題了。
下面是一個闡述這個屬性的具體例子蚓胸。試試去CodePen上查看挣饥,再調(diào)整瀏覽器窗口看看會發(fā)生什么。
HTML:
<ul class="flex-container">
<li class="flex-item">1</li>
<li class="flex-item">2</li>
<li class="flex-item">3</li>
<li class="flex-item">4</li>
<li class="flex-item">5</li>
<li class="flex-item">6</li>
</ul>
SCSS:
@import "compass/css3";
.flex-container {
padding: 0;
margin: 0;
list-style: none;
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
-webkit-flex-flow: row wrap;
justify-content: space-around;
}
.flex-item {
background: tomato;
padding: 5px;
width: 200px;
height: 150px;
margin-top: 10px;
line-height: 150px;
color: white;
font-weight: bold;
font-size: 3em;
text-align: center;
}
這是在PC正常顯示屏幕下的效果(瀏覽器寬度約為1190px)的效果:
縮小瀏覽器沛膳,6個盒子的排列會隨瀏覽器寬度的大小進行調(diào)整扔枫,這是瀏覽器寬度小于約700px時的效果:
隨著瀏覽器繼續(xù)縮小,最終6個盒子會變?yōu)橹饌€縱向排列的布局形式锹安。
再試試別的屬性短荐。設(shè)想網(wǎng)站頂部有一個靠右對齊的導(dǎo)航,我們希望它在中等大小的屏幕和單一欄目的小屏幕上都居中顯示八毯。非常容易:
CSS:
/* Large */
.navigation {
display: flex;
flex-flow: row wrap;
/* This aligns items to the end line on main-axis */
justify-content: flex-end;
}
/* Medium screens */
@media all and (max-width: 800px) {
.navigation {
/* When on medium sized screens, we center it by evenly distributing empty space around items */
justify-content: space-around;
}
}
/* Small screens */
@media all and (max-width: 500px) {
.navigation {
/* On small screens, we are no longer using row direction but column */
flex-direction: column;
}
}
具體示例代碼:
HTML:
<ul class="navigation">
<li><a href="#">Home</a></li>
<li><a href="#">About</a></li>
<li><a href="#">Products</a></li>
<li><a href="#">Contact</a></li>
</ul>
SCSS:
@import "compass/css3";
.navigation {
list-style: none;
margin: 0;
background: deepskyblue;
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
-webkit-flex-flow: row wrap;
justify-content: flex-end;
}
.navigation a {
text-decoration: none;
display: block;
padding: 1em;
color: white;
}
.navigation a:hover {
background: darken(deepskyblue, 2%);
}
@media all and (max-width: 800px) {
.navigation {
justify-content: space-around;
}
}
@media all and (max-width: 600px) {
.navigation {
-webkit-flex-flow: column wrap;
flex-flow: column wrap;
padding: 0;
}
.navigation a {
text-align: center;
padding: 10px;
border-top: 1px solid rgba(255,255,255,0.3);
border-bottom: 1px solid rgba(0,0,0,0.1);
}
.navigation li:last-of-type a {
border-bottom: none;
}
}
上述示例結(jié)果圖:
縮小瀏覽器搓侄,寬度小于等于600px時:
現(xiàn)在讓我們再嘗試一下伸縮項目上的屬性瞄桨!比如一個手機上的三欄布局话速,其中頭部和尾部占據(jù)全屏。并且不管它們在文檔流的順序芯侥。
CSS:
.wrapper {
display: flex;
flex-flow: row wrap;
}
/* We tell all items to be 100% width */
.header, .main, .nav, .aside, .footer {
flex: 1 100%;
}
/* We rely on source order for mobile-first approach
* in this case:
* 1. header
* 2. nav
* 3. main
* 4. aside
* 5. footer
*/
/* Medium screens */
@media all and (min-width: 600px) {
/* We tell both sidebars to share a row */
.aside { flex: 1 auto; }
}
/* Large screens */
@media all and (min-width: 800px) {
/* We invert order of first sidebar and main
* And tell the main element to take twice as much width as the other two sidebars
*/
.main { flex: 2 0px; }
.aside-1 { order: 1; }
.main { order: 2; }
.aside-2 { order: 3; }
.footer { order: 4; }
}
具體示例代碼:
HTML:
<div class="wrapper">
<header class="header">Header</header>
<article class="main">
<p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.</p>
</article>
<aside class="aside aside-1">Aside 1</aside>
<aside class="aside aside-2">Aside 2</aside>
<footer class="footer">Footer</footer>
</div>
SCSS:
@import "compass/css3";
.wrapper {
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
-webkit-flex-flow: row wrap;
flex-flow: row wrap;
font-weight: bold;
text-align: center;
}
.wrapper > * {
padding: 10px;
flex: 1 100%;
}
.header {
background: tomato;
}
.footer {
background: lightgreen;
}
.main {
text-align: left;
background: deepskyblue;
}
.aside-1 {
background: gold;
}
.aside-2 {
background: hotpink;
}
@media all and (min-width: 600px) {
.aside { flex: 1 auto; }
}
@media all and (min-width: 800px) {
.main { flex: 3 0px; }
.aside-1 { order: 1; }
.main { order: 2; }
.aside-2 { order: 3; }
.footer { order: 4; }
}
body {
padding: 2em;
}
上述示例結(jié)果圖:
縮小瀏覽器泊交,寬度小于等于600px時:
Flexbox 前綴
Flexbox需要書寫較多的前綴以支持大多數(shù)瀏覽器下的顯示乳讥。這里指的不僅僅包括(在屬性前)加入瀏覽器的前綴,實際上還包含加入其它一些不一樣的屬性和屬性值廓俭。這是因為Flexbox規(guī)范一直在向前發(fā)展云石,先后創(chuàng)建了"old", "tweener"和"new"幾個版本。
也許更好的處理辦法是使用新語法研乒,并通過Autoprefixer來運行你的CSS汹忠。
這里給出一個Sass @mixin的示例可以幫助解決一些前綴問題,或許可以給你提供一些思路:
SCSS:
@mixin flexbox() {
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
}
@mixin flex($values) {
-webkit-box-flex: $values;
-moz-box-flex: $values;
-webkit-flex: $values;
-ms-flex: $values;
flex: $values;
}
@mixin order($val) {
-webkit-box-ordinal-group: $val;
-moz-box-ordinal-group: $val;
-ms-flex-order: $val;
-webkit-order: $val;
order: $val;
}
.wrapper {
@include flexbox();
}
.item {
@include flex(1 200px);
@include order(2);
}
相關(guān)屬性
- A Complete Guide to Grid
- Almanac entries on Grid properties, like grid-row / grid-column
其它資源
- Flexbox in the CSS specifications
- Flexbox at MDN
- Flexbox at Opera
- Diving into Flexbox by Bocoup
- Mixing syntaxes for best browser support on CSS-Tricks
- Flexbox by Raphael Goetter (FR)link
- Flexplorer by Bennett Feely
Bugs
Flexbox 并非沒有bug. 我看過的最好的收集這方面bug的是Philip Walton and Greg Whitworth的Flexbugs雹熬。 這是一個開源的跟蹤問題的地方宽菜。
瀏覽器支持
這個要區(qū)分一下flexbox的版本:
- (new)表明規(guī)范上最新的語法(例如:display:flex;);
- (tweener)表明是2011年舊版的非官方語法(例如:display: flexbox;);
- (old)表明是2009年舊版語法(例如:display:box)竿报。
Blackberry瀏覽器10+支持新版語法铅乡。
更多關(guān)于如何混合使用語法來最好地讓flexbox得到瀏覽器的支持,請參考這篇文章或這篇