Flex 布局教程:語法篇

作者: 阮一峰

日期: 2015年7月10日

騰訊課堂 NEXT 學院

網頁布局(layout)是 CSS 的一個重點應用。

布局的傳統解決方案,基于盒狀模型,依賴 display 屬性 + position屬性 + float屬性。它對于那些特殊布局非常不方便,比如,垂直居中就不容易實現。

2009年,W3C 提出了一種新的方案----Flex 布局,可以簡便、完整、響應式地實現各種頁面布局。目前,它已經得到了所有瀏覽器的支持,這意味著,現在就能很安全地使用這項功能。

Flex 布局將成為未來布局的首選方案。本文介紹它的語法,下一篇文章給出常見布局的 Flex 寫法。網友 JailBreak 為本文的所有示例制作了 Demo,也可以參考。

以下內容主要參考了下面兩篇文章:A Complete Guide to FlexboxA Visual Guide to CSS3 Flexbox Properties

一、Flex 布局是什么?

Flex 是 Flexible Box 的縮寫,意為"彈性布局",用來為盒狀模型提供最大的靈活性。

任何一個容器都可以指定為 Flex 布局。


.box{
  display: flex;
}

行內元素也可以使用 Flex 布局。


.box{
  display: inline-flex;
}

Webkit 內核的瀏覽器,必須加上-webkit前綴。


.box{
  display: -webkit-flex; /* Safari */
  display: flex;
}

注意,設為 Flex 布局以后,子元素的floatclearvertical-align屬性將失效。

二、基本概念

采用 Flex 布局的元素,稱為 Flex 容器(flex container),簡稱"容器"。它的所有子元素自動成為容器成員,稱為 Flex 項目(flex item),簡稱"項目"。

容器默認存在兩根軸:水平的主軸(main axis)和垂直的交叉軸(cross axis)。主軸的開始位置(與邊框的交叉點)叫做main start,結束位置叫做main end;交叉軸的開始位置叫做cross start,結束位置叫做cross end

項目默認沿主軸排列。單個項目占據的主軸空間叫做main size,占據的交叉軸空間叫做cross size

三、容器的屬性

以下6個屬性設置在容器上。

  • flex-direction
  • flex-wrap
  • flex-flow
  • justify-content
  • align-items
  • align-content

3.1 flex-direction屬性

flex-direction屬性決定主軸的方向(即項目的排列方向)。


.box {
  flex-direction: row | row-reverse | column | column-reverse;
}

它可能有4個值。

  • row(默認值):主軸為水平方向,起點在左端。
  • row-reverse:主軸為水平方向,起點在右端。
  • column:主軸為垂直方向,起點在上沿。
  • column-reverse:主軸為垂直方向,起點在下沿。

3.2 flex-wrap屬性

默認情況下,項目都排在一條線(又稱"軸線")上。flex-wrap屬性定義,如果一條軸線排不下,如何換行。


.box{
  flex-wrap: nowrap | wrap | wrap-reverse;
}

它可能取三個值。

(1)nowrap(默認):不換行。

(2)wrap:換行,第一行在上方。

(3)wrap-reverse:換行,第一行在下方。

3.3 flex-flow

flex-flow屬性是flex-direction屬性和flex-wrap屬性的簡寫形式,默認值為row nowrap


.box {
  flex-flow: <flex-direction> || <flex-wrap>;
}

3.4 justify-content屬性

justify-content屬性定義了項目在主軸上的對齊方式。


.box {
  justify-content: flex-start | flex-end | center | space-between | space-around;
}

它可能取5個值,具體對齊方式與軸的方向有關。下面假設主軸為從左到右。

  • flex-start(默認值):左對齊
  • flex-end:右對齊
  • center: 居中
  • space-between:兩端對齊,項目之間的間隔都相等。
  • space-around:每個項目兩側的間隔相等。所以,項目之間的間隔比項目與邊框的間隔大一倍。

3.5 align-items屬性

align-items屬性定義項目在交叉軸上如何對齊。


.box {
  align-items: flex-start | flex-end | center | baseline | stretch;
}

它可能取5個值。具體的對齊方式與交叉軸的方向有關,下面假設交叉軸從上到下。

  • flex-start:交叉軸的起點對齊。
  • flex-end:交叉軸的終點對齊。
  • center:交叉軸的中點對齊。
  • baseline: 項目的第一行文字的基線對齊。
  • stretch(默認值):如果項目未設置高度或設為auto,將占滿整個容器的高度。

3.6 align-content屬性

align-content屬性定義了多根軸線的對齊方式。如果項目只有一根軸線,該屬性不起作用。


.box {
  align-content: flex-start | flex-end | center | space-between | space-around | stretch;
}

該屬性可能取6個值。

  • flex-start:與交叉軸的起點對齊。
  • flex-end:與交叉軸的終點對齊。
  • center:與交叉軸的中點對齊。
  • space-between:與交叉軸兩端對齊,軸線之間的間隔平均分布。
  • space-around:每根軸線兩側的間隔都相等。所以,軸線之間的間隔比軸線與邊框的間隔大一倍。
  • stretch(默認值):軸線占滿整個交叉軸。

四、項目的屬性

以下6個屬性設置在項目上。

  • order
  • flex-grow
  • flex-shrink
  • flex-basis
  • flex
  • align-self

4.1 order屬性

order屬性定義項目的排列順序。數值越小,排列越靠前,默認為0。


.item {
  order: <integer>;
}

4.2 flex-grow屬性

flex-grow屬性定義項目的放大比例,默認為0,即如果存在剩余空間,也不放大。


.item {
  flex-grow: <number>; /* default 0 */
}

