前面一篇文章「一文帶你弄懂 CSS 布局知識(shí)」里,我整體介紹了 CSS 的布局知識(shí),其中說(shuō)到 float 布局是 CSS 不斷完善的副產(chǎn)物。而在 2023 年的今天,flex 這種布局方式才是未來(lái)!那么今天我們就來(lái)學(xué)習(xí)下 flex 彈性布局。
在經(jīng)過(guò)了長(zhǎng)達(dá) 10 年的發(fā)展之后,CSS3 才終于迎來(lái)了一個(gè)簡(jiǎn)單好用的布局屬性 —— flex。Flex 布局又稱(chēng)彈性布局,它使用 flexbox 屬性使得容器有了彈性,可以自動(dòng)適配各種設(shè)備的不同寬度,而不必依賴(lài)于傳統(tǒng)的塊狀布局和浮動(dòng)定位。
舉個(gè)很簡(jiǎn)單地例子,如果我們想要實(shí)現(xiàn)一個(gè)很簡(jiǎn)單左側(cè)定寬,右側(cè)自適應(yīng)的導(dǎo)航布局,如下圖所示。
-w1239
在沒(méi)有 flex 之前,我們的代碼是這么寫(xiě)的。
<div><h1>4.1 兩欄布局 - 左側(cè)定寬、右側(cè)自適應(yīng) - float</h1><div class="container"> <div class="left41"></div> <div class="right41"></div></div></div>
/** 4.1 兩欄布局 - 左側(cè)定寬、右側(cè)自適應(yīng) - float **/.left41 { float: left; width: 300px; height: 500px; background-color: pink;}.right41 { width: 100%; height: 500px; background-color: aquamarine;}
這種方式不好的地方在于,我們還需要去理解 float 這個(gè)概念。一旦需要理解 float 這個(gè)概念,我們就會(huì)拖出一大堆概念,例如文檔流、盒子模型、display 等屬性(雖然這些東西確實(shí)應(yīng)該學(xué))。但對(duì)于 flex 來(lái)說(shuō),它就很簡(jiǎn)單,只需要設(shè)置一個(gè)伸縮系數(shù)即可,如下代碼所示。
<div><h1>4.2 兩欄布局 - 左側(cè)定寬、右側(cè)自適應(yīng) - flex</h1><div class="container42"> <div class="left42"></div> <div class="right42"></div></div></div>
.container42 { display: flex;}.left42 { width: 300px; height: 500px; background-color: pink;}.right42 { flex: 1; width: 100%; height: 500px; background-color: aquamarine;}
上面的代碼里,我們只需要將父級(jí)容器設(shè)置為 flex 展示形式(display: flex),隨后在需要自動(dòng)伸縮的容器里設(shè)置屬性即可。上面代碼中的 flex: 1 表示其占據(jù)所有當(dāng)行所剩的空間。通過(guò)這樣的方式,我們非常方便地實(shí)現(xiàn)了彈性布局。
當(dāng)然,上面只是一個(gè)最簡(jiǎn)單的例子,甚至還不是很能體現(xiàn)出 flex 的價(jià)值。flex 除了在響應(yīng)式布局方面非常方便之外,它在對(duì)齊等方面更加方便,能夠極大地降低學(xué)習(xí)成本、提高工作效率。
對(duì)于 Flex 布局來(lái)說(shuō),其有幾個(gè)核心概念,分別是:主軸與交叉軸、起始線和終止線、Flex 容器與 Flex 容器項(xiàng)。
在 Flex 布局中有一個(gè)名為 flex-direction 的屬性,可以取 4 個(gè)值,分別是:
如果你選擇了 row 或者 row-reverse,那么主軸(Main Axis)就是橫向的 X 軸,交叉軸(Cross Axis)就是豎向的 Y 軸,如下圖所示。
主軸是橫向的X軸,交叉軸是豎向的Y軸
如果你選擇了 column 或者 column-reverse,那么主軸(Main Axis)就變成是豎向的 Y 軸,交叉軸(Cross Axis)就是橫向的 X 軸,如下圖所示。
主軸是豎向的Y軸,交叉軸是橫向的X軸
過(guò)去,CSS 的書(shū)寫(xiě)模式主要被認(rèn)為是水平的,從左到右的。但現(xiàn)代的布局方式涵蓋了書(shū)寫(xiě)模式的范圍,所以我們不再假設(shè)一行文字是從文檔的左上角開(kāi)始向右書(shū)寫(xiě)的。
對(duì)于不同的語(yǔ)言來(lái)說(shuō),其書(shū)寫(xiě)方向不同,例如英文是從左到右,但阿拉伯文則是從右到左。那么對(duì)于這兩種語(yǔ)言來(lái)說(shuō),其xx會(huì)有所不同 TODO。舉個(gè)簡(jiǎn)單的例子,如果 flex-direction 是 row ,并且我是在書(shū)寫(xiě)英文。由于英文是從左到右書(shū)寫(xiě)的,那么主軸的起始線是左邊,終止線是右邊,如下圖所示。
-w557
但如果我在書(shū)寫(xiě)阿拉伯文,由于阿拉伯文是從右到左的,那么主軸的起始線是右邊,終止線是左邊,如下圖所示。
-w541
在 Flex 布局中,起始線和終止線決定了 Flex 容器中的 Flex 元素從哪個(gè)方向開(kāi)始排列。 舉個(gè)簡(jiǎn)單例子,如果我們通過(guò) direction: ltr 設(shè)置了文字書(shū)寫(xiě)方向是從左到右,那么起始線就是左邊,終止線就是右邊。此時(shí),如果我們?cè)O(shè)置的 flex-direction 值是 row,那么 Flex 元素將會(huì)從左到右開(kāi)始排列。但如果我們?cè)O(shè)置的 flex-direction 值是 row-reverse,那么 Flex 元素將會(huì)從右到左開(kāi)始排列。
在上面的例子中,交叉軸的起始線是 flex 容器的頂部,終止線是底部,因?yàn)閮煞N語(yǔ)言都是水平書(shū)寫(xiě)模式。但如果有一種語(yǔ)言,它的書(shū)寫(xiě)形式是從底部到頂部,那么當(dāng)設(shè)置 flex-direction為 column 或 column-reverse 時(shí),也會(huì)有類(lèi)似的變化。
我們把一個(gè)容器的 display 屬性值改為 flex 或者 inline-flex 之后,該容器就變成了 Flex 容器,而容器中的直系子元素就會(huì)變?yōu)?flex 元素。如下代碼所示,parent 元素就是 Flex 容器,son 元素就是 Flex 元素。
<style>#parent { display: flex;}</style><div id="parent"> <div id="son"></div></div>
對(duì)于 Flex 來(lái)說(shuō),它有非常多的用法,但核心屬性卻相對(duì)較少。這里我只簡(jiǎn)單介紹幾個(gè)核心屬性,如果你想了解更多 Flex 的屬性,可以去 Mozilla 官網(wǎng)查詢(xún),這里給個(gè)傳送門(mén):flex 布局的基本概念 - CSS:層疊樣式表 | MDN。
對(duì)于 Flex 布局來(lái)說(shuō),其核心屬性有如下幾個(gè):
如上文所介紹過(guò)的,flex-direction 定義了主軸的方向,可以取 4 個(gè)值,分別是:
一旦主軸確定了,交叉軸也確定了。主軸和交叉軸與后續(xù)的對(duì)齊屬性有關(guān),因此弄懂它們非常重要!舉個(gè)很簡(jiǎn)單的例子,如下的代碼將展示下圖的展示效果。
.box { display: flex; flex-direction: row-reverse;}<div class="box"> <div>One</div> <div>Two</div> <div>Three</div></div>
-w538
如果你將 flex-direction 改成 column-reverse,那么將會(huì)變成如下的效果,如下圖所示。
-w541
前面說(shuō)到 Flex 布局可以很方便地進(jìn)行響應(yīng)式布局,其實(shí)就是通過(guò) flex 屬性來(lái)實(shí)現(xiàn)的。flex 屬性其實(shí)是 flex-grow、flex-shrink、flex-basis 這三個(gè)參數(shù)的縮寫(xiě)形式,如下代碼所示。
flex-grow: 1;flex-shrink: 1;flex-basis: 200px;/* 上面的設(shè)置等價(jià)于下面 flex 屬性的設(shè)置 */flex: 1 1 200px;
在考慮這幾個(gè)屬性的作用之前,需要先了解一下 可用空間 available space 這個(gè)概念。這幾個(gè) flex 屬性的作用其實(shí)就是改變了 flex 容器中的可用空間的行為。
假設(shè)在 1 個(gè) 500px 的容器中,我們有 3 個(gè) 100px 寬的元素,那么這 3 個(gè)元素需要占 300px 的寬,剩下 200px 的可用空間。在默認(rèn)情況下,flexbox 的行為會(huì)把這 200px 的空間留在最后一個(gè)元素的后面。
-w537
如果期望這些元素能自動(dòng)地?cái)U(kuò)展去填充滿剩下的空間,那么我們需要去控制可用空間在這幾個(gè)元素間如何分配,這就是元素上的那些 flex 屬性要做的事。
flex-basis 屬性用于設(shè)置 Flex 元素的大小,其默認(rèn)值是 auto。此時(shí)瀏覽器會(huì)檢查元素是否有確定的尺寸,如果有確定的尺寸則用該尺寸作為 Flex 元素的尺寸,否則就采用元素內(nèi)容的尺寸。
flex-grow 若被賦值為一個(gè)正整數(shù),flex 元素會(huì)以 flex-basis 為基礎(chǔ),沿主軸方向增長(zhǎng)尺寸。這會(huì)使該元素延展,并占據(jù)此方向軸上的可用空間(available space)。如果有其他元素也被允許延展,那么他們會(huì)各自占據(jù)可用空間的一部分。
舉個(gè)例子,上面的例子中有 a、b、c 個(gè) Flex 元素。如果我們給上例中的所有元素設(shè)定 flex-grow 值為 1,容器中的可用空間會(huì)被這些元素平分。它們會(huì)延展以填滿容器主軸方向上的空間。
但很多時(shí)候,我們可能都需要按照比例來(lái)劃分剩余的空間。此時(shí)如果第一個(gè)元素 flex-grow 值為 2,其他元素值為 1,則第一個(gè)元素將占有 2/4(上例中,即為 200px 中的 100px), 另外兩個(gè)元素各占有 1/4(各 50px)。
flex-grow 屬性是處理 flex 元素在主軸上增加空間的問(wèn)題,相反 flex-shrink 屬性是處理 flex 元素收縮的問(wèn)題。如果我們的容器中沒(méi)有足夠排列 flex 元素的空間,那么可以把 flex 元素 flex-shrink 屬性設(shè)置為正整數(shù),以此來(lái)縮小它所占空間到 flex-basis 以下。
與flex-grow屬性一樣,可以賦予不同的值來(lái)控制 flex 元素收縮的程度 —— 給flex-shrink屬性賦予更大的數(shù)值可以比賦予小數(shù)值的同級(jí)元素收縮程度更大。
justify-content 屬性用來(lái)使元素在主軸方向上對(duì)齊,它的初始值是 flex-start,即元素從容器的起始線排列。justify-content 屬性有如下 5 個(gè)不同的值:
各個(gè)不同的對(duì)齊方式的效果如下圖所示。
flex-start:
-w454
flex-end:
-w444
center:
-w449
space-around:
-w442
space-between:
-w453
align-items 屬性可以使元素在交叉軸方向?qū)R,它的初始值是 stretch,即拉伸到最高元素的高度。align-items 屬性有如下 5 個(gè)不同的值:
各個(gè)不同的對(duì)齊方式的效果如下圖所示。
stretch:
-w448
flex-start:
-w439
flex-end:
-w438
center:
-w444
要注意的事,無(wú)論 align-items 還是 justify-content,它們都是以主軸或者交叉軸為參考的,而不是橫向和豎向?yàn)閰⒖嫉?,明白這點(diǎn)很重要。
由于所有 CSS 屬性都會(huì)有一個(gè)初始值,所以當(dāng)沒(méi)有設(shè)置任何默認(rèn)值時(shí),flex 容器中的所有 flex 元素都會(huì)有下列行為:
弄清楚 Flex 元素的默認(rèn)值有利于我們更好地進(jìn)行布局排版。
看了那么多的 Flex 布局知識(shí)點(diǎn),總感覺(jué)干巴巴的,是時(shí)候來(lái)看看別人在項(xiàng)目中是怎么用的了。
-w1290
上面是我在 CodePen 找到的一個(gè)案例,這樣的一個(gè)布局就是用 Flex 布局來(lái)實(shí)現(xiàn)的。通過(guò)簡(jiǎn)單的分析,其實(shí)我們可以拆解出其 Flex 布局方法,大致如下圖所示。
-w1297
首先整體分為兩大部分,即導(dǎo)航欄和內(nèi)容區(qū)域,這部分的主軸縱向排列的(flex-direction: column),如上圖紅框部分。隨后在內(nèi)容區(qū)域,又將其分成了左邊的導(dǎo)航欄和右邊的內(nèi)容區(qū)域,此時(shí)這塊內(nèi)容是橫向排列的(flex-direction: row),如下上圖藍(lán)框部分。
剩下的內(nèi)容布局也大致類(lèi)似,其實(shí)就是無(wú)限套娃下去。由于偏于原因,這里就不繼續(xù)深入拆解了,大致的布局思路已經(jīng)說(shuō)得很清楚了。
有了 Flex 布局之后,貌似布局也變得非常簡(jiǎn)單了。但紙上得來(lái)終覺(jué)淺,還是得自己實(shí)際動(dòng)手練練才知道容易不容易,不然就變成紙上談兵了!
看到這里,關(guān)于 Flex 布局的核心點(diǎn)就介紹得差不多了。掌握好這幾個(gè)核心的知識(shí)點(diǎn),開(kāi)始去實(shí)踐練習(xí)基本上沒(méi)有什么太大的問(wèn)題了。剩下的一些比較小眾的屬性,等用到的時(shí)候再去查查看就足夠了。
接下來(lái)更多的時(shí)間,就是找多幾個(gè)實(shí)戰(zhàn)案例實(shí)踐,唯有實(shí)踐才能鞏固所學(xué)知識(shí)點(diǎn)。后面有機(jī)會(huì),我將分享我在 Flex 布局方面的項(xiàng)目實(shí)踐。
本文鏈接:http://www.www897cc.com/showinfo-26-15181-0.html別再用 float 布局了,flex 才是未來(lái)!
聲明:本網(wǎng)頁(yè)內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問(wèn)題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。郵件:2376512515@qq.com