譯文:Flexbox 徹底指南 (A Complete Guide to Flexbox)


 

背景

Flexbox 佈局 (Flexible Box) 模塊 (目前是 W3C 的一個最後徵集工做草案(Last Call Working Draft))旨在提供一種更有效的方式,在容器的項之間處理佈局、對齊和空間分配,即便它們的大小未知而且/或是動態變化的(所以叫作「flex」)。 css

Flex 佈局背後的主要思想是讓容器可以改變其項的寬度/高度(和順序),以最好地填充可用空間(主要是爲了適應各類顯示設備和屏幕大小)。一個 flex 容器擴大其項來填充可用的空閒空間,或者縮小它們以防止溢出。html

最重要的是,flexbox 佈局與常規佈局(基於垂直的塊(block)、基於水平的內聯(inline))截然相反,flexbox 佈局是方向無關的。雖然常規佈局工做很適合頁面,但它們缺少靈活性(沒有雙關語)來支持大型或複雜的應用程序(特別是當涉及到方向變化、大小調整、拉伸、收縮等)時。
css3

注意:Flexbox 佈局最適合應用程序的組件和小型佈局,而網格佈局則適合更大規模的佈局。git

 

基礎和術語

因爲 flexbox 是一個完整的模塊,而不是一個單獨的屬性,它涉及到不少東西,包括它的所有屬性。其中一些是要在容器上設置的(父元素,稱爲「flex容器」),而其餘的則是設置在子元素上(稱爲「flex項/元素」)。
若是常規佈局是基於塊(block)和內聯(inline)流方向,那麼 flex 佈局則基於「flex流方向(flex-flow direction)」。 請看一看規範中的下圖,其解釋了 flex 佈局背後的主要思想。

 基本上,彈性項(flex items)將沿着主軸(main axis)(從 main-start 到 main-end)或側軸(cross axis)(從 cross-start 到 cross-end)佈局。github

  • main axis - flex容器的主軸是主要的軸,flex項被沿其放置。小心,它不必定是水平的;這取決於 flex-direction 屬性的值(見下)。
  • main-start | main-end - flex 項放在容器內,從 main-start 到 main-end。
  • main size - 一個彈性項的寬度或高度,任何一個在主維度上,就是這個項的主尺寸。flex 項的 main size 屬性是「寬度」或「高度」屬性之一,任何一個均可以是 main size。
  • cross axis - 垂直於主軸的軸稱爲橫軸。它的方向取決於主軸方向。
  • cross-start | cross-end - Flex行充滿了flex項,並將其放置到容器中,行開始於Flex容器的 cross-start 端,並向 cross-end 端方向前進。
  • cross size - 一個 flex 項的寬度或高度,任何一個在側維度上,就是該項的 cross size。cross size屬性是在側維度上的「寬度」或「高度」中其一。

Properties for the Parentweb

(flex container)瀏覽器

Properties for the Childrenapp

(flex items)ide

 

# display

定義一個 flex 容器;inline 或 block 取決於給定的值。它爲全部直接的子元素提供一個 flex 上下文。
    .container {
        display: flex; /* or inline-flex */
    }
注意,CSS 列對 flex 容器沒有影響。
 

# flex-direction

肯定主軸, 用來定義 flex 容器中的 flex 項的放置方向。Flexbox 是(除了可選的 wrap)一個單向佈局概念。能夠將 flex 項看做主要是在水平的行或垂直的列中佈局的。
    .container {
        flex-direction: row | row-reverse | column | column-reverse;
    }
 
  • row (default): 從左到右(若是元素的 dir 屬性爲 ltr);從右到左(若是元素的 dir 屬性爲 rtl)
  • row-reverse: 從右到左(若是元素的 dir 屬性爲 ltr);從左到右(若是元素的 dir 屬性爲 rtl)
  • column: 自上而下
  • column-reverse: 自下而上

# flex-wrap

默認狀況下,flex 項都將嘗試放置在一行上。你能夠根據須要使用該屬性來更改默認行爲以支持換行。
    .container{
        flex-wrap: nowrap | wrap | wrap-reverse;
    }
 
  • nowrap (default): 全部 flex 項位於一行中
  • wrap: flex 項將從上到下多行排列
  • wrap-reverse: flex 項將從下到上多行排列
 

# flex-flow (適用於:父 flex 容器元素)

這是一個簡化的 flex-direction 和 flex-wrap 屬性,它們一塊兒定義了 flex 容器的主和側軸。默認是 row nowrap。
    flex-flow: <‘flex-direction’> || <‘flex-wrap’>
 

# justify-content

