樣式篇 - Flex彈性盒子佈局(建議收藏)

1、引言

傳統的CSS佈局基本是div + css佈局,依賴盒子模型,經過positionfloatdisplay等方式實現,可是對於一些特殊佈局,就不太容易實現,好比垂直居中佈局。css

2009年,W3C 提出了一種新的方案----Flex 佈局,能夠簡便、完整、響應式地實現各類頁面佈局。目前大部分瀏覽器都已經支持Flex屬性。html

我也一直在使用Flex,可是有的屬性也只是會用,只知其一;不知其二,甚至有的屬性就沒用過,好比: orderflex-grow等。寫這篇文章的目的主要仍是作個總結與梳理,加深印象。web

2、什麼是Flex佈局

Flex 是 Flexible Box 的縮寫,意爲"彈性佈局"。

CSS 彈性盒子佈局是 CSS 的模塊之一,定義了一種針對用戶界面設計而優化的 CSS 盒子模型。在彈性佈局模型中,彈性容器的子元素能夠在任何方向上排布,也能夠「彈性伸縮」其尺寸,既能夠增長尺寸以填滿未使用的空間,也能夠收縮尺寸以免父元素溢出。子元素的水平對齊和垂直對齊都能很方便的進行操控。經過嵌套這些框(水平框在垂直框內,或垂直框在水平框內)能夠在兩個維度上構建佈局。 —— MDN瀏覽器

3、基本概念

3.一、容器

採用 Flex 佈局的元素,稱爲 Flex 容器(flex container),簡稱"容器"。它的全部子元素自動成爲容器成員,稱爲 Flex 項目(flex item),簡稱"項目",也叫flex元素。佈局

3.二、兩根軸線

Flex的兩根軸線,分別是主軸交叉軸,能夠簡單理解爲水平豎直兩個方向。默認狀況下主軸對應的是水平方向交叉軸對應的是豎直方向,可是這個對應關係是能夠修改的(經過flex-direction屬性),不少狀況下咱們也確實要修改,具體怎麼修改下面會講到。flex

3.三、起始線和終止線

以前咱們通常都默認文檔書寫時從左到右的,可是Flex沒有左右的概念,默認狀況下,flex-direction的屬性值爲row,意思就是主軸爲水平方向,起始線(也就是起點)在左邊。flex-direction屬性還有其餘屬性值,這裏先不列舉,後面詳細說。優化

4、CSS屬性

4.一、使用Flex佈局

指定一個元素爲Flex容器很是簡單。spa

.box {
  display: flex;
}

行內元素也能夠指定爲Flex容器。設計

.box {
  display: inline-flex;
}

Webkit內核的瀏覽器。code

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

注意,設爲 Flex 佈局之後,子元素的float、clear和vertical-align屬性將失效。

4.二、容器的屬性

容器能夠設置下面6個屬性:

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

先初始化一下咱們的頁面

/* HTML */
<div class="container">
    <div class="item">one</div>
    <div class="item">two</div>
    <div class="item">three</div>
</div>
/* CSS */
.container {
    width: 800px;
    height: 400px;
    margin: 100px auto;
    border: 1px dashed #00f;
}
.item {
    border: 1px solid #000;
    text-align: center;
}

此時咱們的頁面是這樣的

flex-direction屬性

flex-direction屬性可讓咱們更改 flex 元素的排列方向(即主軸的方向),它有四個值。

.box {
  flex-direction: row | row-reverse | column | column-reverse;
  /* row(默認):  主軸爲水平方向,起點在左端。 */
  /* row-reverse:  主軸爲水平方向,起點在右端。 */
  /* column:  主軸爲豎直方向,起點在上面。 */
  /* column-reverse:  主軸爲豎直方向,起點在下面。 */
}
注意,當主軸爲水平方向時,對應的交叉軸就爲豎直方向,反之亦然。

嗯。。。仍是看效果吧,首先把容器設置爲flex容器

.container {
  ...
  display: flex;
}

而後再設置flex-direction屬性。

效果就不一一展現了,太佔地方,放一張對比的效果圖。

