1. Flex布局與回應式布局
1.1 為什么需要回應式布局?
在電腦PC端,使用浮動,定位同時使用像素px單位就可以完成大部分布局,而且布局完之后不會有大問題,但是到了移動端,移動設備的螢屏尺寸多種多樣,從小螢屏的智能手機到大螢屏的平板電腦,甚至是可穿戴設備,簡單地運用和PC端一樣的方式就會出現一些布局和排列的問題,
這里用PC端的縮放瀏覽器來舉個例子,當瀏覽器縮小的時候,百度就只顯示了一部分,無法在縮小的螢屏(瀏覽器視窗)中完全顯示,
移動前端中常說的 viewport (視口)就是瀏覽器中用于呈現網頁的區域,視口通常并不等于螢屏大小,特別是可以縮放瀏覽器視窗的情況下,為了確保在不同設備上都能夠提供良好的用戶體驗,需要使用回應式布局來適應不同的螢屏尺寸,
1.2 回應式布局的解決方案
回應式布局有多種方案,比如:
- 媒體查詢:它允許根據設備的特性(如螢屏寬度、設備型別等)應用不同的樣式規則,通過使用媒體查詢,可以針對不同的螢屏尺寸和設備型別應用不同的樣式,從而實作回應式布局,
- 流式布局(百分比布局):它是一種基于相對單位(如百分比)進行設計的布局方式,在流式布局中,元素的寬度和高度相對于父元素或視口進行計算,使得它們可以根據可用空間的大小進行自適應調整,流式布局可以使頁面在不同螢屏尺寸下保持比例和流動性,
- Flex布局:Flexbox是CSS3中的一種彈性盒子布局模型,它提供了強大的排列和對齊功能,可以實作靈活的回應式布局,通過使用Flexbox屬性和值,可以輕松地控制元素在容器中的位置、順序和大小,
- 柵格系統:柵格系統是一種將頁面劃分為多個網格列的布局方式,通過定義網格列數和間距來布局頁面內容,柵格系統通常與媒體查詢和流式布局結合使用,以實作在不同螢屏尺寸下的回應式布局,流行的柵格系統包括Bootstrap的柵格系統和Foundation的柵格系統,
本文主要介紹Flex布局
1.3 Flex布局的優越性
排列靈活,樣式簡單:Flex布局在回應式解決方案中具有靈活的排列和對齊、自適應的彈性性質、自動換行和調整順序以及容器和專案的靈活性等優點,可以通過簡單的CSS屬性設定來控制元素在容器中的位置和布局,通過設定容器的flex-direction、justify-content和align-items等屬性,可以輕松實作水平或垂直方向上的排列和對齊需求,這種靈活性使得在不同設備上適應不同布局要求變得容易,相比起針對不同螢屏來設定的媒體查詢,相同的樣式設定就可以適配多種螢屏尺寸,Flex布局非常的方便,
自動換行,調整順序:在移動設備上,螢屏空間有限,需要在有限的空間中合理布局元素,Flex布局可以通過設定flex-wrap屬性實作自動換行,使得專案可以在一行排列不下時自動換行到下一行,此外,還可以使用order屬性調整專案的顯示順序,以便在移動設備上優先顯示重要內容,這種自動換行和調整順序的特性使得在小螢屏設備上實作良好的用戶體驗變得簡單,
除了回應式布局外,在PC端也可以利用Flex布局來替代浮動和定位,完成很好的元素排列,讓開發者免去使用float,position來布局的不便,最常見的八股文面試題,垂直水平居中就可以用flex布局輕松完成,這也是作業中較為常用的方式,
2. Flex布局定義
Flex布局對于元素的行內(行內)或塊級的性質是不關心的,在Flex布局中,元素會根據容器和專案的屬性進行排列,無論元素是行內元素還是塊級元素,采用Flex布局的元素,稱為Flex容器(flex container),簡稱”容器”,Flex容器的所有子元素自動成為容器成員,稱為Flex專案(flex item),簡稱”專案”,
容器默認存在兩根軸:水平的主軸(main axis)和垂直的交叉軸(cross axis),主軸的開始位置(與邊框的交叉點)叫做main start,結束位置叫做main end;交叉軸的開始位置叫做cross start,結束位置叫做cross end,
專案默認沿主軸排列,單個專案占據的主軸空間叫做main size,占據的交叉軸空間叫做cross size,
3. Flex容器屬性
3.1 開啟flex布局display:flex
元素寫了這個屬性之后,就變成了一個flex的容器,就可以通過flex布局相關的方式去操作排列子元素,
<style>
.parent{
display: flex;
width: 400px;
height: 200px;
background-color:blueviolet;
}
.child{
width: 100px;
height: 50px;
background-color: aqua;
border: 1px solid black;
}
</style>
</head>
<body>
<div >
<div >1</div>
<div >2</div>
</div>
</body>
開啟flex布局之后,沒有進行其他的設定,可以看到這個排列和沒有開啟flex布局的時候是不一樣的,2個塊級元素,并沒有上下排列,而是已經排列在左右,開啟flex布局后,容器中的專案默認會沿著主軸進行排列,此時沒有對容器和專案進行其他的設定,主軸也按照默認的方向水平放置,所以2個子盒子都沿著主軸水平排列了,
3.2 改變主軸的方向flex-direction屬性
flex-direction屬性決定了主軸的方向,所有容器中的專案都會根據主軸方向來排列,
flex-direction 屬性有四個可能的取值:
- row(默認值):Flex 專案水平排列,起點在左端,終點在右端,主軸從左到右,
- row-reverse:Flex 專案水平排列,起點在右端,終點在左端,主軸從右到左,
- column:Flex 專案垂直排列,起點在頂部,終點在底部,主軸從上到下,
- column-reverse:Flex 專案垂直排列,起點在底部,終點在頂部,主軸從下到上,
圖中顯示flex-direction的值為row時元素按順序從左往右橫向排列,子元素貼著父元素的左側
1 .parent{
2 display: flex;
3 flex-direction: row;
4 width: 400px;
5 height: 200px;
6 background-color:blueviolet;
7 }
圖中顯示flex-direction的值為row-reverse時元素按順序從右往左橫向排列,子元素貼著父元素的右側(代碼同上)
圖中顯示flex-direction的值為column時元素按順序從上往下豎向排列,子元素貼著父元素的頂部,這一點類似于常規的檔案流中塊級元素的排列(代碼同上)
圖中顯示flex-direction的值為column-reverse時元素按順序從下往上豎向排列,子元素貼著父元素的底部(代碼同上)
總的來說,flex-direction屬性雖然簡單,但是有重要的作用,可以
- 控制主軸方向:flex-direction 屬性決定了主軸的方向,即 Flex 專案在水平方向或垂直方向上的排列,通過設定不同的取值,我們可以實作水平排列(左到右或右到左)或垂直排列(從上到下或從下到上)的布局,
- 確定起點和終點:flex-direction 屬性的取值影響了 Flex 專案在主軸上的起點和終點的位置,在 row 值下,起點位于左端,終點位于右端;在 row-reverse 值下,起點位于右端,終點位于左端;在 column 值下,起點位于頂部,終點位于底部;在 column-reverse 值下,起點位于底部,終點位于頂部,這種控制起點和終點的能力對于設計布局非常有用,
- 影響專案排列順序:flex-direction 屬性還決定了 Flex 專案在主軸上的排列順序,在默認的 row 值下,Flex 專案按照其在 HTML 結構中的順序從左到右排列;在 row-reverse 值下,專案按照相反的順序從右到左排列;在 column 值下,專案按照結構順序從上到下排列;在 column-reverse 值下,專案按照相反的順序從下到上排列,通過改變專案的排列順序,我們可以調整 Flex 布局的外觀和行為,
3.3 改變換行方式flex-wrap屬性
flex-wrap屬性決定了換行相關的策略,它決定了當彈性容器的寬度不足以容納所有子元素時,是否允許子元素換行并如何排列,
它有幾個常用的屬性值:
- nowrap(默認值):子元素不換行,盡可能地將它們放在一行內,即使溢位彈性容器的邊界,
- wrap:如果子元素在一行內放不下,將它們進行換行,從新行開始排列,
- wrap-reverse:與 wrap 相同,但換行時的排列順序與正常順序相反,
當沒有寫flex-wrap屬性時,所有元素會默認沿著主軸在一行(或一列)排列,這也就和寫了flex-wrap: nowrap是等效的
在已經給子專案設定了100px的寬度的情況下,6個專案仍然會排在同一行,而此時父元素的寬度也只有400px,說明此時子專案的寬度已經被壓縮了變成了小于100px,
1 <style>
2 .parent {
3 display: flex;
4 width: 400px;
5 height: 200px;
6 background-color: blueviolet;
7 }
8
9 .child {
10 width: 100px;
11 height: 50px;
12 background-color: aqua;
13 border: 1px solid black;
14 }
15 </style>
16 <body>
17 <div class="parent">
18 <div class="child">1</div>
19 <div class="child">2</div>
20 <div class="child">3</div>
21 <div class="child">4</div>
22 <div class="child">5</div>
23 <div class="child">6</div>
24 </div>
25 </body>
當希望子專案完成換行的時候可以設定flex-wrap: wrap
明顯可以看到,圖片已經完成了換行效果,但是這里上下兩行元素出現了空隙,似乎與預期效果不符合,這是由于多行對齊時的align-content的默認值導致的,具體align-content用法會在后文解釋,
1 .parent {
2 display: flex;
3 flex-wrap: wrap;
4 width: 400px;
5 height: 200px;
6 background-color: blueviolet;
7 }
8
9 .child {
10 width: 100px;
11 height: 50px;
12 background-color: aqua;
13 border: 1px solid black;
14 }
當換行屬性設定為flex-wrap: wrap-reverse,也會完成換行,但是換行的順序與前面相反,第一行會在最下面,最后一行在上面
3.4 主軸對齊方式justify-content屬性
justify-content是flex布局中的重要屬性之一,用于定義和調整彈性容器中專案在主軸上的對齊方式,它控制專案沿著主軸的分布方式,包括專案之間的間距、對齊和對齊方式的調整,
這個屬性常用的有以下幾個值
- flex-start(默認值):將專案對齊到彈性容器的起始位置,專案靠主軸起始端對齊,
- flex-end:將專案對齊到彈性容器的末尾位置,專案靠主軸末尾端對齊,
- center:將專案在主軸上居中對齊,專案在主軸上平均分布,兩端留有相同的空白,
- space-between:將專案在主軸上平均分布,并使專案之間的間距相等,首個專案對齊到主軸起始端,最后一個專案對齊到主軸末尾端,
- space-around:將專案在主軸上平均分布,并使專案之間的間距相等,首尾兩端的間距是相鄰專案間距的一半,
- space-evenly:將專案在主軸上平均分布,并使專案之間的間距相等,首尾兩端和相鄰專案之間的間距相等,
不寫justify-content或者justify-content的值為flex-start時,flex容器內部的專案會按順序沿著主軸排列,也就是當主軸是水平的時候就橫過來排列,主軸是豎直的就豎過來排列,
以較常見的flex-direction取默認值row的時候舉例,有類似于float:left的效果,但是不會出現子元素浮動后脫離檔案流導致父元素高度塌陷的問題,
1 .parent {
2 display: flex;
3 justify-content: flex-start;
4 width: 400px;
5 height: 200px;
6 background-color: blueviolet;
7 }
justify-content的值為flex-end時,子元素也就是flex容器會靠主軸的終點處對齊,與前面的flex-start呈現相反的對齊排列效果,
以較常見的flex-direction取默認值row的時候舉例,類似于float:right的效果,但是與右浮動不同的是右浮動會導致元素倒序排列而flex-end會保持元素的順序,元素的排列順序仍然是1,2,3,
1 <div class="parent">
2 <div class="child">1</div>
3 <div class="child">2</div>
4 <div class="child">3</div>
5 </div>
對于右浮動會出現倒序的原因,這里進行簡單的解釋:
浮動的元素直到碰到邊緣或另一個浮動元素的邊緣為止,而代碼又是從上往下執行,對于第一個child會優先進行浮動,碰到父盒子右邊緣,結束,第二個child再開始浮動,碰到第一個child的左邊緣再結束,第三個child在第二個child浮動結束后再浮動,就貼著第二個child左邊緣,
解決右浮動倒序的方法可以有以下幾種:
- 利用flex布局的flex-end,如上圖所示
- 倒序書寫元素,這樣就可以正序排列了,
- 對于多個右浮動的child,再在外面加一層div包裹,先讓外層的div右浮動(只有一個盒子,不會出現順序問題的同時又能靠右對齊),然后讓每個child左浮動(左浮動不會導致順序出現問題,又可以實作浮動效果),代碼和圖片如下
<style> .parent { width: 400px; height: 200px; background-color: blueviolet; } .wrapper { float: right; } .child { float: left; width: 100px; height: 50px; background-color: aqua; border: 1px solid black; } </style> </head> <body> <div class="parent"> <div class="wrapper"> <div class="child">1</div> <div class="child">2</div> <div class="child">3</div> </div> </div> </body>
justify-content的值為center時,flex容器內的元素在主軸上居中對齊,向兩邊平均分布
以較常見的flex-direction取默認值row的時候舉例,圖中利用flex布局的justify-content:center 可以非常方便地實作塊級元素的居中對齊
justify-content的值為space-between時,專案會在主軸兩端對齊,中間平均排列,讓不同的專案之間的間距相等
這里將每個child的寬度調成50px讓多個盒子都能呈現在父容器內(同時避免尺寸發生變化)以展示space-between的效果,
這種布局形式在真實開發中也較為常用,有許多場景都需要兩端對齊后,中間均分空隙,
以較常見的flex-direction取默認值row的時候舉例,可以看到子專案中的間距都是相同的,在沒有設定任何margin的情況下,元素也可以完成分離,
1 .parent {
2 display: flex;
3 justify-content: space-between;
4 width: 400px;
5 height: 200px;
6 background-color: blueviolet;
7 }
8
9 .child {
10 width: 50px;
11 height: 50px;
12 background-color: aqua;
13 border: 1px solid black;
14 }
justify-content的值為space-around時,每個專案自身的左右間距會相等,類似于設定了左右兩邊相同的margin值
以較常見的flex-direction取默認值row的時候舉例,看起來首尾元素間距更窄,是因為對于中間元素一共有2份間距,前一個元素的右間距+后一個元素的左間距,所以中間的間距是首尾的兩倍,
justify-content的值為space-evenly時,所有專案的間距都會相等,前面提到的space-around會讓每個專案自身都具有相同左右邊距,導致中間的間距疊加成立首尾的2倍,而space-evenly中會讓所有的間距都相等,包括剛才所提到的首尾和中間,
以較常見的flex-direction取默認值row的時候舉例,所有間距都相同,
3.5 交叉軸單行對齊align-items屬性
與justify-content對應的,align-items用于定義和調整彈性容器中專案在交叉軸上的對齊方式,它同樣也控制專案沿著交叉軸的分布方式,包括專案之間的間距、對齊和對齊方式的調整,
這個屬性有以下幾個常用的值
- stretch(默認值):將專案在交叉軸上拉伸以填充整個彈性容器,專案將沿交叉軸方向拉伸至與容器的交叉軸尺寸相等,
- flex-start:將專案對齊到彈性容器的交叉軸起始位置,專案靠交叉軸起始端對齊,
- flex-end:將專案對齊到彈性容器的交叉軸末尾位置,專案靠交叉軸末尾端對齊,
- center:將專案在交叉軸上居中對齊,專案在交叉軸上平均分布,上下留有相同的空白,
- baseline:將專案在交叉軸上與其基線對齊,專案的基線與其他專案的基線對齊,
這里先從默認不寫這個屬性來看,雖然align-items里也有和justify-content相同的flex-start值,但是這里的默認值并不是flex-start而是stretch,stretch的意思是伸展、延伸,也就是說寫了stretch之后(或者直接不寫align-items讓他取默認值),專案會在交叉軸上伸展,
以沒有寫高度的專案舉例
1 .parent {
2 display: flex;
3 justify-content: stretch;
4 width: 400px;
5 height: 200px;
6 background-color: blueviolet;
7 }
8
9 .child {
10 width: 50px;
11 background-color: aqua;
12 border: 1px solid black;
13 }
注意,以上代碼中,子元素沒有設定高度,所以flex專案完成拉伸并且在交叉軸上填滿整個父容器的高度(或寬度),當然如果專案分多行排列,也會撐滿整個父容器,每個專案的高度會被拉伸到:父元素高度/行數,
如果子專案已經設定了高度,那么這個屬性就不會生效,不會再去拉伸專案,同樣的如果主軸是垂直的,專案沒有寫寬度,也會橫向撐滿整個容器
1 .parent {
2 display: flex;
3 align-items: stretch;
4 width: 400px;
5 height: 200px;
6 background-color: blueviolet;
7 }
8
9 .child {
10 width: 50px;
11 height: 50px;
12 background-color: aqua;
13 border: 1px solid black;
14 }
align-items為flex-start時,子專案都沿著交叉軸靠著交叉軸的起點對齊
這里因為只有一行(沒有設定換行屬性,也沒有一行排列不下),整個容器的上端也就是交叉軸的起點, 所以看起來和上面的圖沒什么區別,
align-items為flex-end時,子專案都沿著交叉軸靠著交叉軸的終點對齊
和上圖相反的是,設定了這個屬性,一行的專案就來到了容器底部,因為默認情況下交叉軸從上往下,容器的底部也就是整個交叉軸的終點
align-items為center時,子專案都沿著交叉軸靠著交叉軸居中對齊,往兩邊平均分布
設定了center后,子專案來到居中的位置,這也是在flex布局中最常用的居中技巧之一,如果需要垂直方向的居中,可以直接使用flex布局并且寫上align-items: center,
align-items為baseline時,專案會按照文本的基線對齊
先針對第二個專案設定了一個padding,這樣第二個專案的文字就會被擠下去,所以文字就不會在同一潭訓線上了
1 <style>
2 .parent {
3 display: flex;
4 width: 400px;
5 height: 200px;
6 background-color: blueviolet;
7 }
8
9 .child {
10 width: 50px;
11 height: 50px;
12 background-color: aqua;
13 border: 1px solid black;
14 }
15
16 #two {
17 padding-top: 10px;
18 }
19 </style>
20 <body>
21 <div class="parent">
22 <div class="child">1</div>
23 <div class="child" id="two">2</div>
24 <div class="child">3</div>
25 <div class="child">4</div>
26 <div class="child">5</div>
27 <div class="child">6</div>
28 </div>
29 </body>
如果設定align-items: baseline之后,專案明顯都在同一潭訓線上,
3.6 交叉軸多行對齊align-content屬性
在上文的flex-wrap中,換行顯示的盒子出現了一些空隙,這就和align-content有關系,align-content是CSS中用于控制flex容器中多行專案的對齊方式的屬性,它適用于具有多行內容的flex容器,并決定了這些行在容器中的專案在交叉軸上的對齊方式,
以下是align-content的一些常用的取值:
- flex-start:將多行專案對齊到容器的起始位置,第一行將與容器的頂部對齊,
- flex-end:將多行專案對齊到容器的結束位置,最后一行將與容器的底部對齊,
- center:將多行專案在容器中垂直居中對齊,
- space-between:在容器中平均分布多行專案,使第一行在容器的頂部,最后一行在容器的底部,剩余的行平均分布在中間,
- space-around:在容器中平均分布多行專案,使每行周圍具有相等的空間,包括頂部和底部,
- space-evenly:在容器中平均分布多行專案,使每行之間和周圍都具有相等的空間,
- stretch(默認值):在容器中平均分布多行專案,專案將被拉伸以填充整個容器的高度,
需要注意的是,align-content只在有多行的情況下才會生效,而在只有一行的情況下是不會產生任何效果的,所以以下的示例全部會涉及到flex-wrap換行,
當默認不寫align-content時,align-content的值默認取stretch,也就是會把每一個專案都會拉伸來撐滿整個容器,這里最多2行,所以每個專案的高度都被拉伸到了容器高度/2,
當對子專案設定高度的時候,專案不會被拉伸,但是原來拉伸后的空間會有間距填充
1 .parent{
2 display: flex;
3 flex-wrap: wrap;
4 /* 默認值,也可以不寫 */
5 align-content: stretch;
6 width: 400px;
7 height: 200px;
8 background-color:blueviolet;
9 }
10 .child{
11 width: 100px;
12 background-color: aqua;
13 border: 1px solid black;
14 }
當align-content的值取flex-start時,第一行會靠著交叉軸起點,也就是頂部對齊,不會留有上圖那樣的間距
當align-content的值取flex-end時,最后一行會靠著交叉軸終點,也就是底部對齊,也不會留有上圖那樣的間距
當align-content的值取center時,專案會在交叉軸上居中對齊,向兩邊平均分布,這個與之前的align-items和justify-content相似
當align-content的值取space-between時,專案會在交叉軸上貼著兩端,中間間距相同
當align-content的值取space-around時,每個專案的上下間距相同,和justify-content一樣,因為中間的間距疊加,首尾的間距是中間間距的一半
當align-content的值取space-evenly時,所有交叉軸上的間距相同
4. Flex專案屬性
4.1 改變專案的顯示順序order屬性
order屬性用于控制Flex容器中子元素的排序,默認情況下,Flex容器中的子元素按照它們在HTML源代碼中的順序進行排列,但是使用order屬性,我們可以改變這個順序
每個Flex專案的order屬性默認值是0,你可以為專案設定任意整數值,數值可以是正數、0或者負數,具有較小order值的元素將被優先排列,具有相同order值的元素將按照它們在HTML源代碼中的原始順序排列,
1 .parent{
2 display: flex;
3 flex-wrap: wrap;
4 align-content: flex-start;
5 width: 400px;
6 height: 200px;
7 background-color:blueviolet;
8 }
9 .child{
10 width: 100px;
11 height: 50px;
12 background-color: aqua;
13 border: 1px solid black;
14 }
15 #two{
16 order: -1;
17 }
18 #three{
19 order: -2;
20 }
4.2 子專案擴張flex-grow屬性
flex-grow用于設定或檢索flex容器中的flex子專案的能力,以根據其在flex容器中的空間比例來伸展和占用空間,
flex-grow屬性的默認值為0,表示子專案將不會伸展以填充容器,
flex可以取的值是所有非負數,數值不帶單位,表示當容器有剩余空間的時候,子專案按比例去增大,占滿容器,子專案擴張的演算法如下:比如剩余空間為 x,三個元素的 flex-grow 分別為 a,b,c,設 sum 為 a + b + c,那么三個元素將得到剩余空間分別是 x * a / sum, x * b / sum, x * c / sum
對第三個子專案進行設定flex-grow:1,表示的意思是:有剩余空間的時候,第三個專案會擴張,占一份,因為只有一個元素設定了flex-grow,所以第三專案占滿了所有剩余空間,
此時如果對第三個專案設定flex-grow:2/3/4/5....都不會使他變得更大,因為剩余空間只有那么多,其他的元素也都是flex-grow:0,
對多個專案設定flex-grow時,它們就按照比例來占滿剩余空間,第二個子專案占1份(四分之一),第三個子專案占3份(四分之三)
1 .parent {
2 display: flex;
3 width: 400px;
4 height: 200px;
5 background-color: blueviolet;
6 }
7
8 .child {
9 width: 50px;
10 height: 50px;
11 background-color: aqua;
12 border: 1px solid black;
13 }
14
15 #two {
16 flex-grow: 1;
17 }
18
19 #three {
20 flex-grow: 3;
21 }
前面有說到,flex-grow可以設定所有非負的值,當所有的子專案flex-grow的值之和小于1時,計算擴張的演算法會發生改變,不再只是將所有的剩余空間的按flex-grow的比例分配,而是將剩余空間*sum(三個元素的 flex-grow 分別為 a,b,c設 sum 為 a + b + c)按flex-grow的比例分配,也可以等效地理解為按上面講的演算法x * a / sum, x * b / sum, x * c / sum,當sum<1時,分母直接使用1,
如下圖,第二個子專案獲得剩余空間的20%,第三個子專案獲得剩余空間的60%,剩下的20%仍然空出,
1 .parent {
2 display: flex;
3 width: 400px;
4 height: 200px;
5 background-color: blueviolet;
6 }
7
8 .child {
9 width: 50px;
10 height: 50px;
11 background-color: aqua;
12 border: 1px solid black;
13 }
14
15 #two {
16 flex-grow: 0.2;
17 }
18
19 #three {
20 flex-grow: 0.6;
21 }
簡單案例:之前在開發中遇到一個需求,后端會給前端傳許多一段一段的標簽,每個標簽的寬度都不一樣長,這些標簽要換行排列,每一行的標簽要貼著左右邊緣,中間間距相等(justify-content: space-between),最后一行標簽一般都會數量較少,如果僅僅使用justify-content: space-between而不對最后一行專門處理,最后一行的間距就會特別大,影響最后頁面效果的呈現,
為了解決最后一行標簽數量較少的問題,可以在容器末尾加一個看不見的盒子,讓那個盒子占滿剩余的空間,也就是利用flex-grow: 1
以下用簡單的代碼模擬了一下上述開發場景
1 <style>
2 .parent {
3 display: flex;
4 flex-wrap: wrap;
5 justify-content: space-between;
6 width: 400px;
7 height: 200px;
8 background-color: blueviolet;
9 }
10
11 .child {
12 width: 100px;
13 height: 40px;
14 background-color: aqua;
15 border: 1px solid black;
16 font-size: 18px;
17 }
18
19 .hidden {
20 flex-grow: 1;
21 visibility: hidden;
22 }
23 </style>
24 <body>
25 <div class="parent">
26 <div class="child">1</div>
27 <div class="child" style="width: 120px;">2</div>
28 <div class="child" style="width: 30px;">3</div>
29 <div class="child">4</div>
30 <div class="child" style="width: 150px;">5</div>
31 <div class="child">6</div>
32 <div class="child">7</div>
33 <div class="child">8</div>
34 <div class="child">9</div>
35 <div class="hidden"></div>
36 </div>
37 </body>
4.3 子專案收縮flex-shrink屬性
flex-shrink用于指定專案在容器中縮小的能力,當 flex 容器空間不足時候,單個元素的收縮比例,當父元素的寬度小于子元素寬度之和并且超出了父元素的寬度時,flex-shrink 就會按照一定的比例進行收縮:將子元素寬度之和與父元素寬度的差值按照子元素 flex-shrink 的值分配給各個子元素,每個子元素原本寬度減去按比例分配的值,其剩余值為實際寬度,
flex-shrink的默認值是1,也就是說,當子元素寬度的和超出父容器的時候,所有子專案都等比例的縮小
下圖中所有子專案的flex-shrink都取1,但是子專案的寬度是有不同的,第二個子專案寬度為120px,第三個子專案寬度為150px,其他所有子專案的寬度都是100px,他們寬度的和是100*4+120+150 = 670px,但是父容器寬度只有400px,也就是說超出了270px,此時要等比例縮小,要計算每個盒子要縮小的寬度,演算法是:子專案寬度/(每個子專案的寬度*對應shrink的值)之和 * 超出的寬度,對于寬度為100的子專案要縮小的寬度是 (100*1)/(100*4*1+120*1+150*1)*270 = 40.29px,對于第二個寬度為120px的子專案要縮小的寬度是(120*1)/(100*4*1+120*1+150*1)*270 = 48.36px,對于第三個寬度為150px的子專案要縮小的寬度是(150*1)/(100*4*1+120*1+150*1)*270 = 60.48px
所有盒子在收縮后,最后的寬度=原來寬度-要縮小的寬度
1 .parent {
2 display: flex;
3 width: 400px;
4 height: 200px;
5 background-color: blueviolet;
6 }
7
8 .child {
9 width: 100px;
10 height: 50px;
11 flex-shrink: 1;
12 background-color: aqua;
13 border: 1px solid black;
14 }
15 #two{
16 width: 120px;
17 }
18 #three{
19 width: 150px;
20 }
當flex-shrink為0的時候,該子專案不會收縮
以第三個150px的盒子舉例,讓它的flex-shrink為0,它就不會收縮,其他盒子按比例收縮,寬度為100px的專案flex-shrink為1,要縮小的寬度為 (100*1)/(100*4*1+120*1.5+150*0)*270 = 46.55px, 寬度為120px的專案flex-shrink為1.5,要縮小的寬度為 (120*1.5)/(100*4*1+120*1.5+150*0)*270 = 83.79px
1 .parent {
2 display: flex;
3 width: 400px;
4 height: 200px;
5 background-color: blueviolet;
6 }
7
8 .child {
9 width: 100px;
10 height: 50px;
11 flex-shrink: 1;
12 background-color: aqua;
13 border: 1px solid black;
14 }
15 #two{
16 width: 120px;
17 flex-shrink: 1.5;
18
19 }
20 #three{
21 width: 150px;
22 flex-shrink: 0;
23
24 }
4.4 子專案初始尺寸flex-basis屬性
flex-basis用于設定flex容器中專案的初始大小,它定義了一個專案在主軸上的初始尺寸,即在專案沒有被放大或縮小之前的大小,flex-basis可以接受多種單位值,如像素(px)、百分比(%)、視口寬度(vw)、視口高度(vh)等,
flex-basis常用的值有
- <length>:可以是像素值(px)、百分比(%)等,表示專案的初始尺寸,
- auto(默認值):專案的初始尺寸由其內容決定,如果專案沒有設定尺寸或具有固定的尺寸,則自動計算尺寸,
- content:專案的初始尺寸由專案內容決定,
在Flex布局中,子項設定width是沒有直接效果的,之前所有設定寬度并且生效是因為沒有寫flex-basis屬性,也就是說flex-basis屬性取了默認值auto,當flex-basis取auto的時候,容器的寬度就由子項自身的尺寸(比如width,max-width等)去渲染,
1 .parent {
2 display: flex;
3 width: 400px;
4 height: 200px;
5 background-color: blueviolet;
6 }
7
8 .child {
9 width: 50px;
10 height: 50px;
11 flex-basis: auto;
12 background-color: aqua;
13 border: 1px solid black;
14 }
在同時用長度設定flex-basis和width時,width將無效,根據flex-basis的值決定尺寸
在設定flex-basis為content時,子專案的尺寸根據內容的大小決定
4.5 聯合寫法flex屬性
flex屬性是flex-grow,flex-shrink,flex-basis三個屬性的簡寫,用于控制子專案的縮放行為和初始尺寸,
flex的完整寫法是 flex:<flex-grow> <flex-shrink> <flex-basis>,也就是一共有3個值要去設定,分別按順序對應flex-grow,flex-shrink,flex-basis,而在日常作業中并不會經常寫完整的寫法,而較常用的是flex:1或者50%這種寫法,
flex-grow和flex-shrink可以同時設定,但是對于一個元素,同時只會有其中一者生效,因為flex-grow需要有剩余空間才能進行拉伸分配而flex-shrink需要子元素寬度之和超過父元素(溢位)才會收縮,一個盒子要么空間不足,要么就空間超出,不可能既有剩余空間又寬度之和超出父元素
flex屬性的常用值有
- flex: auto: 此值表示元素可以根據可用空間進行伸縮,可以擴展也可以收縮,
- flex: initial: 此值將 flex-grow、flex-shrink 和 flex-basis 設定為默認值,flex-grow 為 0,flex-shrink 為 1,flex-basis 為 auto,
- flex: none: 此值表示元素不應該伸縮,flex-grow 和 flex-shrink 均為 0,flex-basis 為其本來的大小,
- flex: 數字/百分比/長度
flex:auto代表的是 flex:1 1 auto(flex-grow:1, flex-shrink: 1, flex-basis: auto) ,表示的是根據具體空間來進行擴展或者收縮
flex:initial(默認值)代表的是 flex:0 1 auto(flex-grow:0, flex-shrink: 1, flex-basis: auto) ,表示子專案不會在有剩余空間時候擴張,但是超出時會要收縮,
flex:none 代表的是 flex:0 0 auto(flex-grow:0, flex-shrink: 0, flex-basis: auto),表示子專案不會擴張也不會收縮,保持原有尺寸
在超出父容器的時候,也會繼續保持原有的尺寸
其他值:
如果只寫一個值,類似于flex: 1 這種,分2種情況
- 如果寫的是數字比如,flex: 1,flex: 2,flex: 3這種那設定的是flex-grow的值,其他2個值取默認
- 如果寫的是百分比(flex: 20%)或者是長度(flex: 100px),就是設定的flex-basis屬性,其他2個值取默認
如果只寫兩個值,第一個值對應的是flex-grow,第二個值對應2種情況
- 如果第二個值寫的是數字比如,flex: 1,flex: 2,flex: 3這種那設定的是flex-shrink的值
- 如果寫的是百分比(flex: 20%)或者是長度(flex: 100px),就是設定的flex-basis屬性
如果寫三個值,對應地去設定flex-grow、flex-shrink 和 flex-basis
簡單案例:
場景1:簡單實作一個兩欄布局,左列定寬,右邊自適應
這里用到flex: 1 讓右邊的專案自動根據剩余空間擴張
1 <style>
2 .parent {
3 display: flex;
4 width: 400px;
5 height: 200px;
6 background-color: blueviolet;
7 }
8
9 .child1 {
10 width: 100px;
11 height: 50px;
12 background-color: aqua;
13 border: 1px solid black;
14 }
15 .child2 {
16 height: 50px;
17 background-color: aqua;
18 flex: 1;
19 border: 1px solid black;
20 }
21 </style>
22
23 <body>
24 <div class="parent">
25 <div class="child1">1111</div>
26 <div class="child2">2</div>
27 </div>
28 </body>
場景2:讓多個盒子分行排列,每行要三個盒子,同時寬度自適應
這里要對父容器設定flex-wrap:wrap,對子專案設定,flex:33%來讓它們每行排列3個
1 <style>
2 .parent {
3 display: flex;
4 justify-content: space-between;
5 flex-wrap: wrap;
6 width: 400px;
7 height: 200px;
8 background-color: blueviolet;
9 }
10
11 .child {
12 box-sizing: border-box;
13 flex: 33%;
14 height: 50px;
15 background-color: aqua;
16 border: 1px solid black;
17 }
18 </style>
19
20 <body>
21 <div class="parent">
22 <div class="child">1</div>
23 <div class="child">2</div>
24 <div class="child">3</div>
25 <div class="child">4</div>
26 <div class="child">5</div>
27 <div class="child">6</div>
28 </div>
29 </body>
4.6 子專案單獨對齊align-self屬性
align-self屬性用于調整Flex容器中單個專案(Flex項)的垂直對齊方式,它允許你為單個專案指定不同于其它專案的垂直對齊方式,align-self屬性可以應用于任何Flex項,并覆寫容器級別的垂直對齊設定(通過align-items屬性設定)
常用的值有:
- auto(默認值):繼承自父容器的align-items屬性,
- flex-start:專案與容器的頂部對齊,
- flex-end:專案與容器的底部對齊,
- center:專案在容器的垂直中心對齊,
- baseline:專案與容器的基線對齊,
- stretch:專案被拉伸以填充整個容器的高度,
這些取值都在前面的align-items中介紹過了,這里只用一些案例來演示align-self的效果
針對第二個子專案,設定了align-self: center,第三個子專案設定了align-self: flex-end
這里是單行的align-self效果
1 .parent {
2 display: flex;
3 align-items: flex-start;
4 width: 400px;
5 height: 200px;
6 background-color: blueviolet;
7 }
8
9 .child {
10 box-sizing: border-box;
11 width: 100px;
12 height: 50px;
13 background-color: aqua;
14 border: 1px solid black;
15 }
16
17 #two{
18 align-self: center;
19 }
20 #three{
21 align-self: flex-end;
22 }
如果在父容器中加入換行,效果如下
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/556646.html
標籤:其他
上一篇:提升網站速度與用戶體驗!了解Whirl動態加載庫的最新技術
下一篇:返回列表