該屬性定義了瀏覽器如何分配順着父容器主軸的彈性元素之間及其周圍的空間。它幫助分配剩餘的空閒空間當不管在一行中的全部 flex 項是固定大小的仍是彈性的可是達到它們的最大尺寸的時候。 當它們溢出行時, 該屬性也能這些項的對齊方式發揮一些控制做用。
    .container {
        justify-content: flex-start | flex-end | center | space-between | space-around | space-evenly;
    }
 
  • flex-start (default): 從行首開始排列。每行第一個彈性元素與行首對齊,同時全部後續的彈性元素與前一個對齊
  • flex-end: 從行尾開始排列。每行最後一個彈性元素與行尾對齊,其餘元素將與後一個對齊
  • center: 伸縮元素向每行中點排列。每行第一個元素到行首的距離將與每行最後一個元素到行尾的距離相同
  • space-between: 在每行上均勻分配元素;第一個元素位於行首,最後一個元素位於行尾
  • space-around: 元素在行內均勻分佈,在元素周圍的間距相等。注意,視覺上的間距不相等,由於全部元素在其兩邊都有相等的空白。第一個元素距離容器邊緣有一個單位的空白,而元素之間有兩個單位的空白由於下一個元素也有其本身的空白邊距。
  • space-evenly: 元素到容器邊緣及元素之間間距相等地均勻分佈方式。
 

# align-items