如果所有項目的flex-grow屬性都為1,則它們將等分剩余空間(如果有的話)。如果一個項目的flex-grow屬性為2,其他項目都為1,則前者占據的剩余空間將比其他項多一倍。

4.3 flex-shrink屬性

flex-shrink屬性定義了項目的縮小比例,默認為1,即如果空間不足,該項目將縮小。


.item {
  flex-shrink: <number>; /* default 1 */
}

如果所有項目的flex-shrink屬性都為1,當空間不足時,都將等比例縮小。如果一個項目的flex-shrink屬性為0,其他項目都為1,則空間不足時,前者不縮小。

負值對該屬性無效。

4.4 flex-basis屬性

flex-basis屬性定義了在分配多余空間之前,項目占據的主軸空間(main size)。瀏覽器根據這個屬性,計算主軸是否有多余空間。它的默認值為auto,即項目的本來大小。


.item {
  flex-basis: <length> | auto; /* default auto */
}

它可以設為跟widthheight屬性一樣的值(比如350px),則項目將占據固定空間。

4.5 flex屬性

flex屬性是flex-grow, flex-shrinkflex-basis的簡寫,默認值為0 1 auto。后兩個屬性可選。


.item {
  flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
}

該屬性有兩個快捷值:auto (1 1 auto) 和 none (0 0 auto)。

建議優先使用這個屬性,而不是單獨寫三個分離的屬性,因為瀏覽器會推算相關值。

4.6 align-self屬性

align-self屬性允許單個項目有與其他項目不一樣的對齊方式,可覆蓋align-items屬性。默認值為auto,表示繼承父元素的align-items屬性,如果沒有父元素,則等同于stretch


.item {
  align-self: auto | flex-start | flex-end | center | baseline | stretch;
}

該屬性可能取6個值,除了auto,其他都與align-items屬性完全一致。

(完)

留言(210條)

坐個沙發, ie10的普及率還有待觀望啊..

四、容器的屬性,應該是“項目的屬性”吧?

@王永起,

謝謝指出,已經改正。

好文章,簡單明了。

聽說博主是搞經濟出身的,居然沒有一篇經濟類的文章,真想問博主炒股不?

現在介紹有點晚了吧-_-#

贊,終于在您這兒看明白了,謝謝!

謝謝分享,新的開發技術,使我們開發者越來越方便了。

flex布局除了響應不同頁面之外,還有什么優點呢?

簡單明了,配圖很贊!

看標題還以為是講編譯器,興沖沖點進來。不過并不失望,最近做課程設計正好需要這個。博主配圖好漂亮。

屬性名字起的很別扭哈。

多謝,很不錯的文章,一直都用Polymer預定義的flex排版("layout horizontal center"這樣),看完才知道原來flex還有其它這些功能。

wow! 這傢伙太實用了!
grid layout framework 不知道是否會重寫了

長見識了

進了阿里,寫文章不精致了。

阮大神啊,flex-basis,這個屬性的作用是優先級高于width的width嗎?它除了設置寬度的作用還有什么用處?(寬度指的是水平方向,如果是垂直方向就是height了)。

阮老師,那個item的flex-grow屬性,我寫了個demo
CSS:
body{margin:0;}
ul,li{margin:0; padding:0;}
li{list-style-type:none;}
#list{border:2px solid gold; height:500px; display:flex; flex-direction:row;}
#list li{font-family:"microsoft yahei"; font-size:50px; background:#C00; color:#fff; margin:2px; flex-grow:1;}
#list li:nth-child(2){flex-grow:2;}

<ul id="list">
<li>test1</li>
<li>test2</li>
<li>test3</li>
</ul>
結果第2個li所占的寬度并不是其它li的2倍,為什么呢?比其它兩個要大,但不足2倍。

寫的非常好!我用來弄我的 zhihu-daily-reader 布局了,嘿嘿!

@longfei:

flex-basis都設為0,因為flex-grow定義的是,剩余空間分配的比例關系。

兼容性是大問題!

Nice!看了這篇文后我寫了個基于flex的柵格布局庫 flex-layout
https://github.com/Coffcer/flex-layout

有了這個以后可以真正的告別table了。

阮老師,align-items:flex-start和align-items:flex:end 的圖弄反了

您發表的每篇文章,都是那么的善于理解,一目了然,看著很輕松并且感覺學到了知識;非常感覺,看了您的很多文章覺得不評論支持一下過意不去.

阮老師,您好,我是0基礎開始學習flex,今天看了你的這篇博文,發現有個地方好像你給弄反了。就是justify-content和align-items這兩個屬性。我試過了,其實,前者是設置項目在交叉軸上的對齊方式的,而后者是設置項目在主軸上的對齊方式的。

引用阮一峰的發言:

@longfei:

flex-basis都設為0,因為flex-grow定義的是,剩余空間分配的比例關系。

那請問不設為0的時候它是多少呢?看您的原文里是“auto”,但這個auto是怎么計算的?

能不能好好解釋下flex-grow flex-shrink flex-basis的用法,網上的各種解釋感覺都不好理解

想學習flex的相關知識,找了幾篇文章大概看了一下,覺得都不滿意,突然在google上發現文章后面帶有阮老師標識的文章,于是默默把其他的幾篇文章的tab都關了

引用廣州哈哥的發言:

阮老師,您好,我是0基礎開始學習flex,今天看了你的這篇博文,發現有個地方好像你給弄反了。就是justify-content和align-items這兩個屬性。我試過了,其實,前者是設置項目在交叉軸上的對齊方式的,而后者是設置項目在主軸上的對齊方式的。

