flexbox彈性盒子,真正意義上的布局樣式

前段時(shí)間接手了一個(gè)基于cef1的項(xiàng)目,由于其特別限定的場(chǎng)景,在查詢了對(duì)html5的支持后,整站都采用了flexbox布局,也從頭熟悉了一遍該布局的使用方法。故分享出來,供參考。

背景

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

彈性盒子的核心概念是父容器擁有能夠改變其子元素的的寬度/高度和排列順序,使得子元素能夠以最佳的尺寸填充整個(gè)父容器的可用空間。簡(jiǎn)單來說,一個(gè)彈性盒子能夠充分?jǐn)U展它的子元素尺寸使其填滿自身的可用空間,或者收縮子元素來防止溢出。

最重要的一點(diǎn)是,相對(duì)于傳統(tǒng)的塊布局block以及行布局inline來說,彈性盒子模型是方向不可知的(direction-agnostic)。盡管塊布局以及行布局能夠很好的滿足頁面布局,但是它們?nèi)狈椥裕荒芎芎玫刂С执笮突蛘呤菑?fù)雜的應(yīng)用(特別在屏幕進(jìn)行橫豎屏切換,改變視圖尺寸,延伸,收縮等等復(fù)雜情景下)。

注意:彈性盒子布局適合作用在一個(gè)應(yīng)用的組件和小范圍的布局,例如,一個(gè)歌曲列表,一個(gè)導(dǎo)航條,等等。相對(duì)的,Grid layout,即柵格布局則傾向于進(jìn)行大規(guī)模的界面布局,例如,整體界面的分欄布局,左右結(jié)構(gòu),上下結(jié)構(gòu),等等。

基本原理

由于彈性盒子是一整套模型而不是單獨(dú)的一個(gè)css屬性,它包含了一個(gè)屬性集合,其中的一些屬性作用于父容器(flex container),另一些則作用于子元素(flex items),所以特別需要區(qū)分這些屬性的作用對(duì)象。

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

彈性盒子模型

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

main axis(主軸)

父容器的主軸是子元素排列的基本軸,但這并不意味著基本軸必須是橫向的,這取決于父容器的flex-direction屬性(后邊會(huì)介紹到)。例如,如果子元素是豎向排列的,那么主軸則是豎向的那條軸。

main-start | main-end

子元素會(huì)沿著main-start從左至右排列,直到main-end。值得注意的是,默認(rèn)情況下,子元素只會(huì)排列在一排上,就算已經(jīng)到達(dá)了父容器的右邊緣,也不會(huì)進(jìn)行換行,除非設(shè)置了flex-wrap屬性(后邊會(huì)介紹到)。

main size

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

cross axis

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

cross-start | cross-end

當(dāng)父容器中的子元素?fù)Q行時(shí),子元素的行排列的方向則是沿著交叉軸進(jìn)行的,從cross-start開始,直到cross-end。

cross size

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


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


父容器屬性(flex-container)

父容器

display

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

.flex-container {
  display: flex; // 實(shí)際相當(dāng)于block-flex,塊級(jí)容器,寬度同其外層容器
  display: inline-flex; // 顧名思義,行級(jí)容器,寬度取決于其子元素
}

flex-direction

用于定義主軸方向,同時(shí)也決定了子元素的排列方向。

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

flex-wrap

默認(rèn)情況下,所有的子元素都會(huì)嘗試沿著主軸在排列在同一行(列)上,這個(gè)屬性用來對(duì)子元素進(jìn)行換行排列,即當(dāng)子元素排列到main-end的時(shí)候,會(huì)自動(dòng)進(jìn)行換行。

flex-wrap
.flex-container {
  flex-wrap: nowrap; // 子元素都在排列在同一行(默認(rèn)值)
  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; // 橫向排列 不換行(默認(rèn)值)
}

justify-content

定義子元素在主軸上的對(duì)其方式。主要用在當(dāng)所有的子元素在同一行,且為非彈性元素時(shí),分配剩下的額外空間;或者是彈性元素但是并沒有撐滿整個(gè)父容器的主尺寸。該屬性也能夠?qū)σ绯龅淖釉仄鸬揭欢ǖ目刂谱饔茫?,?dāng)子元素溢出時(shí),對(duì)其進(jìn)行居中,則左右溢出的寬度將是相等的。

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

小貼士:justify-centent: center;還可以配合align-self: center;進(jìn)行內(nèi)容的居中垂直布局。

align-items

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

align-items
.flex-container {
  align-items: flex-start; // 子元素向交叉軸起點(diǎn)看齊排列
  align-items: flex-end; // 子元素向交叉軸終點(diǎn)看齊排列
  align-items: flex-center; // 子元素在交叉軸居中排列
  align-items: flex-stretch; // 子元素沿交叉軸拉伸排列(撐滿整個(gè)交叉軸的長(zhǎng)度)(默認(rèn)值)
  align-items: flex-baseline; // 子元素在交叉軸上沿其文本的基線對(duì)其排列
}

align-content

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

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

小貼士:當(dāng)只有一排子元素時(shí),align-content屬性并沒有什么卵用。


子元素屬性(flex-items)

子元素

order