該屬性定義彈性元素沿當前行的側軸方向上如何佈局的默認行爲。能夠將其理解爲 justify-content 應用於側軸的版本(垂直於主軸)。
    .container {
        align-items: flex-start | flex-end | center | baseline | stretch;
    }
 
  • flex-start: 元素側軸起點的邊緣與行的側軸起點對齊
  • flex-end: 元素側軸終點的邊緣與行的側軸終點對齊
  • center: 元素在側軸方向上居中對齊
  • baseline: 全部元素向基線對齊。側軸起點到元素基線距離最大的元素將會於側軸起點對齊以肯定基線
  • stretch (default): 彈性元素被在側軸方向被拉伸到與容器相同的高度或寬度。(同時遵照 min-width/max-width 屬性的設置

# align-content

該屬性設置當在側軸方向上有額外空間的時候彈性容器中行的對齊方式,相似於在主軸上 justify-content 屬性對個體元素的對齊方式。
注意:該屬性在彈性容器中僅有一行彈性元素的狀況下沒有效果。
    .container {
        align-content: flex-start | flex-end | center | space-between | space-around | stretch;
    }
 
  • flex-start: 全部行從側軸起點開始填充。第一行的側軸起點邊和容器的側軸起點邊對齊。接下來的每一行緊跟前一行
  • flex-end: 全部行從側軸末尾開始填充。最後一行的側軸終點和容器的側軸終點對齊。同時全部後續行與前一個對齊
  • center: 全部行朝向容器的中心填充。每行互相緊挨,相對於容器居中對齊。容器的側軸起點邊和第一行的距離相等於容器的側軸終點邊和最後一行的距離
  • space-between: 全部行在容器中平均分佈。相鄰兩行間距相等。容器的側軸起點邊和終點邊分別與第一行和最後一行的邊對齊
  • space-around: 全部行在容器中平均分佈,相鄰兩行間距相等。容器的側軸起點邊和終點邊分別與第一行和最後一行的距離是相鄰兩行間距的一半
  • stretch (default): 拉伸全部行來填滿剩餘空間。剩餘空間平均的分配給每一行
 

# order

默認狀況下,flex 元素按源順序排列。同時,order 屬性能夠控制它們在彈性容器中出現的順序。
    .item {
        order: <integer>;
    }
 

# flex-grow

該屬性定義彈性盒子項(flex item)的拉伸因子,它定義了一個 flex 項在必要時能夠拉伸的能力。它接受一個無單位數值,做爲一個比例。它規定了 flex 項在 flex 容器內可佔據的可用空間的大小。
若是全部項的 flex-grow 屬性都設置爲 1,那麼容器中的剩餘空間將平均分配給全部的子元素。若是其中一個子元素的值爲 2,那麼其對剩餘空間的佔用將比其餘項多一倍(或者至少嘗試一下)。
    .item {
        flex-grow: <number>; /* default 0 */
    }
負值是無效的。
 

# flex-shrink

這定義了一個 flex 項在必要時收縮的能力。flex 元素僅在默認寬度之和大於容器的時候纔會發生收縮,其收縮的大小是依據 flex-shrink 的值。
    .item {
        flex-shrink: <number>; /* default 1 */
    }
負值是無效的。
 

# flex-basis

這定義了在剩餘空間被分配以前,元素的默認大小。它能夠是一個長度(例如 20%,5rem 等)或一個關鍵字。auto 關鍵字的意思是「看個人 width 或 height 屬性」(這是由關鍵字 main-size 臨時完成的,直到廢棄爲止)。content 關鍵字的意思是「基於項中內容的大小調整尺寸」 ———— 這個關鍵字尚未獲得很好的支持,因此很難測試,也很難知道它的同胞屬性 max-content、min-content 和 fit-content 是什麼。
    .item {
        flex-basis: <length> | auto; /* default auto */
    }
若是設置爲0,則不將內容周圍的額外空間考慮在內。若是設置爲 auto,額外的空間將基於它的 flex-grow 屬性值分配。 查看此圖
 

# flex

這是一個簡寫屬性,能夠同時設置 flex-grow, flex-shrink 與 flex-basis。第二和第三個參數(flex-shrink 和 flex-basis)是可選的。默認爲 0 1 auto。
    .item {
        flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
    }
建議使用這個簡寫屬性,而不是設置單個屬性。
 

# align-self

這容許對單個 flex 元素覆蓋默認對齊(或者由 align-item 指定的對齊)。
屬性值請參考對 align-items 屬性的解釋。
    .item {
        align-self: auto | flex-start | flex-end | center | baseline | stretch;
    }
 
注意,float,clear 和 vertical-align 對彈性元素沒有影響。

 

Examples

讓咱們從一個很是簡單的例子開始,解決一個幾乎平常的問題:完美地居中。若是你使用 flexbox,那就不能再簡單了。
.parent {
    display: flex;
    height: 300px; /* Or whatever */
}
.child {
    width: 100px;  /* Or whatever */
    height: 100px; /* Or whatever */
    margin: auto;  /* Magic! */
}
這就依賴於在 flex 容器中設置 「auto」 的 margin 吸取額外的空間。所以,設置一個垂直的 margin 爲 auto,將使這個 flex 項完美地在兩個軸上居中。
 
如今咱們來使用更多的屬性。 考慮一個擁有6個元素的 list,全部元素都有一個固定的尺寸,在美學問題上,但它們能夠是自動大小的。咱們但願它們在水平軸上均勻地分佈,這樣當咱們調整瀏覽器的大小時,一切都很好(沒有 media query!)。
.flex-container {
    /* We first create a flex layout context */
    display: flex;
 
    /* Then we define the flow direction and if we allow the items to wrap
     * Remember this is the same as:
     * flex-direction: row;
     * flex-wrap: wrap;
     */
    flex-flow: row wrap;
 
    /* Then we define how is distributed the remaining space */
    justify-content: space-around;
}
完成。其餘的都只是一些樣式的問題。 下面是本例在 CodePen 上的一個 pen。必定要去CodePen,試着調整你的窗口大小,看看會發生什麼。
 
 
讓咱們試試別的。假設咱們在咱們的網站上有一個右對齊的導航,但咱們但願它在中等大小的屏幕上居中對齊,而在小的設備上是單列的。很是簡單。
/* 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; } }
 
 
讓咱們利用彈性元素的靈活性來嘗試一些更有趣的事情。一個移動優先(mobile-first)的帶有全寬(full-width)頁頭和頁腳的三列布局怎麼樣,而且獨立於源順序。
.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; } }

https://codepen.io/team/css-tricks/pen/jqzNZqsvg

 

Flexbox 前綴

Flexbox 須要一些供應商(vendor)的前綴來支持儘量多的瀏覽器。它不只包含帶有供應商前綴的前置修飾屬性,還包括實際上徹底不一樣的屬性和值名。這是由於 Flexbox 規範已經隨着時間的推移而改變,建立了一個 「舊的」、「過渡的」和「新的」版本。
也許處理這一問題的最好方法是編寫新的(和最終的)語法,並經過  Autoprefixer 運行您的CSS,它可以很好地處理回退問題。
或者,這裏有一個 Sass 的 @mixin 來幫助處理一些前綴,這也讓你知道須要作些什麼:
@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);
}

 

相關文章

其餘資源

Bugs

Flexbox 固然不是沒有它的 bug/缺陷/issue。我目前所看到的最好的關於它們的收集是 Philip Walton 和 Greg Whitworth 的  Flexbugs。這是一個用來追蹤全部 bug/缺陷/issue 的開放源代碼的地方,因此我認爲最好只是將它連接在此。
 

瀏覽器支持

根據 flexbox 的「版本」拆分:
  • (new) 表示規範中最新的語法(例如 display: flex;)
  • (tweener) 這是2011年以來的一種怪異的非官方語法(例如 display: flexbox;)
  • (old) 表示從2009開始的舊的語法(例如 display: box;)
Chrome
Safari
Firefox
Opera
IE
Android
iOS
20- (old)
3.1+ (old)
2-21 (old)
12.1+ (new)
10 (tweener)
2.1+ (old)
3.2+ (old)
21+ (new)
6.1+ (new)
22+ (new)
11+ (new)
4.4+ (new)
7.1+ (new)
 
有關如何混合語法以得到最佳瀏覽器支持的更多信息,請參考  this article (CSS-Tricks) 或者  this article (DevOpera)。黑莓瀏覽器 10+ 支持新語法。
相關文章
相關標籤/搜索