我不知道自己理解的對不對,但是我覺得主軸的話也就是項目的排布方向,加入是水平排布,那么交叉軸即是垂直方向的,設置align-items:stretch;的話確實是在垂直方向上拉伸的,那align-itmes就是設置交叉軸的吧

如果我把子元素按照固定像素來分配,是否可以(就是替換現在的float布局),還是子元素用width嗎?

很好用的布局,學習了!

多次過來學習,非常感謝。

flex-direction 圖片順序和文字順序是不是不一樣呀。

原來是css-tricks上的文章翻譯過來的,為什么不做說明
傳送門:https://css-tricks.com/snippets/css/a-guide-to-flexbox/

我每次寫項目的時候也考慮過用flex布局,但是有的手機上顯示不謙容。我到現在都不知道該怎么解決。

@mixin flex(){
display: -webkit-box; /* OLD - iOS 6-, Safari 3.1-6 */
display: -moz-box; /* OLD - Firefox 19- (buggy but mostly works) */
display: -ms-flexbox; /* TWEENER - IE 10 */
display: -webkit-flex; /* NEW - Chrome */
display: flex; /* NEW, Spec - Opera 12.1, Firefox 20+ */
}
body{
@include flex();
flex: 1;
justify-content: center;
align-items: center;
flex-direction: column;
}
#main{
@include flex();
height: 400px;
width: 1200px;
background-color: red;
}
div #main 并不會居中

想問一下,微信的內置瀏覽器是不是不支持這個屬性啊。。我寫了一個。在電腦上用chrome瀏覽器有用。在微信上沒用了

引用lomin的發言:

想問一下,微信的內置瀏覽器是不是不支持這個屬性啊。。我寫了一個。在電腦上用chrome瀏覽器有用。在微信上沒用了

微信的話用display: box

感謝科普,跟著demo學習下來很有收獲。

移動端的兼容應該沒有什么大問題了吧。可以在團隊開發時候推廣了吧?

引用longfei的發言:

阮老師,那個item的flex-grow屬性,我寫了個demo
CSS:
body{margin:0;}
ul,li{margin:0; padding:0;}
li{list-style-type:none;}
#list{border:2px solid gold; height:500px; display:flex; flex-direction:row;}
#list li{font-family:"microsoft yahei"; font-size:50px; background:#C00; color:#fff; margin:2px; flex-grow:1;}
#list li:nth-child(2){flex-grow:2;}

<ul id="list">
<li>test1</li>
<li>test2</li>
<li>test3</li>
</ul>
結果第2個li所占的寬度并不是其它li的2倍,為什么呢?比其它兩個要大,但不足2倍。

這里是你理解錯了,3個 li 平分下來每個是1/3。
你想實現的2個相等,1個寬度是其他2個的兩倍實際上就是4個 li 平分,其中2個合并成1個,所以每個 li 是1/4,也就是#list li:nth-child(2){flex-grow:3;}

引用巫婆的發言:

我每次寫項目的時候也考慮過用flex布局,但是有的手機上顯示不謙容。我到現在都不知道該怎么解決。

不兼容可以用 display:box 試試看

引用廣州哈哥的發言:

阮老師,您好,我是0基礎開始學習flex,今天看了你的這篇博文,發現有個地方好像你給弄反了。就是justify-content和align-items這兩個屬性。我試過了,其實,前者是設置項目在交叉軸上的對齊方式的,而后者是設置項目在主軸上的對齊方式的。

是你自己弄錯了好吧~

http://flexboxin5.com/
博士哥與我本科生一站

3.1 節關于 flex-direction 的部分,代碼和圖不是一一對應的。

我就看看能不能發表成功

flex-wrap: wrap;
在微信內置瀏覽器中無效!

引用cc的發言:

flex-wrap: wrap;
在微信內置瀏覽器中無效!


autoprefixer({browsers: ['last 10 version']})
這樣都無效!

引用cc的發言:


autoprefixer({browsers: ['last 10 version']})
這樣都無效!

換個寫法吧,歷史的倒退!shit!

謝謝老師講解,之前的一些困惑現在看明白了

厲害

棒棒的

阮老師,item翻譯成項目感覺怪怪的,沒有直接用item好理解點

一峰老師,我簡直不能更加感激您,也非常崇拜您。哇唔,我猜您已經將技術看作是藝術了吧!!!現在好多程序員生活都比較枯燥(我猜他們和我一樣,嘻嘻)(每天都很忙,技術更新快,提升自己的技術還要完成項目),靈魂也很干涸(因為很忙,所以太少的時間感受生活,去吸取技術之外的東西來滋養我們的靈魂)。然而每次看您的博文,我就感覺自己經歷了一場與藝術的邂逅,不僅學習了知識,還讓我得以短暫的放松,讓我的心靈經歷了一次奇妙的旅行,然后再元氣滿滿,整裝繼續上路。非常感謝您的分享,您無私的指引,以及心靈的關懷。

引用阮一峰的發言:

@longfei:

flex-basis都設為0,因為flex-grow定義的是,剩余空間分配的比例關系。

flex-basis設為0,那項目的初始大小是多大?

很清楚,一目了然

請問flex在任何瀏覽器都能用嗎,有沒有兼容性的問題

老師的文章寫得總是那么易懂

圖片很好!點贊。flex在安卓原生開發上也有了支持庫。https://github.com/google/flexbox-layout

前端自學者受用了,謝謝!

好的老師不僅要學會知識,還要講得通俗易懂,阮老師就是這樣的老師

flex-direction這個屬性的默認值是row嗎?這樣的話是不是默認情況下,item就是橫向排列了。但是。我在做的過程中發現,如果不寫flex-direction屬性的話,item是豎向排列的