默認(rèn)情況下,子元素按照它們?cè)谠创a中出現(xiàn)的位置進(jìn)行排列。幸運(yùn)的是,通過order屬性,則能夠控制子元素在父容器中的排列順序,這大大增加了布局的靈活性。

order

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

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

flex-grow

用于定義子元素能否伸展的能力。它接受一個(gè)數(shù)字來作為比例值,這使得子元素能夠自動(dòng)檢測(cè)父容器中的可用空間,并將其進(jìn)行填充。

如果所有的子元素都有flex-grow: 1,那么所有子元素都將均分主軸的長(zhǎng)度;如果其中有一個(gè)子元素有flex-grow: 2,那么這個(gè)子元素將占據(jù)其他flex-grow: 1的子元素占據(jù)主軸長(zhǎng)度的兩倍(至少會(huì)盡量這樣做)。

flex-grow
.flex-item {
  flex-grow: <number>; // 非負(fù)自然數(shù)(包括0)
  flex-grow: 0; // 默認(rèn)值
  flex-grow: 1|2...n;
}

小貼士1:如果子元素的內(nèi)容超過了其flex-grow所分配的空間,則會(huì)繼續(xù)伸展,直到滿足子元素內(nèi)容的長(zhǎng)度。
小貼士2:如果父容器設(shè)置了flex-wrap: wrap;,那么擠到第二排的子元素將按照第二排的主軸長(zhǎng)度進(jìn)行flex-grow比例的重新計(jì)算。

flex-shrink

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

flex-shrink

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

flex-basis

用于在空間被分配前,定義子元素的默認(rèn)長(zhǎng)度。這個(gè)值可以是長(zhǎng)度(百分比,rem等等)或者是關(guān)鍵字(如auto等)。

.flex-item {
  flex-basis: <length> | auto(默認(rèn)值); 
}

需要注意的是,如果flex-basis: 0;,那么子元素內(nèi)容旁邊的額外空間是不計(jì)算在flex-basis內(nèi)的。如果設(shè)置為auto,那么額外的空間將基于子元素的flex-grow進(jìn)行計(jì)算。計(jì)算方式如下圖所示。

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

在上圖中,子元素的flex-grow1:1:2。當(dāng)flex-basis: 0;時(shí),子元素內(nèi)容旁邊的額外空間不計(jì)數(shù);flex-basis: auto;時(shí),子元素內(nèi)容旁邊的額外空間計(jì)數(shù),且比例由其flex-grow決定,這里則是1:1:2。故而,雖然我們的flex-grow設(shè)置為了1:1:2,但是由于flex-basis的影響,產(chǎn)生了不同的顯示結(jié)果。

flex

flex-grow,flex-shrink,flex-basis的屬性縮寫。其中,flex-shrink和flex-basis是可選項(xiàng),如不填寫這兩個(gè)值,則默認(rèn)值為flex-shrink: 1,flex-basis: 0%。如果整個(gè)flex屬性都不填寫,則整個(gè)屬性默認(rèn)值為0 1 auto。

.flex-item {
  flex: none | [ <'flex-grow'> <'flex-shrink'> || <'flex-basis'> ];
  flex: 0 1 auto; // 不伸展 收縮度為1 自動(dòng)基礎(chǔ)長(zhǎng)度
}

小貼士:強(qiáng)烈建議采用屬性縮寫的方式來定義子元素的彈性屬性,因?yàn)樗軒椭覀冏詣?dòng)地設(shè)置許多默認(rèn)值。

align-self

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

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

小貼士:float,clearvertical-align這些屬性對(duì)一個(gè)彈性盒子布局的元素將失去作用。

歡迎交流,完。

TODO:Grid layout 柵格布局


參考文獻(xiàn)

https://css-tricks.com/snippets/css/a-guide-to-flexbox/
https://www.w3.org/TR/css-flexbox-1/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • H5移動(dòng)端知識(shí)點(diǎn)總結(jié) 閱讀目錄 移動(dòng)開發(fā)基本知識(shí)點(diǎn) calc基本用法 box-sizing的理解及使用 理解dis...
    Mx勇閱讀 4,831評(píng)論 0 26
  • CSS 3中彈性盒布局的最新版概述 在CSS 3中,CSS Flexible Box模塊為一個(gè)非常重要的模塊,該模...
    吾名無雙閱讀 1,307評(píng)論 0 5
  • 問答題47 /72 常見瀏覽器兼容性問題與解決方案? 參考答案 (1)瀏覽器兼容問題一:不同瀏覽器的標(biāo)簽?zāi)J(rèn)的外補(bǔ)...
    _Yfling閱讀 14,155評(píng)論 1 92
  • 移動(dòng)開發(fā)基本知識(shí)點(diǎn) 一.使用rem作為單位 html { font-size: 100px; } @media(m...
    橫沖直撞666閱讀 3,728評(píng)論 0 6
  • 事實(shí)上它是一種新類型的盒子模型,也有書上稱作彈性伸縮盒布局。比較新的布局方式:旨在提供一個(gè)更加有效的方式來布置,對(duì)...
    zh_yang閱讀 11,630評(píng)論 3 14

友情鏈接更多精彩內(nèi)容