一篇完整的FlexBox佈局指南

一篇完整的FlexBox佈局指南

轉載請標註本文連接並附帶如下信息: 譯:Cydiacen 做者:CHRIS COYIER 原文:A Complete Guide to Flexbox 原文更新於 2016-11-19css

譯者的話

出於提高自身英語水平和鞏固FlexBox的知識,因而打算翻譯一篇比較知名的FlexBox佈局的文章,固然這篇文章以前網上已有大漠的譯文,這次翻譯也有部分參考大漠譯文的內容,因而在此貼上大漠譯文的地址,以此致敬大佬。《一個完整的Flexbox指南html

爲了避免浪費你們時間,先說明下flexBox如今的兼容狀況:css3

  • (new)意味着已成爲規範的新語法(好比:display:flex;
  • (tweener)意味着是來自2011年一種臨時的非官方的語法(display:flexbox;
  • (old)意味着來自2009年的老語法(display:box;
Chorme 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)

黑莓瀏覽器 10+ 支持新語法。git

關於怎麼樣混合語法能夠獲得更好的瀏覽器支持的信息,能夠跳轉到《CSS-Tricks》或者《DevOpera》。github

寫做背景

Flexbox(彈性盒子)佈局模式(目前是個W3C規範草案)旨在爲佈局,對齊和分佈容器內的子項提供一種更加高效的方式,即便這些玩意兒的大小是未知的或者動態變化的。(正如他的名字所示——Flex,彈性的意思)web

Flex佈局背後的主要思想是——給指定的容器提供修改其子項的寬、高乃至順序的能力,而且足夠完美的去填充可用的空間(主要是爲了適應各類各樣的顯示設備和屏幕大小)。瀏覽器

一個使用了Flex佈局的容器,將會擴展其子項以致於填充起可用的空間,或者縮小他們以防止溢出容器。app

有一個至關重要的一點,FlexBox佈局的方向不像常規佈局(塊就是垂直從上到下,行就是水平從左到右),它是不可預知方向的。而那些常規的適合頁面佈局,但對於做用在大型或者複雜的應用程序(特別是當他涉及到方向改變、大小變化、拉伸和收縮等)就缺少靈活性。ide

注意: FlexBox佈局最適用於應用程序的組件和小規模佈局,而網格佈局更適用於大規模的佈局。佈局

基本要素

由於FlexBox是一整個模塊並非一個單獨的屬性,它涉及到不少東西包括它的全部設置屬性。一些屬性是須要被設置在容器(父級元素,稱爲『彈性容器』),而一些其餘的屬性須要被設置在子元素(稱爲『彈性項』)中。

若是常規佈局是基於塊佈局與內聯佈局的方向流的,那麼彈性佈局就是基於「flex-flow流」。請看一下來自W3C規範的這張圖,它解釋了彈性佈局的主要思想。

基本上,彈性項(flex item)會沿着主軸方向(main-startmain-end)或側軸方向(cross-startcross-end)排列。

  • 主軸(main axis) - 彈性項主要是沿着彈性容器的主軸進行排列的。要注意一點,他不必定是水平的;這主要仍是看flex-direction屬性(見下文)。
  • main-start | main-end - 彈性項將由main-startmain-end方向放置在容器內。
  • main size - 彈性項在主軸方向的寬度或高度就是主軸的尺寸。彈性項主要的大小屬性能夠是寬度,也能夠是高度屬性,由哪個對着主軸方向決定。
  • cross axis - 與主軸垂直相交的軸線就是側軸。它的方向由主軸決定。
  • cross-start | cross-end - 彈性行是由彈性項填充起來的,它的配置是從容器的cross-start開始,往cross-end結束。
  • cross size - 彈性項在側軸方向的寬度或高度就是cross sizecross size根據側軸的方向來取決是寬度仍是高度。

父級(彈性容器)屬性

display

這個屬性是定義在彈性容器上的;根據其值決定是內聯仍是塊佈局。這時它的直屬下級將會變成flex文檔流。

.container {
  display: flex; /* or inline-flex */
}

須要注意CSS的columns在flex容器裏沒有效果。

flex-direction

這個是創建在主軸上的,從而定義了彈性項放置在容器的方向。FlexBox是單方向的佈局概念。能夠將彈性項視爲主要佈置在水平行或垂直列中。

.container {
  flex-direction: row | row-reverse | column | column-reverse;
}
  • row(默認):在ltr排版方式下從左向右排列;在rtl排版方式下從右向左排列。
  • row-reverse:與row排列方向相反,在ltr排版方式下從右向左排列;在rtl排版方式下從左向右排列。
  • column:相似於row可是是頂部到底部
  • column-reverse:相似於row-reverse可是是底部到頂部

flex-wrap

彈性項默認會所有集中在一行。你可使用這個屬性來改變這種狀況,讓他們根據你的須要進行自動換行。文檔方向在這裏也起做用,決定了新的一行被堆疊的方向。

.container{
  flex-wrap: nowrap | wrap | wrap-reverse;
}
  • nowrap(默認):單行顯示。在ltr排版下,項目自左向右;在rtl下,自右向左
  • wrap:多行顯示。在ltr排版下,項目自左向右;在rtl下,自右向左
  • wrap-reverse:多行顯示。與wrap相反

flex-flow(定義在彈性容器中)

這個是flex-directionflex-wrap屬性的縮寫版,它同時定義了彈性容器的主軸和側軸。默認是row nowrap

flex-flow: <‘flex-direction’> || <‘flex-wrap’>

justify-content

這屬性是用來定義主軸上的對齊方式的。當全部的彈性項在一行而且沒法彈性伸展,或者可伸展可是達到了最大尺寸,它能幫助分配剩下的多餘空間。而且當他們行內溢出時,這個屬性也能夠對項目對齊施加一些控制。

.container {
  justify-content: flex-start | flex-end | center | space-between | space-around;
}
  • flex-start(默認):子項會從一行的起始處開始放置
  • flex-end:子項會從一行的結尾處開始放置
  • center:子項會集中在一行的中央
  • space-between:子項會被均勻的分佈在行內;首項放置在一行的開始,尾項放置在一行的結束
  • space-around:子項會均勻的按照同等距離分佈在一行。須要注意的是,在視覺上會以爲並不等距,由於全部子項在兩側都須要加上同等的空間。首項會與容器開始邊緣有一個單位空間的距離,可是與下一項會有兩個單位空間的距離,由於下一項也有它本身的適配空間。

align-items

這用來定義彈性項目在彈性容器的當前側軸上的默認行爲。能夠認爲是側軸版的justity-content

.container {
  align-items: flex-start | flex-end | center | baseline | stretch;
}
  • flex-start:彈性項在側軸起點邊的外邊距緊靠住該行在側軸起始的邊。
  • flex-end:彈性項在側軸起點邊的外邊距緊靠改行在側軸結尾的邊。
  • center:彈性項會被放置在側軸的中央。
  • baseline:彈性項會根據他們的基線對齊。
  • stretch(默認):在側軸方向上拉伸彈性項以至填充滿彈性容器。(任聽從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(默認):每行將會伸展以佔用剩餘的空間。

子項(彈性項)的屬性

order

通常來講,彈性項會按照文檔流的順序進行佈局。然而,order屬性能夠控制他們出如今彈性容器中的順序。

.item {
  order: <integer>;
}

flex-grow

這個屬性給予彈性項在須要的時候能夠伸展的能力。它接收一個不帶單位的值做爲比例。它規定了在容器內的彈性項能夠佔用多少的可用空間。

若是全部的子項都設置了flex-grow爲1,那麼容器內的剩餘空間會被均勻的分配給全部自項。若是其中一項的值爲2,那麼這項的佔用空間會是其餘項的兩倍。

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

設置負數是無效的。

flex-shrink

這定義了彈性項在須要的時候具備伸展的能力。

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

負數是無效的。

flex-basis

這定義了,當一個元素在被分配到剩餘空間以前的默認大小。它能夠是一個長度(如:20%,5rem等)或者一個關鍵字。auto關鍵字的意思就是『按照個人寬度和高度屬性調整尺寸』(他會暫時根據main-size來佈局大小直到被棄用)。若是使用關鍵字content,意思就是『基於內容調整大小』——不過這個關鍵字並必定能很好的工做,所以很難去測試或者知曉它的兄弟們max-contentmin-contentfit-content作了什麼。

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

若是設置爲0,額外空間內容不會被分解開來。若是設置成auto,額外空間會基於它的flex-grow的值進行分佈。

flex

這是flex-growflex-shrinkflex-basis組合縮寫版。第二個和第三個參數(flex-shrinkflex-basis)是可選的。默認是0 1 auto

推薦你使用的這種縮寫屬性,這比設置單獨屬性更好。能夠智能的經過縮寫形式設置值。

align-self

用來在單獨的伸縮項目上覆寫默認的對齊方式。

請看下align-items的解釋,幫助你瞭解可用值。

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

注意,floatclearvertical-align在彈性項中會失效。

例子

讓咱們從一個很是很是簡單的例子開始,解決一個很是平常的問題:完美居中。若是你使用flexBox佈局,這將會變得很是簡單。

.parent {
  display: flex;
  height: 300px; /* Or whatever */
}

.child {
  width: 100px;  /* Or whatever */
  height: 100px; /* Or whatever */
  margin: auto;  /* Magic! */
}

這個依賴於設置margin值爲auto值,會自動獲取彈性容器的額外空間。所以設置垂直方向marginauto可讓彈性項完美的居中在兩個軸。

如今讓咱們使用下一些其餘屬性。

考慮使用一個包含六個項的列表,而且爲了視覺審美給他設置了一個固定大小尺寸,但他們也有可能能夠自動獲取尺寸大小。咱們想要他們能夠均勻的,而且完美分佈在水平軸上,而且當我改變瀏覽器的大小,他們仍是能夠很好的展現(不須要引用媒體查詢!)。

.flex-container {
  /* 咱們先建立一個彈性佈局環境*/
  display: flex;
  
  /* 而後若是咱們容許子項換行能夠定義flow-direction
   * 記住這相等於:
   * flex-direction: row;
   * flex-wrap: wrap;
   */
  flex-flow: row wrap;
  
  /* 而後咱們再定義怎麼樣分佈剩餘的空間 */
  justify-content: space-around;
}

完工。其餘的一切不過是美化樣式。下面提供一些html,css代碼,能夠在codePen調試而且改變下瀏覽器的大小看看會發生什麼。
codePen

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

SASS:

@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;
}

讓咱們再嘗試下其餘東西。想象下,咱們的網站全部頁面頭部都有個右對齊佈局的導航,可是咱們想讓他在中等大小的屏幕中居中顯示而且在小屏幕設備中單行顯示。很是簡單。

/* 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;
  }
}

codePen調試連接

讓咱們再來試試一些更加靈活性的彈性項!關於移動先行,3列布局與頁眉頁腳全屏。和獨立的文檔順序。

.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; }
}

codePen

Flexbox前綴

Flexbox接受一些運營商前綴以支持能夠在更多的瀏覽器上使用。它不只只包括在屬性前添加前綴,它也有徹底不一樣的屬性名字和值名字。這是由於Flexbox規範隨着時間一直在變化,所以有了oldtweenernew版本。

固然最好的方式是使用最新的語法,而且經過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

Flex固然不是沒有bug,我見過的關於這些bug收集最好的是Philip WaltonGreg WhitworthFlexBugs

相關文章
相關標籤/搜索