還是沒看明白align-content跟justify-content的區別 :(

老師,怎樣使用flex布局使得兩個組件的一部分重疊

引用longfei的發言:

阮老師,那個item的flex-grow屬性,我寫了個demo
CSS:
body{margin:0;}
ul,li{margin:0; padding:0;}
li{list-style-type:none;}
#list{border:2px solid gold; height:500px; display:flex; flex-direction:row;}
#list li{font-family:"microsoft yahei"; font-size:50px; background:#C00; color:#fff; margin:2px; flex-grow:1;}
#list li:nth-child(2){flex-grow:2;}

<ul id="list">
<li>test1</li>
<li>test2</li>
<li>test3</li>
</ul>
結果第2個li所占的寬度并不是其它li的2倍,為什么呢?比其它兩個要大,但不足2倍。

好像是按多余空間算的

玉峰老師的博客真寫的通熟易懂 點贊一個

引用石海偉的發言:

好像是按多余空間算的

一共有三個li元素,flex-grow:2即當前元素寬度為 父元素的2/3 并不是其他元素的兩倍

引用longfei的發言:

阮老師,那個item的flex-grow屬性,我寫了個demo
CSS:
body{margin:0;}
ul,li{margin:0; padding:0;}
li{list-style-type:none;}
#list{border:2px solid gold; height:500px; display:flex; flex-direction:row;}
#list li{font-family:"microsoft yahei"; font-size:50px; background:#C00; color:#fff; margin:2px; flex-grow:1;}
#list li:nth-child(2){flex-grow:2;}

<ul id="list">
<li>test1</li>
<li>test2</li>
<li>test3</li>
</ul>
結果第2個li所占的寬度并不是其它li的2倍,為什么呢?比其它兩個要大,但不足2倍。

一共有三個li元素,flex-grow:2即當前元素寬度為 父元素的2/3 并不是其他元素的兩倍

默認好像是flex-wrap: wrap;

請問: 針對此屬性 justify-content: space-between 3個元素為一行排列,最后多余的兩個多余的元素如何讓它靠左排布,事實上是左右排布了,表面看就是中間空了個元素,請看demo

1 2 3 4 5

.container {width: 400px;display: flex;justify-content: space-between;flex-flow: row wrap;
}

span {width: 110px;background-color: #f60;border-radius: 5px;margin-top: 10px;padding: 10px;
}

引用卓的發言:

請問: 針對此屬性 justify-content: space-between 3個元素為一行排列,最后多余的兩個多余的元素如何讓它靠左排布,事實上是左右排布了,表面看就是中間空了個元素,請看demo


1
2
3
4
5


.container {width: 400px;display: flex;justify-content: space-between;flex-flow: row wrap;
}

span {width: 110px;background-color: #f60;border-radius: 5px;margin-top: 10px;padding: 10px;
}


我只想說這個css3的新屬性flex局勢一個巨坑,誰用誰知道。安卓低端機完全不支持

目前發現一個問題,和@卓貌似是一個問題:
父元素:justify-content: space-between
在每排3個元素一共5個元素情況下,第五個元素怎么實現居中?
現在的效果是第1、2、3元素正常,4元素居左,5元素居右

UC瀏覽器設置flex:1;盒子里面加入文字 彈性盒子會被撐開要怎么解決,其他瀏覽器都是正常的

不得不說,看了半天外文網站, 不如看十分鐘阮大師的。

"Webkit內核的瀏覽器,必須加上-webkit前綴。“, 我測試了下safari和chrome,都不需要的。

問下,支付寶是否已經有頁面部署了flex的布局? 似乎各大瀏覽器,除了chrome支持的都不是特別好,比如IE8就,FireFox46之前的,Safari9.1之前的都不支持

引用liangwang的發言:

"Webkit內核的瀏覽器,必須加上-webkit前綴。“, 我測試了下safari和chrome,都不需要的。

在ios8及以下的版本中就需要了

太好了,總算是弄明白了,謝謝博主!

怎么用flex實現footer一直存在在屏幕下方 不隨滾動消失

引用Silvers · Rayleigh的發言:

這里是你理解錯了,3個 li 平分下來每個是1/3。
你想實現的2個相等,1個寬度是其他2個的兩倍實際上就是4個 li 平分,其中2個合并成1個,所以每個 li 是1/4,也就是#list li:nth-child(2){flex-grow:3;}


3也不行吧?

引用longfei的發言:

阮老師,那個item的flex-grow屬性,我寫了個demo
CSS:
body{margin:0;}
ul,li{margin:0; padding:0;}
li{list-style-type:none;}
#list{border:2px solid gold; height:500px; display:flex; flex-direction:row;}
#list li{font-family:"microsoft yahei"; font-size:50px; background:#C00; color:#fff; margin:2px; flex-grow:1;}
#list li:nth-child(2){flex-grow:2;}

<ul id="list">
<li>test1</li>
<li>test2</li>
<li>test3</li>
</ul>
結果第2個li所占的寬度并不是其它li的2倍,為什么呢?比其它兩個要大,但不足2倍。

是按剩余空間算的,因為你里面有文字,所以刨去了文字寬度,你去掉文字就好了

引用zhishaofei3的發言:

是按剩余空間算的,因為你里面有文字,所以刨去了文字寬度,你去掉文字就好了

這里是必須先除去每個元素實際占有的大小之后,然后按照你設置的比例來分配空間,h

還有默認空間應該是flex-grow: 1,而不是flex-grow: 0;

<ul id="list">
  <li>test1</li>
  <li>test2</li>
  <li>test3</li>
</ul>
body{margin:0;}
	ul,li{ margin:0; padding:0;}
	li{ list-style-type:none;}
	#list{ border:2px solid gold; height:500px; display:flex; flex-direction:row;}
	#list li {
		width: 120px;
	}
	#list li{font-family:"microsoft yahei"; font-size:50px; background:#C00; color:#fff; margin:2px; flex-grow:1;}
	#list li:nth-child(2){flex-grow:2;}
	#list li:nth-child(3){
		flex-grow: 0;
	}

你可以比較一下兩段代碼的不同

蘋果手機的IOS8系統不支持flex布局,有什么好方法嗎?

不錯,容易明白,大神就是大神

今天實踐過程中發現了一個理解誤區,就是剛開始把justify-content誤認為是指定水平對齊方式(其實針對的是主軸),而align-items是指定垂直對齊方式。而指定主軸需要用到flex-direction(默認為水平)。不過后來想想,假使指定主軸為豎直的話,那主軸和交叉軸是不是就是一樣了?還有那個align-content說的是針對多根軸線,是不是就意味著如果主軸指定為column,就是主軸和交叉軸一樣是一根線了,如果主軸為默認,那么當主軸和交叉軸的對齊方式一樣的話,直接用一個align-content屬性就ok了?

很明了,很直觀,感謝博主~

flex-direction: row | row-reverse | column | column-reverse;

這部分的描述和下面的配圖,容易誤導一些新手哈

可能會造成 row = 下圖第一個 依次的順序

“四、項目的屬性”這個標題的字體小了,之前同種標題都是,應該是H2

在我測試中有這樣的感覺,還請指正
1.當主軸設置的是水平方向時(row,row-reverse)方向還和容器的dir屬有關;
flex-direction 的方向是相對dir設置的方向來設置的.

2.交叉軸的方向(默認和主軸換行的方向一至),flex-wrap: wrap-reverse; 會改變交叉軸的方向

demo: http://sandbox.runjs.cn/show/zkqimsj5


引用phc的發言:

我不知道自己理解的對不對,但是我覺得主軸的話也就是項目的排布方向,加入是水平排布,那么交叉軸即是垂直方向的,設置align-items:stretch;的話確實是在垂直方向上拉伸的,那align-itmes就是設置交叉軸的吧

真的非常感謝!解決了從入行以來一直面臨的垂直居中的大問題,在很多應用場景中可以實現。雖然負面性還有待發掘,真的是非常感謝博主!!!

感謝阮老師無私教誨

以前一直對flex模糊不清,終于決定攻破它,打開了好幾篇教程,看完阮老師的后,徹底會用啦!謝謝您

我有個等高布局不懂,就是左邊有一張1000多px高的圖片,右邊為文字區域。

怎么讓其當右邊文字區域的高度小于瀏覽器高度時,左邊的圖片高度為瀏覽器高度,
當右邊文字區域的高度大于瀏覽器高度時,則左邊的圖片的高度為右邊文字區域的高度?

要求是:不用js控制,還有不能把左邊的圖片當背景圖來使用

flex-grow, flex-shrink,flex-basis可能不好理解,補充下,這里指的空間是主軸空間,是水平的還是垂直的,依flex-direction而定

引用zhishaofei3的發言:

是按剩余空間算的,因為你里面有文字,所以刨去了文字寬度,你去掉文字就好了

引用Silvers · Rayleigh的發言:

這里是你理解錯了,3個 li 平分下來每個是1/3。
你想實現的2個相等,1個寬度是其他2個的兩倍實際上就是4個 li 平分,其中2個合并成1個,所以每個 li 是1/4,也就是#list li:nth-child(2){flex-grow:3;}

你說的很對,博主沒有說清楚

引用chshouyu的發言:

現在介紹有點晚了吧-_-#

不晚,我就是剛剛來學習的,因為小程序出來了,學習一下布局

引用Silvers · Rayleigh的發言:

這里是你理解錯了,3個 li 平分下來每個是1/3。
你想實現的2個相等,1個寬度是其他2個的兩倍實際上就是4個 li 平分,其中2個合并成1個,所以每個 li 是1/4,也就是#list li:nth-child(2){flex-grow:3;}

flex-grow分的是剩余的空間你要看你內容之外的空間

引用廣州哈哥的發言:

阮老師,您好,我是0基礎開始學習flex,今天看了你的這篇博文,發現有個地方好像你給弄反了。就是justify-content和align-items這兩個屬性。我試過了,其實,前者是設置項目在交叉軸上的對齊方式的,而后者是設置項目在主軸上的對齊方式的。

沒有錯啊,你再試試看,或者是你理解錯了吧。

阮老師,在align-content屬性中,您說 `align-content屬性定義了多根軸線的對齊方式。如果項目只有一根軸線,該屬性不起作用。` 一開始我沒太看明白,后來才發現這里說的應該是多行的對齊方式。我覺得在這里用行代替軸線更容易解釋整個屬性。

四、項目的屬性 應該是h2標簽吧,現在用的是h3標簽

使用align-content屬性,如何定義多軸?
求html代碼,或者align-content的Demo

這篇是我看到講得最好的一篇

嘗試了一下flex+單行省略號,發現盒子被撐開好多。

您好,我試了一下align-content,將其設置成stretch,并不會把每行拉伸,填滿容器高度。而是在每行下面留有相同高度的空白。能否確認一下?

非常好~講的清楚明白

每次看到您的內容, 我嘴里默默來了一個句 阮大神~~~

