1. 程式人生 > >彈性盒子的使用

彈性盒子的使用

背景

Flexbox Layout,俗稱Flexible box模型,由W3C於2009年開始起草的css3佈局樣式。它旨在提供一種更加有效的佈局方式,控制父容器中子元素的佈局,排列以及分佈,甚至在它們的尺寸未知或動態變化的情況下,都能夠做到正確的展現(彈性盒子中的flex也由此而得名)。

彈性盒子的核心概念是父容器擁有能夠改變其子元素的的寬度/高度和排列順序,使得子元素能夠以最佳的尺寸填充整個父容器的可用空間。簡單來說,一個彈性盒子能夠充分擴充套件它的子元素尺寸使其填滿自身的可用空間,或者收縮子元素來防止溢位。

最重要的一點是,相對於傳統的塊佈局block以及行佈局inline來說,彈性盒子模型是方向不可知的(direction-agnostic

)。儘管塊佈局以及行佈局能夠很好的滿足頁面佈局,但是它們缺乏彈性,不能很好地支援大型或者是複雜的應用(特別在螢幕進行橫豎屏切換,改變檢視尺寸,延伸,收縮等等複雜情景下)。

注意:彈性盒子佈局適合作用在一個應用的元件和小範圍的佈局,例如,一個歌曲列表,一個導航條,等等。相對的,Grid layout,即柵格佈局則傾向於進行大規模的介面佈局,例如,整體介面的分欄佈局,左右結構,上下結構,等等。

基本原理

由於彈性盒子是一整套模型而不是單獨的一個css屬性,它包含了一個屬性集合,其中的一些屬性作用於父容器(flex container),另一些則作用於子元素(flex items),所以特別需要區分這些屬性的作用物件

如果說常規佈局是建立在塊級和行級方向(block and inline flow directions)上的,那麼彈性盒子佈局則是建立彈性流方向(flex-flow directions)上的。

  彈性盒子模型

如上圖所示,假設主軸是橫向的,那麼子元素將會沿著主軸從左至右依次排列,或者是沿著與主軸垂直的交叉軸由上至下依次排列。下面我們一一進行剖析:

main axis(主軸)

父容器的主軸是子元素排列的基本軸,但這並不意味著基本軸必須是橫向的,這取決於父容器的flex-direction

屬性(後邊會介紹到)。例如,如果子元素是豎向排列的,那麼主軸則是豎向的那條軸。

main-start | main-end

子元素會沿著main-start從左至右排列,直到main-end。值得注意的是,預設情況下,子元素只會排列在一排上,就算已經到達了父容器的右邊緣,也不會進行換行,除非設定了flex-wrap屬性(後邊會介紹到)。

main size

在父容器中主軸上的子元素的主尺寸(不論寬度或者高度)之和,構成了彈性盒子的主尺寸。例如,如果子元素是橫向排列的,則寬度則是主尺寸,相對的,如果子元素是豎向排列的,則高度則是主尺寸。

cross axis

垂直於主軸的軸,稱之為交叉軸。顯然,交叉軸的方向取決於主軸的方向。

cross-start | cross-end

當父容器中的子元素換行時,子元素的行排列的方向則是沿著交叉軸進行的,從cross-start開始,直到cross-end。

cross size

和main size同理,只是方向與之垂直。


下面進行彈性盒子屬性詳解,分為兩類,分別是父容器屬性和子元素屬性。


父容器屬性(flex-container)

  父容器

display

用於定義彈性盒子的顯示方式。

.flex-container {
  display: flex; // 實際相當於block-flex,塊級容器,寬度同其外層容器
  display: inline-flex; // 顧名思義,行級容器,寬度取決於其子元素
}

flex-direction

用於定義主軸方向,同時也決定了子元素的排列方向。

  flex-direction