這樣就很清晰了,可能有人已經注意到了,項目在交叉軸方向上都被拉伸了,這是由於有另外一個屬性的做用,它是align-items,它的做用是控制容器內項目在交叉軸上的排列方式,後面會介紹,這裏先不詳細說。

flex-wrap屬性

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

.box{
  flex-wrap: nowrap | wrap | wrap-reverse;
  /* nowrap(默認):  不換行 */
  /* wrap:  換行,第一行在前面 */
  /* wrap-reverse:  換行,第一行在後面 */
}

仍是要寫一寫,首先把上面的flex-direction屬性改爲默認的,或者刪除掉,如今效果是這樣的

而後,咱們給容器內的項目設置寬度,使內容寬度超過容器的寬度

.item {
  width: 300px;  /* 每一個項目寬度爲300px,總共是900px */
  ...
}

能夠看到,每一個項目寬度設置爲300px,已經超過容器寬度的800px了,可是項目並無換行,而是被壓縮在一行了,接下來看看flex-wrap的做用,仍是展現對比圖。

對比看起來就很明瞭了,nowrap其實就是默認的屬性值,不換行,壓縮在容器內展現,wrapwrap-reverse都是換行,可是不一樣行的展現順序不一樣。

flex-flow屬性

能夠將兩個屬性 flex-directionflex-wrap 組合爲簡寫屬性 flex-flow。第一個指定的值爲 flex-direction ,第二個指定的值爲 flex-wrap。默認值爲:row nowrap

justify-content屬性

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

justify-content: flex-start;       /* 默認值,左對齊 */
justify-content: flex-end;         /* 右對齊 */
justify-content: center;           /* 居中 */
justify-content: space-between;    /* 兩端對齊,項目之間的間隔都相等
                                      (首個元素在起點,末尾元素在終點) */
justify-content: space-around;     /* 均勻排列每一個元素
                                      每一個元素周圍分配相同的空間 */
justify-content: space-evenly;     /* 均勻排列每一個元素
                                      每一個元素之間的間隔相等 */

仍是看對比圖吧

其中space-aroundspace-evenly要分清楚,兩個都是均勻分佈,區別在於容器兩端與元素之間的距離是否相等。

align-items屬性

align-items屬性定義了項目在交叉軸上的對其方式,上面講flex-direction屬性的最後說到了這個屬性,如今就一塊兒來看看。

align-items: flex-start;   /* 元素向交叉軸的起點對齊 */
align-items: flex-end;     /* 元素向交叉軸的終點對齊 */
align-items: center;       /* 元素在交叉軸居中對齊。 */
align-items: baseline;     /* 項目的第一行文字的基線對齊 */
align-items: stretch;      /* 默認,若是項目未設置高度或設爲auto,將佔滿整個容器的高度。 */

能夠看到當屬性值爲stretch的時候和一開始的效果是同樣的,由於這是默認的屬性值。

align-content屬性

align-content屬性定義了多根軸線在交叉軸上的對齊方式。是軸線的對齊方式,不是項目

align-content: flex-start;     /* 與交叉軸的起點對齊 */
align-content: flex-end;      /* 與交叉軸的終點對齊 */
align-content: center;        /* 在交叉軸居中對齊 */
align-content: space-between; /* 與交叉軸兩端對齊,軸線之間的間隔平均分佈 */
align-content: space-around;   /* 每根軸線兩側的間隔都相等 */
align-content: space-evenly;  /* 均勻分佈,兩端與每條軸線之間距離相等 */
align-content: stretch;   /* 默認,軸線佔滿整個交叉軸 */

這裏有個須要注意的地方,當內容高度(也多是寬度)不固定的時候,align-content默認屬性值是stretch,也就是充滿交叉軸的長度,這時候設置align-items能夠看出效果。

可是若是align-content設置爲其餘屬性,align-items設置的屬性可能就「失效」了。其實不是失效,由於給align-content設置除了stretch的屬性後,每一個主軸的內容高度(也多是寬度)就被壓縮了,這時候再設置align-items固然就看不出什麼效果了。

最後仍是看下對比圖

4.三、項目的屬性

項目能夠設置下面幾個屬性

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

order屬性

order屬性定義項目(元素)的排列順序。數值越小,排列越靠前,默認爲0。

仍是先修改一下頁面代碼