每個例子都照著敲了一遍,真贊。敲完之后,對flex布局了解的也就差不多了。謝謝阮大神,如果不是你,我還困在MDN的文檔里,犯糊涂呢。哈哈哈

謝謝阮老師,您傳授給我們的知識讓我們收獲很多

"多根軸線的對齊方式" 是不是指出現了多行item的情況,每行一根軸線,多行item就有多根軸線?

瀏覽這篇文章就是一次賞心悅目的瀏覽體驗,配圖清爽明了,真希望我以后看到的文章都有這么好的瀏覽體驗

我測試加入了 align-items: flex-start; 子標簽加入了align-self: flex-end; 驚人的發現 在不同的瀏覽器 flex-end 和flex-start 效果不一樣 這要如何解決?我放在谷歌和Edege里 效果居然上下相反

老師寫的文章真的很清晰,期待您的續作。

老師的文章和配圖很贊!

總結的真好,條理清晰,便于理解和記憶。真是個有思想的人

仔細過了一遍真的很方便.

有事沒事就逛阮老師的博客,受益匪淺。

一講就懂,很棒,超棒,非常棒;
哪怕有些玩家吐槽進了阿里文章變得不精致了;這篇文章也遠比網上泛濫的各種云里霧里的資料有用得多。
感謝大大的分享√

將文章中提及的布局 全部實現了一遍,源碼:

https://github.com/JailBreakC/flex-box-demo

非常好的文章,詳細明了

@JailBreak:

贊! 我要把它加到教程里面。

我也來做點貢獻,看完阮一峰老師的教學文章,臨時做了個 flex 布局動態測試的 demo,支持 flex 所有的屬性測試,希望能對大家有所幫助

演示地址 : https://ihuangmx.gitbooks.io/front-demo/content/zen-flex-demo.html#flex-布局在線測試

源碼:https://github.com/ihuangmx/zen-flex-online

@阮一峰:

哈哈,多謝阮老師!

阮一峰老師的教學文章真的太棒了,感謝有您,指路明燈

實現過之后發現 3.1 flex-direction屬性 中的圖中的效果和下面的文字描述順序就不一致

阮老師,flex布局,左邊自適應,右邊固定寬,但當頁面縮小到一定比例后,左邊不在自適應了,而是右邊變小了,sapn的寬度好像不能一直按照70%的比例縮小下去



DOM3 event textInput

body{
padding:0;
margin:0;
font-size:0;
}
.box{
display: flex;
}
.d1{
flex:1;
border:1px solid blue;
margin-right:15px;
}
.d2{
width:300px;
border:1px solid red;
min-height:100vh;
}
.span{
display: inline-block;
width:70%;
border:1px solid red;
overflow: hidden;
white-space: nowrap;
text-overflow:ellipsis;
font-size:12px;
}





Loommodi cumque us repellendus unde veritatis? Beatae doloribus





3.1 flex-direction屬性

樣式中 屬性 和 下面示意圖 中的順序 不一致。 有閱讀誤導。

圖中順序 對應為:
flex-direction: column-reverse | column | row | row-reverse;

阮大神我發現flex-basis這個屬性好像并不是主軸所占空間,如果我將主軸方向定為垂直排列flex-direction: column;再給他定義flex-basis的屬性,結果我發現只有水平方向的大小在變,垂直方向無效果

看完以后,加深了印象

謝謝您的教程
整整兩年了 即使到現在依然是非常好的react-native中文入門教程

真心感謝 阮一峰同學

引用小小柴的發言:

阮大神我發現flex-basis這個屬性好像并不是主軸所占空間,如果我將主軸方向定為垂直排列flex-direction: column;再給他定義flex-basis的屬性,結果我發現只有水平方向的大小在變,垂直方向無效果

主軸就是水平方向的啊,垂直方向的叫做交叉軸。

設為 Flex 布局以后,子元素的float屬性沒有失效呀。。。

我自己看錯了。。。[允悲],設為 Flex 布局以后,子元素的float、clear和vertical-align屬性將失效是OK的。

我發現這個文章的亮點現在在評論區了,從15年的7月到17年的7月,整整跨了兩年!!!

處于轉型階段的我,第一次看到這么詳細的介紹,對于我來說就是雪中送炭啊!!!

引用cshenger的發言:

我發現這個文章的亮點現在在評論區了,從15年的7月到17年的7月,整整跨了兩年!!!

不要大驚小怪,阮大師的文章一向如此,兩年并不算多

flex-direction這塊配圖順序是不是還可以優化?容易誤導人

vue里面使用justify-content:flex-end 無效

糾正一下。當align-items : baseline的時候,子元素的vertical-align是有效的

大愛 太實用的

引用longfei的發言:

阮老師,那個item的flex-grow屬性,我寫了個demo
CSS:
body{margin:0;}
ul,li{margin:0; padding:0;}
li{list-style-type:none;}
#list{border:2px solid gold; height:500px; display:flex; flex-direction:row;}
#list li{font-family:"microsoft yahei"; font-size:50px; background:#C00; color:#fff; margin:2px; flex-grow:1;}
#list li:nth-child(2){flex-grow:2;}

<ul id="list">
<li>test1</li>
<li>test2</li>
<li>test3</li>
</ul>
結果第2個li所占的寬度并不是其它li的2倍,為什么呢?比其它兩個要大,但不足2倍。

引用zhishaofei3的發言:

是按剩余空間算的,因為你里面有文字,所以刨去了文字寬度,你去掉文字就好了

