傳統的CSS佈局基本是div
+ css
佈局,依賴盒子模型,經過position
、float
、display
等方式實現,可是對於一些特殊佈局,就不太容易實現,好比垂直居中佈局。css
2009年,W3C 提出了一種新的方案----Flex 佈局,能夠簡便、完整、響應式地實現各類頁面佈局。目前大部分瀏覽器都已經支持Flex屬性。html
我也一直在使用Flex,可是有的屬性也只是會用,只知其一;不知其二,甚至有的屬性就沒用過,好比: order
、flex-grow
等。寫這篇文章的目的主要仍是作個總結與梳理,加深印象。web
Flex 是 Flexible Box 的縮寫,意爲"彈性佈局"。CSS 彈性盒子佈局是 CSS 的模塊之一,定義了一種針對用戶界面設計而優化的 CSS 盒子模型。在彈性佈局模型中,彈性容器的子元素能夠在任何方向上排布,也能夠「彈性伸縮」其尺寸,既能夠增長尺寸以填滿未使用的空間,也能夠收縮尺寸以免父元素溢出。子元素的水平對齊和垂直對齊都能很方便的進行操控。經過嵌套這些框(水平框在垂直框內,或垂直框在水平框內)能夠在兩個維度上構建佈局。 —— MDN瀏覽器
採用 Flex 佈局的元素,稱爲 Flex 容器(flex container),簡稱"容器"。它的全部子元素自動成爲容器成員,稱爲 Flex 項目(flex item),簡稱"項目",也叫flex
元素。佈局
Flex的兩根軸線,分別是主軸
和交叉軸
,能夠簡單理解爲水平
和豎直
兩個方向。默認狀況下主軸
對應的是水平方向
,交叉軸
對應的是豎直方向
,可是這個對應關係是能夠修改的(經過flex-direction
屬性),不少狀況下咱們也確實要修改,具體怎麼修改下面會講到。flex
以前咱們通常都默認文檔書寫時從左到右的,可是Flex沒有左右的概念,默認狀況下,flex-direction
的屬性值爲row
,意思就是主軸爲水平方向,起始線(也就是起點)在左邊。flex-direction
屬性還有其餘屬性值,這裏先不列舉,後面詳細說。優化
CSS
屬性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屬性將失效。
容器能夠設置下面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
其實就是默認的屬性值,不換行,壓縮在容器內展現,wrap
和wrap-reverse
都是換行,可是不一樣行的展現順序不一樣。
flex-flow
屬性能夠將兩個屬性 flex-direction
和 flex-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-around
和space-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
固然就看不出什麼效果了。
最後仍是看下對比圖
項目能夠設置下面幾個屬性
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-shrink
和 flex-basis
的簡寫,默認值爲0 1 auto
。後兩個屬性可選。
有幾種寫法:
單值語法
flex-grow
的屬性值。10px
),會被當作flex-basis
的屬性值。none
,auto
或initial
。雙值語法
第一個值必須爲一個無單位數,而且它會被看成 <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,概念和語法的東西大概就說這麼多,也參考了不少資料,有什麼補充和錯誤之處還請斧正,很是感謝!!!
以爲有用的話能夠點贊 + 收藏哦!
參考資料: