一直知道css3的flex布局很重要膜蠢,不過由于我的工作主要是做的PC,且公司要求對(duì)IE6、IE7和IE8等瀏覽器要保證兼容性(主要是本人缺乏鉆研精神)抡砂,所以對(duì)flex用得少,這次為了準(zhǔn)備面試恬涧,需要將這個(gè)知識(shí)點(diǎn)重新整理注益。剛好趁著這個(gè)時(shí)候?qū)W習(xí)下。不到之處溯捆,還請(qǐng)各位見諒丑搔。
好,主角登場(chǎng)提揍。
CSS彈性盒子模型( Flexible Box 或者 Flexbox )
先來看看它的定義:彈性布局是指通過調(diào)整其內(nèi)元素的寬高低匙,從而在任何顯示設(shè)備上實(shí)現(xiàn)對(duì)可用顯示空間最佳填充的能力。彈性容器擴(kuò)展其內(nèi)元素來填充可用空間碳锈,或?qū)⑵涫湛s來避免溢出顽冶。
簡(jiǎn)單來說,彈性盒子模型售碳,是為了你的網(wǎng)頁可以在不同分辨率設(shè)備上自適應(yīng)展示而生的一種布局方式强重。
彈性盒子布局主要適用于應(yīng)用程序的組件及小規(guī)模的布局,而(新興的)柵格布局則針對(duì)大規(guī)模的布局贸人。這二者都是 CSS 工作組為在不同用戶代理间景、不同書寫模式和其他靈活性要求下的網(wǎng)頁應(yīng)用程序有更好的互操作性而做出的更廣泛的努力的一部分。
現(xiàn)在艺智,我們來看如何定義一個(gè)彈性盒子:
<div id="main">
<div style="background-color:coral;">A</div>
<div style="background-color:lightblue;">B</div>
<div style="background-color:khaki;">C</div>
<div style="background-color:pink;">D</div>
<div style="background-color:lightgrey;">E</div>
<div style="background-color:lightgreen;">F</div>
</div>
如果要將上面的HTML布局改為彈性盒子布局倘要,該怎么辦?
很簡(jiǎn)單J稹封拧!
只需要設(shè)置如下:
#main{
display: flex
}
或者
#main{
display: inline-flex
}
區(qū)別在于,flex會(huì)使彈性容器成為塊級(jí)元素夭问,而inline-flex會(huì)使彈性容器成為單個(gè)不可分的行內(nèi)級(jí)元素泽西。
說到這里,有人會(huì)問了缰趋,彈性容器是什么東東捧杉?陕见??
大家先來看一張圖:
對(duì)比這張圖和上面的html代碼味抖,大家可以看到:
彈性容器(Flex container)
:指的就是包含著彈性項(xiàng)目的父元素评甜,即上面的 #main
彈性項(xiàng)目(Flex item)
:彈性容器的每個(gè)子元素都稱為彈性項(xiàng)目,彈性容器直接包含的文本將被包覆成匿名彈性單元仔涩。即上面的 #main div
大家再仔細(xì)觀察上面的那張圖忍坷,圖上有個(gè)主軸和側(cè)軸,這里又涉及到一個(gè)知識(shí)點(diǎn):軸(Axis)
每個(gè)彈性框布局都包含兩個(gè)軸红柱。彈性項(xiàng)目沿其依次排列的那根軸稱為主軸(main axis)
承匣。垂直于主軸的那根軸稱為側(cè)軸(cross axis)
接下來我結(jié)合上面的HTML代碼為大家講解下怎么確定主軸和主軸上內(nèi)容的顯示:
使用彈性容器的flex-derection可以確立主軸,這個(gè)屬性一共有6個(gè)值锤悄,接下來韧骗,我為大家一一展示:
#main{
display: flex;
width: 200px;
flex-direction:row; //默認(rèn)值,水平展示
}
#main{
display: flex;
width: 200px;
flex-direction:row-reverse; //與row相同零聚,但是以相反的順序
}
#main{
display: flex;
width: 200px;
flex-direction:column; // 彈性項(xiàng)目將垂直展示
}
#main{
display: flex;
width: 200px;
flex-direction:column-reverse; // 與 column 相同袍暴,但是以相反的順序。
}
還有兩個(gè)屬性隶症,簡(jiǎn)單介紹下政模,就不用舉例了:
initial:設(shè)置該屬性為它的默認(rèn)值
inherit:從父元素繼承該屬性
確定了主軸之后,那么在主軸上彈性項(xiàng)目怎么分布蚂会?淋样?
我們來看一個(gè)新的屬性:
justify-content: 定義了在當(dāng)前行上,彈性項(xiàng)目沿主軸如何排布胁住。
#main {
display: flex;
width: 400px;
flex-direction: row;
justify-content: flex-start; //默認(rèn)值趁猴,項(xiàng)目位于容器的開頭
}
#main{
display: flex;
width: 400px;
flex-direction: row;
justify-content: flex-end; // 項(xiàng)目位于容器的結(jié)尾
}
#main{
display: flex;
width: 400px;
flex-direction: row;
justify-content: center; // 項(xiàng)目位于容器的中間
}
#main{
display: flex;
width: 400px;
flex-direction: row;
justify-content: space-between; // 項(xiàng)目位于各行之間留有空白的容器內(nèi)
}
#main{
display: flex;
width: 400px;
flex-direction: row;
justify-content: space-around; // 項(xiàng)目位于各行之前、之間彪见、之后都留有空白的容器內(nèi)儡司。
}
還有兩個(gè)屬性,簡(jiǎn)單介紹下余指,就不用舉例了:
initial:設(shè)置該屬性為它的默認(rèn)值
inherit:從父元素繼承該屬性
確定了彈性項(xiàng)目在主軸上是怎么排布的捕犬,接下來,再介紹下在側(cè)軸上是怎么排布的:
#main{
display: flex;
height: 200px;
align-items: stretch; // 默認(rèn)值酵镜,項(xiàng)目被拉伸以適應(yīng)容器
}
#main{
display: flex;
height: 200px;
align-items: center; // 項(xiàng)目位于容器的中心
}
#main{
display: flex;
height: 200px;
align-items: flex-start; // 項(xiàng)目位于容器的開頭
}
#main{
display: flex;
height: 200px;
align-items: flex-end; // 項(xiàng)目位于容器的結(jié)尾
}
#main{
display: flex;
height: 200px;
align-items: baseline; // 項(xiàng)目位于容器的基線上
}
還有兩個(gè)屬性碉碉,簡(jiǎn)單介紹下,就不用舉例了:
initial:設(shè)置該屬性為它的默認(rèn)值
inherit:從父元素繼承該屬性
如果我只想改變單個(gè)彈性項(xiàng)目的對(duì)齊方式笋婿,該怎么辦誉裆?
別怕,align-self 屬性來也缸濒!
align-self:定義了單個(gè)彈性項(xiàng)目在側(cè)軸上應(yīng)當(dāng)如何對(duì)齊足丢,這個(gè)定義會(huì)覆蓋由align-items所確立的默認(rèn)值。
還是用這個(gè)HTML來展示:
<div id="main">
<div class="a" style="background-color:coral;">A</div>
<div class="b" style="background-color:lightblue;">B</div>
<div class="c" style="background-color:khaki;">C</div>
<div class="d" style="background-color:pink;">D</div>
<div class="e" style="background-color:lightgrey;">E</div>
<div class="f" style="background-color:lightgreen;">F</div>
</div>
#main{
display: flex;
height: 200px;
align-items: center;
background: red;
}
#main div{
width: 40px;
}
#main .d{
align-self: auto; //默認(rèn)值庇配。元素繼承了它的父容器的 align-items 屬性斩跌。如果沒有父容器則為 "stretch"。
}
#main .d{
align-self: stretch; //元素被拉伸以適應(yīng)容器
}
#main .d{
align-self: center; //元素位于容器的中心
}
#main .d{
align-self: flex-start; //元素位于容器的開頭
}
#main .d{
align-self: flex-end;
}
//元素位于容器的結(jié)尾#main .d{
align-self: baseline; //元素位于容器的基線上
}
還有兩個(gè)屬性捞慌,簡(jiǎn)單介紹下耀鸦,就不用舉例了:
initial:設(shè)置該屬性為它的默認(rèn)值
inherit:從父元素繼承該屬性
說完了彈性項(xiàng)目的排布,接下來啸澡,我們回看最上面那張圖袖订,再來說說,怎么確定主軸/側(cè)軸的方向
我們先來看一個(gè)屬性:
flex-wrap:規(guī)定flex容器是單行或者多行嗅虏,同時(shí)橫軸的方向決定了新行堆疊的方向洛姑。
#main{
width: 200px;
height: 200px;
border: 1px solid #c3c3c3;
display:flex;
background: red;
flex-wrap: nowrap; // 默認(rèn)值,規(guī)定靈活的項(xiàng)目不拆行或不拆列
}
#main{
width: 200px;
height: 200px;
border: 1px solid #c3c3c3;
display:flex;
background: red;
flex-wrap: wrap; // 默認(rèn)值皮服,規(guī)定靈活的項(xiàng)目在必要時(shí)拆行或拆列
}
#main{
width: 200px;
height: 200px;
border: 1px solid #c3c3c3;
display:flex;
background: red;
flex-wrap: wrap-reverse; // 規(guī)定靈活的項(xiàng)目在必要的時(shí)候拆行或拆列楞艾,但是以相反的順序。
}
還有兩個(gè)屬性龄广,簡(jiǎn)單介紹下硫眯,就不用舉例了:
initial:設(shè)置該屬性為它的默認(rèn)值
inherit:從父元素繼承該屬性
order: 屬性將元素與序號(hào)關(guān)聯(lián)起來,以此決定哪些元素先出現(xiàn)
<div id="main">
<div class="a" style="background-color:coral;">A</div>
<div class="b" style="background-color:lightblue;">B</div>
<div class="c" style="background-color:khaki;">C</div>
<div class="d" style="background-color:pink;">D</div>
<div class="e" style="background-color:lightgrey;">E</div>
<div class="f" style="background-color:lightgreen;">F</div>
</div>
.a{
order: 6;
-webkit-order: 6;
}
.b{
order: 5;
-webkit-order: 5;
}
.c{
order: 4;
-webkit-order: 4;
}
.d{
order: 3;
-webkit-order: 3;
}
.e{
order: 2;
-webkit-order: 2;
}
.f{
order: 1;
-webkit-order: 1;
}
flex-flow:是 flex-direction 和 flex-wrap 屬性的簡(jiǎn)寫择同,決定彈性項(xiàng)目如何排布两入。
對(duì)于行(Line)中來說,根據(jù)flex-wrap屬性敲才,彈性項(xiàng)目可以排布在單個(gè)行或多個(gè)行中裹纳。此屬性控制側(cè)軸的方向和新行排列的方向
我們確定了彈性容器的主軸與側(cè)軸,彈性項(xiàng)目的寬和高归斤,怎么來確定對(duì)應(yīng)的主軸尺寸和側(cè)軸尺寸痊夭??脏里?
(1) 可以使用min-height和min-width來確定她我,這兩個(gè)的初始值都是0
(2) flex屬性是flex-grow、flex-shrink和flex-basis的簡(jiǎn)寫迫横,描述彈性項(xiàng)目的整體伸縮性番舆。
接下來,我們逐一看看這三個(gè)新的屬性
flex-grow: 用于設(shè)置或檢索彈性盒的擴(kuò)展比率
#main{
width: 500px;
height: 200px;
border: 1px solid #c3c3c3;
display:flex;
background: red;
}
#main div{
width: 40px;
}
.a{
flex-grow: 2;
}
.b{
flex-grow: 3;
}
.c{
flex-grow: 1;
}
.d{
flex-grow: 3;
}
.e{
flex-grow: 2;
}
.f{
flex-grow: 1;
}
flex-shrink: 指定了 flex 元素的收縮規(guī)則矾踱,flex 元素僅在默認(rèn)寬度之和大于容器時(shí)才會(huì)發(fā)生收縮恨狈,其收縮的大小是依據(jù)flex-shrink的值
<p>div 總寬度為 500px, flex-basic 為 120px。</p>
<p>A, B, C 設(shè)置 flex-shrink:1呛讲。 D , E 設(shè)置為 flex-shrink:2</p>
<p>D , E 寬度與 A, B, C 不同</p>
<div id="content">
<div class="box" style="background-color:red;">A</div>
<div class="box" style="background-color:lightblue;">B</div>
<div class="box" style="background-color:yellow;">C</div>
<div class="box1" style="background-color:brown;">D</div>
<div class="box1" style="background-color:lightgreen;">E</div>
</div>
flex-shrink的默認(rèn)值為1禾怠,如果沒有顯示定義該屬性返奉,將會(huì)自動(dòng)按照默認(rèn)值1在所有因子相加之后計(jì)算比率來進(jìn)行空間收縮。
本例中A吗氏、B芽偏、C 顯式定義了 flex-shrink 為 1,D弦讽、E 定義了 flex-shrink 為 2污尉,所以計(jì)算出來總共將剩余空間分成了 7 份,其中 A往产、B被碗、C 占 1 份,D仿村、E 占 2 份锐朴,即1:1:1:2:2
我們可以看到父容器定義為 500px,子項(xiàng)被定義為 120px奠宜,子項(xiàng)相加之后即為 600 px包颁,超出父容器 100px。那么超出的 100px 需要被 A压真、B娩嚼、C、D滴肿、E 消化 通過收縮因子,所以加權(quán)綜合可得 1001+1001+1001+1002+1002=700px
于是我們可以計(jì)算 A岳悟、B、C泼差、D贵少、E 將被移除的溢出量是多少:
A 被移除溢出量:(1001/700)100,即約等于14px
B 被移除溢出量:(1001/700)100堆缘,即約等于14px
C 被移除溢出量:(1001/700)100滔灶,即約等于14px
D 被移除溢出量:(1002/700)100,即約等于28px
E 被移除溢出量:(1002/700)100吼肥,即約等于28px
最后A录平、B、C缀皱、D斗这、E的實(shí)際寬度分別為:120-14=106px, 120-14=106px, 120-14=106px, 120-28=92px,120-28=92px,此外啤斗,這個(gè)寬度是包含邊框的表箭。**
flex-basis:用于設(shè)置或檢索彈性盒伸縮基準(zhǔn)值。
接下來钮莲,說幾個(gè)彈性盒子的相關(guān)屬性:
由于彈性盒子使用了不同的布局算法免钻,某些屬性用在彈性容器上沒有意義:
- 多欄布局模塊的 column-* 屬性對(duì)彈性項(xiàng)目無效
- float與clear對(duì)彈性項(xiàng)目無效彼水。使用float將使元素的display屬性記為block
- vertical-align對(duì)彈性項(xiàng)目的對(duì)齊方式無效。
最后伯襟,我們來看換一個(gè)例子:
?<!DOCTYPE html>
<html lang="en">
<head>
<style>
.flex
{
/* 基本樣式 */
width: 350px;
height: 200px;
border: 1px solid #555;
font: 14px Arial;
/* 建立彈性框 */
display: -webkit-flex;
-webkit-flex-direction: row;
display: flex;
flex-direction: row;
}
.flex > div
{
-webkit-flex: 1 1 auto;
flex: 1 1 auto;
width: 30px; /* 讓過渡表現(xiàn)良好猿涨。(從/到"width:auto"的過渡
至少在 Gecko 和 Webkit 上是有 bug 的握童。
更多信息參見 http://bugzil.la/731886 ) */
-webkit-transition: width 0.7s ease-out;
transition: width 0.7s ease-out;
}
/* colors */
.flex > div:nth-child(1){ background : #009246; }
.flex > div:nth-child(2){ background : #F1F2F1; }
.flex > div:nth-child(3){ background : #CE2B37; }
.flex > div:hover
{
width: 200px;
}
</style>
</head>
<body>
<p>Flexbox nuovo</p>
<div class="flex">
<div>uno</div>
<div>due</div>
<div>tre</div>
</div>
</body>
</html>