zhishaofei3 說得對,確實是文字影響了item的寬度;
如果要修改的話,考慮到 longfei的代碼里面 現在只是修改了flex-grow而剩余兩個用的是默認值(也就是flex-shrink:1;flex-basis:auto;)。
可以根據 阮老師寫的“建議優先使用flex這個屬性,而不是單獨寫三個分離的屬性,因為瀏覽器會推算相關值。”,把代碼修改成
#list li{flex:1;}
#list li:nth-child(2){flex:2;}
這樣顯示出來就和沒有文字的時候一樣是兩倍,不會因為文字影響了寬度;

想問一個問題
如果我擁有一個高為500px的容器
并flex-direction:row,flex-wrap:warp
添加兩個項目寬均為100%
那么這兩個項目會均分高,為什么
即使我沒有指定他們的高度

引用xbup的發言:

想問一個問題
如果我擁有一個高為500px的容器
并flex-direction:row,flex-wrap:warp
添加兩個項目寬均為100%
那么這兩個項目會均分高,為什么
即使我沒有指定他們的高度

經驗證,flex-grow自動默認到了1

引用xbup的發言:

經驗證,flex-grow自動默認到了1

即使不設置100%也會如此啊。。。。。。。。。。

阮老師,我做demo時,發現flex-wrap會把交叉軸的方向都改變了,垂直方向flex-start本來是頂部,變成了底部

引用Silvers · Rayleigh的發言:

這里是你理解錯了,3個 li 平分下來每個是1/3。
你想實現的2個相等,1個寬度是其他2個的兩倍實際上就是4個 li 平分,其中2個合并成1個,所以每個 li 是1/4,也就是#list li:nth-child(2){flex-grow:3;}


這個分配還是不完全 等比1:2:3的

css掛掉了啊。。頁面變形了

align-content 這個東西的解釋有問題,應該是多行,而不是多軸

為什么不把您的文章整理成書籍呢?期待中

flex-direction配圖不走心啊

居然不知道flex還有這么多屬性,寫的很好,雖然有人吐槽說什么進了阿里文章寫得不如以前精致,不知道還要怎么精致,自己寫不出來,還好意思吐槽別人的文章,有本事寫個精簡的,把鏈接發出來,不然就別指責別人,我也是長見識了

很好,非常受用。之前看 css-tricks 的教程看得一頭霧水,在這篇文章里理清了很多概念,卡住的一些問題也得到了解決。十分感謝博主。

文章寫的很不錯,配圖很給力,簡單明了。我看了很多阮老師的文章,有點不敢相信,感覺好像什么都會一樣,學Python看得到教程,學前端出看得到教程,而且都還講得挺不錯。

引用小小柴的發言:

阮大神我發現flex-basis這個屬性好像并不是主軸所占空間,如果我將主軸方向定為垂直排列flex-direction: column;再給他定義flex-basis的屬性,結果我發現只有水平方向的大小在變,垂直方向無效果

flex-direction這個屬性是容器container的屬性,你外層容器設置flex-direction:column(此時主軸就是垂直方向),在項目item里面設置flex-basis屬性為不同值,這樣主軸(即垂直方向)所占的大小就會變化。

也做了個直觀的 demo,感謝阮老師 https://hanzichi.github.io/2017/flex/index.html

在谷歌中,item的align-self 并不是居中在父親的中間的。

引用石麗麗的發言:

在谷歌中,item的align-self 并不是居中在父親的中間的。

容器的justify-content設置成space-between

此文大贊!看一次就明白了,作者大才,才能這樣簡潔就把知識講得這樣透徹。

厲害了 16年看了一遍,今天再看一遍

反復看了幾次了,很少用,所以老記不住

@Silvers · Rayleigh:

回答有毛病吧,flex-grow分的是剩余的空間,你的字體大小50px的大小本身就占了空間,應該把這個空間除去再分

今天做微信小程序的時候要做一個png圖標+說明文字的分享的按鈕,結果分享圖標始終無法和文字在一條水平線上對齊,就是用了flex布局(display: flex; flex-direction: row; align-items: center;),結果分享圖標確實是和文字在一條水平線線上了。但是卻把button按鈕撐的特別大,根本沒了按鈕的樣子。。。

一峰老師,我簡直不能更加感激您,也非常崇拜您。哇唔,我猜您已經將技術看作是藝術了吧!!!現在好多程序員生活都比較枯燥(我猜他們和我一樣,嘻嘻)(每天都很忙,技術更新快,提升自己的技術還要完成項目),靈魂也很干涸(因為很忙,所以太少的時間感受生活,去吸取技術之外的東西來滋養我們的靈魂)。然而每次看您的博文,我就感覺自己經歷了一場與藝術的邂逅,不僅學習了知識,還讓我得以短暫的放松,讓我的心靈經歷了一次奇妙的旅行,然后再元氣滿滿,整裝繼續上路。非常感謝您的分享,您無私的指引,以及心靈的關懷。

引用云墨雪的發言:

坐個沙發, ie10的普及率還有待觀望啊..

IE低版本是毒瘤啊

研習完真想給峰哥點贊,可以沒有這個功能~~真心感謝峰哥分享的知識^v^

看了一遍評論,有些錯誤,好像一直沒改正。

阮大大,您在屬性align-content處有地方解釋有點模糊,應該是在交叉軸方向上有多行時,align-content屬性能作用;原文大意也是如此:“This aligns a flex container's lines within when there is extra space in the cross-axis, similar to how justify-content aligns individual items within the main-axis.”

https://css-tricks.com/snippets/css/a-guide-to-flexbox/

flex彈性布局 田字格布局怎么做?

做了一個可交互的演示站flexbox演示站
初學者可以看一下快速幫助理解
https://xluos.github.io/demo/flexbox/

MDN上找到的一個示例網站:http://the-echoplex.net/flexyboxes

4.6 align-self屬性
align-self屬性允許單個項目有與其他項目不一樣的對齊方式,可覆蓋align-items屬性。默認值為auto,表示繼承父元素的align-items屬性,如果沒有父元素,則等同于stretch。

最后一句:“如果沒有父元素”,應該是如果父元素沒有設置 align-items 屬性的意思吧

感謝 您對前端初學者的貢獻,Flex知識點整理的非常好,我原本以為我很熟了,結果一看,查漏補缺了,感謝!
另外 頁面的排版 很舒服,讓我想看下去的沖動,如果排版不行的話,我大概瞄一眼就沒耐心看下去了。

別吹過頭了,圖基本就是照搬國外網站的。https://css-tricks.com/snippets/css/a-guide-to-flexbox/#flexbox-background

不錯,以前用得稀里糊涂,看完您的文章之后,有了總體把握。

不錯看了學的很清晰

main axis, cross axis. 主軸水平,交叉軸垂直,這個是在flex-direction: row;的前提下定義的吧

justify-content取值還可以是space-evenly,上面沒有提到
https://css-tricks.com/snippets/css/a-guide-to-flexbox/#article-header-id-6

flex布局高度問題怎么解決

align-content:space-between; 配圖不對,誤導我很久

子div設置 flex-grow 后,如果沒有內容是正確的,如果設置了內容,布局就變掉了,請問是怎么回事?

感謝,文章加配圖看懂了,怎么提高自己的js編寫能力,看別人代碼還好,但是一到自己寫,,,,,就不知道了

align-content這個定義多根軸線的說法有誤,這個主要是針對定義了wrap或wrap-reverse屬性的父容器垂直布局,從形意理解上來說它和 justify-content正好是一個橫豎布局的對應關系。

為什么在PHP文件中不支持flex橫向布局呢?

做了一年左右純前端,flex布局入門就是看您的博客。今天再次看到,想起忘了給您說聲謝謝了。


thx。

flex-direction 對應的圖列是否反了,row 應該是從左往右的箭頭

建議頂部加一個閱讀進度條,因為目前評論太多了,右側進度條根本無法反應實際進度。
實現很簡單,就加一個fixed div,讓它的背景色為特定顏色,捕捉滾動條滾動事件,更新div的寬度。

網站搞一個目錄看著就更方便了。

雖然存在小瑕疵,但是不得不佩服講得非常的有結構,認真拜讀完收益良多。

非常棒的講解!受益匪淺~

如何讓item主動換行呢?比如我希望4個一行。

突然讀到下面這里的后一句不明白了。
“align-content屬性定義了多根軸線的對齊方式。如果項目只有一根軸線,該屬性不起作用。”
‘如果項目只有一根軸線’? 這個怎么理解。
再開始的時候我們介紹說。‘容器默認存在兩根軸:水平的主軸(main axis)和垂直的交叉軸(cross axis)’。并沒介紹容器里面項目也有軸線。求解。

引用徐凌波的發言:

突然讀到下面這里的后一句不明白了。
“align-content屬性定義了多根軸線的對齊方式。如果項目只有一根軸線,該屬性不起作用。”
‘如果項目只有一根軸線’? 這個怎么理解。
再開始的時候我們介紹說。‘容器默認存在兩根軸:水平的主軸(main axis)和垂直的交叉軸(cross axis)’。并沒介紹容器里面項目也有軸線。求解。

多個軸線既:一個容器內多個flex容器

我有一個問題 flex:1 這種寫法 不是 省略后兩項吧 flex:1 ≠ flex-grow:1吧

跟菜鳥顯示的一樣,為何在你這里看就特別容易理解

@徐凌波:

當wrap了以后發生換行了就有兩根了

通俗易懂

默認主軸是水平方向,flex-direction是唯一能改變主軸、側軸的屬性。。

@xbup:

我的理解是設置了flex-wrap:wrap,項目align-content的默認值是stretch,不知道對不對

對于flex-basis還是不太理解,還需要多多練習,多謝您的講解

哈,這篇文章原來是阮老師寫的,網上很多地方抄了,而且沒寫明出處。

flex 布局的弊端是啥呢

引用六翼的發言:

那請問不設為0的時候它是多少呢?看您的原文里是“auto”,但這個auto是怎么計算的?

因為demo里面沒有給子元素設置寬度,所以auto默認長度由內容決定,basis:0,我理解的是將子元素寬度設置初始寬度為0,取消掉內容的影響,然后在重新按比例分配空間。

引用laoyur的發言:

還是沒看明白align-content跟justify-content的區別:(

如果按照文中所述,這兩個沒區別。實際上是 algin-content在wrap的情況下才生效,實際上還在一個軸上

原文:flex-grow:如果一個項目的flex-grow屬性為2,其他項目都為1,則前者占據的{【剩余空間】將比其他項多一倍。

應該修改:不是剩余空間,應該是項目在主軸方向上的所占比列,如果flow-direction:row,則為寬度比2:1;flow-direction:column,則為項目高度比2:1

上面信息發錯了,不好意思,是主軸上的剩余空間比

今天才知道 明明降龍十八掌 簡潔濃縮版 10分鐘快速生效版。 我當初沒看。 看那么錯雜七雜八的誤入歧途啊

主軸會變化的,以前理解的不是很到位,基本概念中的圖應該有個前提條件 flex-direction:flex。特意寫了一篇文章說明 https://mp.weixin.qq.com/s/T-Z_8he9UxBBfL8Jb3zwtA。

我要發表看法

«-必填

«-必填,不公開

«-我信任你,不會填寫廣告鏈接

体彩7位数