前段時間接手了一個基于cef1的項目孕讳,由于其特別限定的場景,在查詢了對html5的支持后巍膘,整站都采用了flexbox布局厂财,也從頭熟悉了一遍該布局的使用方法。故分享出來峡懈,供參考璃饱。
背景
Flexbox Layout
,俗稱Flexible box模型肪康,由W3C于2009年開始起草的css3布局樣式帜平。它旨在提供一種更加有效的布局方式,控制父容器中子元素的布局梅鹦,排列以及分布裆甩,甚至在它們的尺寸未知或動態(tài)變化的情況下,都能夠做到正確的展現(彈性盒子中的flex
也由此而得名)齐唆。
彈性盒子的核心概念是父容器擁有能夠改變其子元素的的寬度/高度和排列順序嗤栓,使得子元素能夠以最佳的尺寸填充整個父容器的可用空間。簡單來說箍邮,一個彈性盒子能夠充分擴展它的子元素尺寸使其填滿自身的可用空間茉帅,或者收縮子元素來防止溢出。
最重要的一點是锭弊,相對于傳統(tǒng)的塊布局block
以及行布局inline
來說堪澎,彈性盒子模型是方向不可知的(direction-agnostic
)。盡管塊布局以及行布局能夠很好的滿足頁面布局味滞,但是它們缺乏彈性樱蛤,不能很好地支持大型或者是復雜的應用(特別在屏幕進行橫豎屏切換,改變視圖尺寸剑鞍,延伸昨凡,收縮等等復雜情景下)。
注意:彈性盒子布局適合作用在一個應用的組件和小范圍的布局,例如,一個歌曲列表呻疹,一個導航條供屉,等等瑟押。相對的泽论,Grid layout韩脏,即柵格布局則傾向于進行大規(guī)模的界面布局脉让,例如晌杰,整體界面的分欄布局跷睦,左右結構,上下結構乎莉,等等送讲。
基本原理
由于彈性盒子是一整套模型而不是單獨的一個css屬性,它包含了一個屬性集合惋啃,其中的一些屬性作用于父容器(flex container
)哼鬓,另一些則作用于子元素(flex items
),所以特別需要區(qū)分這些屬性的作用對象边灭。
如果說常規(guī)布局是建立在塊級和行級方向(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-container {
flex-direction: row; // 子元素由左至右排列(默認值)
flex-direction: row-reverse; // 子元素由右向左排列
flex-direction: column; // 子元素由上至下排列
flex-direction: column-reverse; // 子元素由下至上排列
}
flex-wrap
默認情況下我衬,所有的子元素都會嘗試沿著主軸在排列在同一行(列)上,這個屬性用來對子元素進行換行排列备畦,即當子元素排列到main-end的時候低飒,會自動進行換行。
.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
定義子元素在主軸上的對其方式褥赊。主要用在當所有的子元素在同一行,且為非彈性元素時莉恼,分配剩下的額外空間拌喉;或者是彈性元素但是并沒有撐滿整個父容器的主尺寸。該屬性也能夠對溢出的子元素起到一定的控制作用俐银,例如尿背,當子元素溢出時,對其進行居中捶惜,則左右溢出的寬度將是相等的田藐。
.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屬性的交叉軸版)。
.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排列)汽久。
.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: 0;
與無order屬性
等效舷丹。
.flex-item: {
order: <integer>;
order: -1|1|2...n;
}
flex-grow
用于定義子元素能否伸展的能力抒钱。它接受一個數字來作為比例值,這使得子元素能夠自動檢測父容器中的可用空間颜凯,并將其進行填充谋币。
如果所有的子元素都有flex-grow: 1,那么所有子元素都將均分主軸的長度症概;如果其中有一個子元素有flex-grow: 2蕾额,那么這個子元素將占據其他flex-grow: 1的子元素占據主軸長度的兩倍(至少會盡量這樣做)。
.flex-item {
flex-grow: <number>; // 非負自然數(包括0)
flex-grow: 0; // 默認值
flex-grow: 1|2...n;
}
小貼士1:如果子元素的內容超過了其
flex-grow
所分配的空間彼城,則會繼續(xù)伸展诅蝶,直到滿足子元素內容的長度。
小貼士2:如果父容器設置了flex-wrap: wrap;
募壕,那么擠到第二排的子元素將按照第二排的主軸長度進行flex-grow
比例的重新計算调炬。
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
進行計算综芥。計算方式如下圖所示。
在上圖中猎拨,子元素的flex-grow
為1: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屬性(故兩者擁有同樣的屬性值)慎恒。
.flex-item {
align-seft: auto | flex-start | flex-end | center | baseline | stretch;
}
小貼士:
float
任内,clear
,vertical-align
這些屬性對一個彈性盒子布局的元素將失去作用融柬。
歡迎交流死嗦,完。
TODO:Grid layout 柵格布局
參考文獻
https://css-tricks.com/snippets/css/a-guide-to-flexbox/
https://www.w3.org/TR/css-flexbox-1/