/* HTML */
<div class="container">
  <div class="item item1">one</div>
  <div class="item item2">two</div>
  <div class="item item3">three</div>
</div>

/* CSS */
.container {
  width: 800px;
  height: 400px;
  margin: 100px auto;
  border: 1px dashed #00f;
  display: flex;
  align-items: flex-start;
}
.item {
  width: 200px;
  margin: 20px 0;
  border: 1px solid #000;
  text-align: center;
}

如今效果是這樣

增長CSS代碼

.item1 {
  order: 3
}

.item2 {
  order: 2
}

.item3 {
  order: 1
}

能夠看到,排列順序發生了變化,order值越小,排列越靠前,還能夠爲負數。

flex-grow屬性

flex-grow屬性定義項目的放大比例,默認爲0,即若是存在剩餘空間,也不放大。

先恢復一下代碼,分別添加代碼

/* 給全部項目都設置爲1 */
.item {
  flex-grow: 1;
}

/* 只給item1設置 */
.item1 {
  flex-grow: 1;
}

/* 只給item1和item2設置 */
.item1 {
  flex-grow: 1;
}
.item2 {
  flex-grow: 1;
}

而後看下對比

能夠看到若是隻給一個元素設置flex-grow大於0的屬性,那個這個元素會佔據剩餘空間。

若是給多個元素設置相同的flwx-grow屬性,那麼這些元素會平分剩餘空間。

還有一種狀況我沒列舉,給不一樣元素設置不一樣大小的flex-grow屬性,這時候會根據flex-grow的大小分配不一樣大小的空間。

上面說的都是在容器有剩餘空間的狀況下,若是項目充滿了容器,name設置flex-grow是沒效果的。

flex-shrink屬性

flex-shrink屬性指定了 flex 元素的收縮規則。flex 元素僅在默認寬度之和大於容器的時候纔會發生收縮,其收縮的大小是依據 flex-shrink 的值,默認爲1。

.container {
  width: 400px;  /* 容器寬度小於項目寬度之和 */
}
.item1 {
  flex-shrink: 2;
}

能夠看到第一個元素被壓縮的程度是其餘兩個的2倍。這是由於flex-shrink默認值爲1,第一個元素咱們設置爲2。

flex-basis屬性

flex-basis屬性指定了 flex 元素在主軸方向上的初始大小。若是不使用 box-sizing 改變盒模型的話,那麼這個屬性就決定了 flex 元素的內容盒(content-box)的尺寸。

當咱們設置爲auto時,就是使用項目原本的寬度。

flex屬性

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

有幾種寫法:

單值語法

  • 一個不帶單位的數值,會被當作flex-grow的屬性值。
  • 一個有效的寬度值(如:10px),會被當作flex-basis的屬性值。
  • 關鍵字noneautoinitial

雙值語法

第一個值必須爲一個無單位數,而且它會被看成 <flex-grow> 的值。第二個值必須爲如下之一:

  • 一個無單位數:它會被看成 <flex-shrink> 的值。
  • 一個有效的寬度值(如:10px),會被當作flex-basis的屬性值。

三值語法

  • 第一個值必須爲一個無單位數,而且它會被看成 <flex-grow> 的值。
  • 第二個值必須爲一個無單位數,它會被看成 <flex-shrink> 的值。
  • 第三個值必須爲一個有效寬度值,它會被看成 <flex-basis> 的值。
flex: auto;  /* 至關於 flex: 1 1 auto */
flex: none;  /* 至關於 flex: 0 0 auto */

align-self屬性

align-self屬性能夠設置單個項目與其餘項目不同的對齊方式,能夠覆蓋align-items屬性,默認值爲auto,表示繼承父元素的align-items屬性。

align-self的屬性值和align-items是同樣的,只不過多了一個auto

上圖中給容器設置了align-items: flex-start;,而後單獨給第一個元素設置了align-self: flex-end;能夠看到該元素和其餘的元素排列方式不一樣。

ok,概念和語法的東西大概就說這麼多,也參考了不少資料,有什麼補充和錯誤之處還請斧正,很是感謝!!!

以爲有用的話能夠點贊 + 收藏哦!

參考資料:

相關文章
相關標籤/搜索