.flex-container {
  flex-direction: row; // 子元素由左至右排列(預設值)
  flex-direction: row-reverse; // 子元素由右向左排列
  flex-direction: column; // 子元素由上至下排列
  flex-direction: column-reverse; // 子元素由下至上排列 } 

flex-wrap

預設情況下,所有的子元素都會嘗試沿著主軸在排列在同一行(列)上,這個屬性用來對子元素進行換行排列,即當子元素排列到main-end的時候,會自動進行換行。

  flex-wrap
.flex-container {
  flex-wrap: nowrap; // 子元素都在排列在同一行(預設值)
  flex-wrap: wrap; // 子元素將沿著交叉軸正向排列在多行中
  flex-wrap: wrap-reverse; // 子元素將沿著交叉軸反向排列在多行中
}

flex-flow

flex-direction和flex-wrap的屬性縮寫。

.flex-container {
  flex-flow: <'flex-direction'> || <'flex-wrap'>;
  flex-flow: row nowrap; // 橫向排列 不換行(預設值) } 

justify-content

定義子元素在主軸上的對其方式。主要用在當所有的子元素在同一行,且為非彈性元素時,分配剩下的額外空間;或者是彈性元素但是並沒有撐滿整個父容器的主尺寸。該屬性也能夠對溢位的子元素起到一定的控制作用,例如,當子元素溢位時,對其進行居中,則左右溢位的寬度將是相等的。

  justify-content
.flex-container {
  justify-content: flex-start; // 子元素向主軸起點看齊排列(預設值)
  justify-content: flex-end; // 子元素向主軸終點看齊排列
  justify-content: center; // 子元素居中排列
  justify-content: space-between; // 子元素以相同的間距從主軸的起點和終點開始平均排列 justify-content: space-around; // 子元素以相同的邊距延主軸平均排列 } 

小貼士:justify-centent: center;還可以配合align-self: center;進行內容的居中垂直佈局

align-items

用於定義排列在同一主軸的子元素在交叉軸方向上的排列方式(可以想象成是justify-content屬性的交叉軸版)。

  align-items
.flex-container {
  align-items: flex-start; // 子元素向交叉軸起點看齊排列
  align-items: flex-end; // 子元素向交叉軸終點看齊排列
  align-items: flex-center; // 子元素在交叉軸居中排列
  align-items: flex-stretch; // 子元素沿交叉軸拉伸排列(撐滿整個交叉軸的長度)(預設值) align-items: flex-baseline; // 子元素在交叉軸上沿其文字的基線對其排列 } 

align-content

用於定義父容器中的多行/列在交叉軸上的排列方式(有點類似於多個子元素在主軸上的justify-content排列)。

  align-content
.flex-container {
  align-content: flex-start; // 多排子元素從交叉軸起點進行排列
  align-content: flex-end; // 多排子元素從交叉軸終點進行排列
  align-content: center; // 多排子元素在交叉軸居中排列
  align-content: stretch; // 多排子元素沿交叉軸拉伸排列(撐滿整個交叉軸的長度)(預設值) align-content: space-between; // 多排子元素以相同的間距從交叉軸的起點和終點開始平均排列 align-around: // 多排子元素以相同的邊距延交叉軸平均排列 } 

小貼士:當只有一排子元素時,align-content屬性並沒有什麼卵用。


子元素屬性(flex-items)

  子元素

order

預設情況下,子元素按照它們在原始碼中出現的位置進行排列。幸運的是,通過order屬性,則能夠控制子元素在父容器中的排列順序,這大大增加了佈局的靈活性。

  order

上圖中的數字,代表了元素的順序值(整型,且接受負值),且order: 0;無order屬性等效。

.flex-item: {
  order: <integer>;
  order: -1|1|2...n; } 

flex-grow

用於定義子元素能否伸展的能力。它接受一個數字來作為比例值,這使得子元素能夠自動檢測父容器中的可用空間,並將其進行填充。

如果所有的子元素都有flex-grow: 1,那麼所有子元素都將均分主軸的長度;如果其中有一個子元素有flex-grow: 2,那麼這個子元素將佔據其他flex-grow: 1的子元素佔據主軸長度的兩倍(至少會盡量這樣做)。

  flex-grow
.flex-item {
  flex-grow: <number>; // 非負自然數(包括0)
  flex-grow: 0; // 預設值
  flex-grow: 1|2...n; } 

小貼士1:如果子元素的內容超過了其flex-grow所分配的空間,則會繼續伸展,直到滿足子元素內容的長度。
小貼士2:如果父容器設定了flex-wrap: wrap;,那麼擠到第二排的子元素將按照第二排的主軸長度進行flex-grow比例的重新計算。

flex-shrink

用於定義了子元素收縮的能力。

  flex-shrink

上圖中,父容器寬度固定為500px,子元素設定了flex-basis: 120px; flex-shrink: 1;,此時,D和E設定了flex-shrink: 2。這樣,D和E將會收縮自身的長度,儘量將所有的元素都排在父容器的主軸上且儘量不超過父容器的寬度500px

flex-basis

用於在空間被分配前,定義子元素的預設長度。這個值可以是長度(百分比,rem等等)或者是關鍵字(如auto等)。

.flex-item {
  flex-basis: <length> | auto(預設值); 
}

需要注意的是,如果flex-basis: 0;,那麼子元素內容旁邊的額外空間是不計算在flex-basis內的。如果設定為auto,那麼額外的空間將基於子元素的flex-grow進行計算。計算方式如下圖所示。

  https://www.w3.org/TR/css-flexbox-1/images/rel-vs-abs-flex.svg

在上圖中,子元素的flex-grow1:1:2。當flex-basis: 0;時,子元素內容旁邊的額外空間不計數;flex-basis: auto;時,子元素內容旁邊的額外空間計數,且比例由其flex-grow決定,這裡則是1:1:2。故而,雖然我們的flex-grow設定為了1:1:2,但是由於flex-basis的影響,產生了不同的顯示結果。

flex

flex-grow,flex-shrink,flex-basis的屬性縮寫。其中,flex-shrink和flex-basis是可選項,如不填寫這兩個值,則預設值為flex-shrink: 1,flex-basis: 0%。如果整個flex屬性都不填寫,則整個屬性預設值為0 1 auto。

.flex-item {
  flex: none | [ <'flex-grow'> <'flex-shrink'> || <'flex-basis'> ]; flex: 0 1 auto; // 不伸展 收縮度為1 自動基礎長度 } 

小貼士:強烈建議採用屬性縮寫的方式來定義子元素的彈性屬性,因為它能幫助我們自動地設定許多預設值。

align-self

允許單個子元素覆寫父容器的align-items屬性(故兩者擁有同樣的屬性值)。

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

小貼士:floatclearvertical-align這些屬性對一個彈性盒子佈局的元素將失去作用。

歡迎交流,完。

TODO:Grid layout 柵格佈局



作者:JSoon
連結:https://www.jianshu.com/p/ce5d23ec13aa
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯絡作者獲得授權並註明出處。