1. 彈性盒基礎(chǔ)
彈性盒子是一種簡單而強大的布局方式,我們可以通過彈性盒子指明空間的分布方式、內(nèi)容的對齊方式和元素的視覺順序。內(nèi)容可以輕易地橫向排列或者縱向排列,也可以沿著某一條軸布局。
彈性盒子最突出的一個特點,能讓元素在不同屏幕尺寸下或者不同顯示設(shè)備做好適應(yīng)準備,因為內(nèi)容可以根據(jù)空間的大小增減尺寸。
彈性盒子依賴的是父子關(guān)系。在父元素上面聲明 display: flex 來創(chuàng)建一個彈性容器,它主要負責內(nèi)部子元素的布置,控制子元素的布局。在彈性容器中的這些子元素,一般都叫彈性元素。
display: flex;
2. 彈性容器
首先要完全理解的概念是彈性容器。display: flex 聲明的目標元素會成為彈性容器,容器內(nèi)部的元素,不管是DOM節(jié)點還是文本還是生成的內(nèi)容,都稱為彈性元素。彈性容器中,絕對定位的元素也叫彈性元素,不過確定其尺寸和位置時,需要將這個彈性元素視為彈性容器中唯一一個彈性元素。
2.1 flex-direction
首先從布局的大體來看,首先要決定元素的布局排列方式:從上到下、從左到右,還是其他的排列方式。這時,可以通過 flex-direction 來改變布局順序。
flex-direction: row | row-reverse | column | column-reverse;
該屬性置頂在彈性容器中如何擺放彈性元素,即定義彈性容器的主軸,彈性元素默認會按這條主軸方向進行排列。
2.2 flex-wrap
在flex布局中,當彈性元素個數(shù)過多時,并且超過了彈性容器的寬度,這時默認情況下會將子元素進行擠壓,然后放在同一行主軸上進行排列。默認情況下,彈性元素不會進行換行,并且允許元素縮減尺寸。
同樣的,我們可以通過 flex-wrap 來讓元素進行換行處理。
flex-wrap: nowrap | wrap | wrap-reverse;
- nowrap:默認值,元素不換行;
- wrap:元素允許換行;
- wrap-reverse:只是決定多出的行顯示在第一行之后。
3. 布置彈性元素
為什么所有元素都按主軸起邊一側(cè)緊挨在一起?
3.1 元素在主軸上的分布方式
justify-content: flex-start | flex-end | center | space-around | space-between | space-evenly;
- flex-start:默認值,彈性元素緊靠主軸的起始邊;
- flex-end:彈性元素緊靠主軸的終邊進行排列,與
flex-direction: row-reverse不同,這個僅僅是將元素貼著終邊排列,沒有改變元素視覺上的布局順序; - center:把彈性元素作為一個整體,居中顯示在主軸尺寸的中點;
- space-around:把余下的空間拆分開,然后平均地分配給每一個彈性元素,看起來就像每個元素四周都有等量的外邊距;這里要注意普通元素的外邊距是第一個元素或最后一個元素與彈性容器間距離的兩倍;
- space-between:把每一行里的第一個彈性元素放在主軸的起始邊,最后一個元素放在主軸的終邊,然后剩下的每一對相鄰的彈性元素之間放置等量的空白(外邊距);
- space-evenly:把余下的空間平均拆分分配到每個元素上。
3.1.1 flex-start 和 flex-end
flex-start 是默認行為,即所有彈性元素都向主軸的起邊靠攏,每一行里的第一個彈性元素都緊靠主軸起始邊的一側(cè);
flex-end 則是在一行里的最后一個彈性元素向主軸的終邊靠攏,前面各彈性元素緊挨后一個彈性元素;
3.1.2 center
當設(shè)置為center時,所有彈性元素會擠在一起,然后統(tǒng)一居中顯示在主軸中點處,而不再向主軸起邊或者終邊靠攏。如果空間放不下躲雨的彈性元素,并且不允許換行,則會進行擠壓容納。
3.1.3 space-between
這個屬性,一行里的第一個彈性元素向主軸起始邊靠攏,一行里的最后一個元素在主軸終邊靠攏。當主軸元素上只存在一個彈性元素時,它不會居中,而是會將它放在主軸的起始邊。
3.1.4 space-around
一行中額外的空白將均勻分布在彈性元素的周圍。當一行中只有一個元素,這個元素將會居中顯示。
3.2 元素在側(cè)軸上的分布方式
justify-content 定義彈性元素在彈性容器主軸方向上的對齊方式,而 align-items 屬性定義的是彈性元素在側(cè)軸上的對齊方式。
align-items: flex-start | flex-end | center | baseline;
3.2.1 起邊對齊、終邊對齊、居中對齊
這三個值是最常見,效果也相對簡單的屬性值。
flex-start 將各彈性元素在側(cè)軸起始邊處開始進行排列,這也是默認的顯示方式;
flex-end 將各元素在側(cè)軸的終邊開始進行排列;
center 將彈性元素的中點與所在行的側(cè)軸中點進行對齊,這也是我們常用的居中對齊的方法。
3.2.2 align-self
如果想改變某個或某些彈性元素的對齊方式,而不是修改全部彈性元素,那就可以用到 align-self 這個屬性,這個屬性的取值和 align-items 一樣,只不過這個屬性只會作用在當前彈性元素上。
將奇數(shù)彈性元素進行側(cè)軸上的居中對齊
li:nth-child(odd) {
align-self: center;
}
4. 對齊內(nèi)容
align-content: flex-start | flex-end | center | space-between | space-around | space-evenly;
該屬性定義彈性容器有額外空間時,在側(cè)軸方向上如何對齊各彈性元素行。
與之前的屬性 align-items 比較,align-content 屬性指定的是容器中側(cè)軸方向上額外空間如何分配到彈性元素行之間和周圍,而 align-items 則是指定每一行彈性元素的分布位置,雖然在效果上會有相似的地方,但是實際上的作用是完全不同的。
align-content 它的默認值并不是 flex-start ,而是一個叫 stretch 的屬性值。這個屬性值,將額外的空間平均分配到每個彈性元素中,增加行的側(cè)軸尺寸,直到邊與邊重合。這也是導(dǎo)致我們彈性元素換行時,沒有緊跟上一行元素的罪魁禍首。
5. flex 屬性
flex: <flex-grow> <flex-shrink> <flex-basis> | none;
彈性布局最突出的一點,就是把彈性元素變得具有彈性,在主軸方向上調(diào)整彈性元素的寬度或者高度,可以占滿可用的空間。彈性容器會根據(jù)彈性增長因子分配額外的空間或者根據(jù)彈性縮減因子按比例縮小元素,以防溢出。
5.1 flex-grow
彈性增長因子。該屬性定義有多余空間時,是否允許彈性元素增大,以及允許增大且有多余空間時,相對其他同輩的元素以多大的比例去增大。簡單來說,如果彈性容器有多余的空間,這空間將會按照彈性增長因子的比例去分配給各個彈性元素。
flex-grow: <number>;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
list-style: none;
text-decoration: none;
}
.father {
width: 750px;
height: 400px;
background-color: pink;
display: flex;
}
.son {
width: 100px;
height: 100px;
background-color: skyblue;
line-height: 100px;
box-sizing: border-box;
border: 1px solid #000;
font-size: 30px;
}
.sonC{
flex-grow: 1;
}
</style>
</head>
<body>
<div class="father">
<div class="son sonA"></div>
<div class="son sonB"></div>
<div class="son sonC"></div>
</div>
</body>
</html>
當設(shè)置 .sonC 的增長因子為1時,多余的空間將會按照 0:0:1 的比例分配到每個元素上,0就代表不分配,這樣就會把剩余的空間全都添加到 .sonC 元素上。
flex-grow 雖然可以設(shè)置很大的數(shù)值,但是實際上看的是每個元素之間的比例大小。1:1:2 和 20:20:40 帶來的效果是一樣的。
5.2 flex-shrink
該屬性指的是彈性縮減因子,當彈性容器定義的空間不足以容納所有的彈性元素,且不允許換行的情況下,每個彈性元素都會以縮減因子這個比例去縮小寬高。
/* 這個值和 flex-grow 一樣,可以取數(shù)字,可以小數(shù)但不能負數(shù)。默認值為 1; */
flex-shrink: <number>;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
list-style: none;
text-decoration: none;
}
.father {
width: 750px;
height: 400px;
background-color: pink;
display: flex;
}
.son {
width: 300px;
height: 300px;
background-color: skyblue;
line-height: 100px;
box-sizing: border-box;
border: 1px solid #000;
font-size: 30px;
flex-shrink: 0;
}
.sonA {
/* flex-grow: 20; */
flex-shrink: 1;
}
.sonB {
/* flex-grow: 20; */
}
.sonC {
/* flex-grow: 40; */
}
</style>
</head>
<body>
<div class="father">
<div class="son sonA"></div>
<div class="son sonB"></div>
<div class="son sonC"></div>
</div>
</body>
</html>
按照例子的情況,子元素需要一共縮減150px,才能讓sonC容納進來。通過上面的設(shè)置,150px 將會以 1:0:0 的比例在每個彈性元素上進行縮減。所以 sonA 這個元素將會縮減150px。
對于縮減因子,需要注意一個地方:如果某個彈性元素的內(nèi)部存在無法縮小的元素(例如圖片、視頻、文字)或者定義了寬高,那么這個彈性元素在達到這個內(nèi)部元素的寬度時,將會等同于 flex-shrink: 0 時的效果,縮小這個操作將會交給其他彈性元素了。
5.3 flex-basis
我們知道,彈性元素的尺寸受到內(nèi)容及模型屬性的影響,而且可以通過 flex 的幾個屬性來重置。其中 flex-basis 就定義了彈性元素的初始或者默認尺寸,即根據(jù)增長因子和縮小因子分配或減小空間前,彈性元素的大小。
flex-basis: auto | content | <length> | <percentage>;
在效果上,flex-basis 雖然和 width 的效果大體是一樣的,但實際上,在 Flex 布局中,彈性元素設(shè)置的 width 其實沒有任何效果。這里其實并不是 width 直接生效,而是 flex-basis 帶來的作用。
回到 flex-basis: auto 這個屬性值上,它具體的含義是彈性元素的基本尺寸是根據(jù)自身的尺寸來決定的,而自身的尺寸和下面幾個因素有關(guān):
- 盒模型,默認作用在
content-box上; -
width還有min-width和max-width等 CSS 屬性; - content 內(nèi)容;
例子一
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
list-style: none;
text-decoration: none;
}
.father {
width: 750px;
height: 400px;
background-color: pink;
display: flex;
}
.son {
/* width: 200px; */
flex-basis: 200px;
height: 300px;
background-color: skyblue;
line-height: 100px;
box-sizing: border-box;
border: 1px solid #000;
font-size: 30px;
flex-shrink: 1;
}
.sonA {
/* flex-grow: 20; */
}
.sonB {
/* flex-grow: 20; */
flex-shrink: 1;
}
.sonC {
/* flex-grow: 40; */
}
/* img {
width: 250px;
height: 200px;
} */
.test {
width: 250px;
height: 200px;
background-color: yellow;
}
</style>
</head>
<body>
<div class="father">
<div class="son sonA"></div>
<div class="son sonB"></div>
<div class="son sonC">aaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
</div>
</body>
</html>
因為此時的 content 內(nèi)容最小寬度超過了 200px,于是 flex-basis: 200px 不會按照寬度來顯示,而是按照最小內(nèi)容寬度顯示了。但是通過 width: 200px 來設(shè)置的尺寸,則會把彈性元素限制得死死的,字符直接溢出到外面。
5.4 簡寫屬性 flex
按照上面的知識點,我們知道每個子屬性的默認值 flex-grow: 0 flex-shrink: 1 flex-basis: auto,在簡寫屬性中,可以這樣表達:
flex: 0 1 auto;
在一般開發(fā)時,我們都不太需要控制后面兩個屬性,因為會進行元素的換行處理。所以一般只需要考慮它的增長因子。
flex: 1;
當 flex 屬性只有一個值時且是正數(shù)時,這個值將會用作增長因子。
6. order 屬性
在默認情況下,彈性元素的顯示和排列順序在源碼中的順序是一致的。在某些情況下,需要單獨改變某個元素的排列位置,比如1,2,3的排列方式改為,1,3,2 的順序。這時就可以通過 order 來控制。
order改變的只是視覺上的順序,源碼的順序不會發(fā)生改變。比如 Tab 鍵索引的順序,不會受到 order 的影響。
order: <integer>;
默認值為0,意思是所有元素的順序都是0,則代表在同一排序組中,元素是按照源碼中的順序沿主軸方向進行排列。order 的值,越小越靠前。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
list-style: none;
text-decoration: none;
}
.father {
/* width: 750px; */
height: 900px;
background-color: pink;
display: flex;
flex-wrap: wrap;
}
.son {
width: 100px;
height: 100px;
line-height: 300px;
background-color: skyblue;
line-height: 100px;
box-sizing: border-box;
border: 1px solid #000;
font-size: 30px;
text-align: center;
}
.sonE {
order: -1;
}
.sonD {
order: 1;
}
</style>
</head>
<body>
<div class="father">
<div class="son sonA">1</div>
<div class="son sonB">2</div>
<div class="son sonC">3</div>
<div class="son sonD">4</div>
<div class="son sonE">5</div>
<div class="son sonF">6</div>
</div>
</body>
</html>