如何使用 Flexbox 構建純 CSS 智能佈局
已發表: 2022-03-11靈活框,或簡稱 Flexbox,是 2009 年引入的 CSS 中的一組屬性,用於提供一種新的、卓越的佈局系統。 Flexbox 模塊被標識為第三版 CSS (CSS3) 的一部分。
您可能已經在使用 CSS3 中的許多新屬性,例如box-shadow
、 border-radius
、背景漸變等。 然而,Flexbox 尚未得到應有的廣泛採用。 這可能是因為它多年來遭受的所有重大變化,或者因為它僅在 Internet Explorer 10 中得到部分支持,或者只是因為 Flexbox 是一個完整的生態系統,而以前的範例主要基於單一的、隨時可用的去屬性。
它非常強大,並提供了廣泛的選項來實現以前只能夢想的佈局。
本文將引導您了解 Flexbox 的基礎知識,以及如何使用它來實現一些非常酷的佈局,否則這些佈局需要復雜的 CSS hack 甚至 JavaScript。
為什麼要使用 Flexbox?
默認情況下,HTML 塊級元素是堆疊的,所以如果你想將它們排成一行,你需要依賴像float
這樣的 CSS 屬性,或者使用 table-ish 或 inline-block 設置來操作display
屬性。
如果您選擇使用float
(左或右),您必須在某個時候清除包裝以將其推送到最後一個浮動元素,否則它們將溢出後面的任何內容。 但是,使用浮動,您只能水平組織元素。
或者,或者另外,您可以操縱display
屬性以嘗試實現您想要的佈局! 但這通常讓人覺得充其量是雜亂無章的,更不用說乏味了,而且通常會導致相當脆弱的佈局,不一定會在瀏覽器中一致地呈現。 如果您針對不同尺寸的多個設備,這種方法尤其無效——如今幾乎總是如此。
進入彈性盒!
通過將簡單規則應用於父元素,您可以輕鬆控制其所有子元素的佈局行為。
使用 Flexbox,您可以:
- 反轉 Flexbox 父級中元素的順序。
- 將子元素包裝在列中(列數可能因子元素和父元素的高度而異)。
- 指定視口大小更改時元素增長或縮小的速率。
- 控制元素是否可收縮,而不管指定的寬度單位類型(相對或絕對)。
- 使用 CSS 更改元素的順序(將其與媒體查詢結合使用,您會發現流程中的無限可能)。
- 生成元素的複雜分佈,使其與周圍的空間或之間的空間等距。
- 生成流動不同的“叛徒”元素(每個人都在左邊,但在右邊,頂部/底部......這是你的電話)。
- 而且,最重要的是,永遠避免使用 clear-fix hack!
我知道 Flexbox 一開始可能很難。 我認為學習十個不相關的 CSS 屬性比學習五個相互依賴的 CSS 屬性更容易。 但是,憑藉您當前的 CSS 技能,以及本文的一些幫助,您將進入一個新的 CSS 世界。
Flexbox 基礎知識
展示
display
是 CSS 中最基本的屬性之一,在 Flexbox 的上下文中非常重要,因為它用於定義 flex 包裝器。
有兩種可能的 flex 包裝器值: flex
和inline-flex
。
兩者的區別在於display: flex
包裝器的作用類似於塊元素,而display: inline-flex
包裝器的作用類似於 inline-block。 此外,如果沒有足夠的空間容納子元素,則inline-flex
元素會增長。 但除了這些差異之外,兩者的行為是相同的。
試試下面的示例代碼,當 inline-flex 處於活動狀態時減小視口寬度,然後……滾動。
請參閱 CodePen 上 DD (@Diegue) 的 Pen Flexbox @Toptal - Parent - `display` 屬性。
.wrapper { display: flex || inline-flex; }
彎曲方向
現在您已經看到了第一個示例,您可以推斷默認行為是簡單地創建一行元素。 但還有更多:
- 行(默認):從左到右排列元素(但如果設置了 RTL,它將向後排列)。
- row-reverse:反轉行配置中元素的順序
- column:從上到下排列元素
- column-reverse:反轉列配置中元素的順序
提示:
column
和column-reverse
值可用於交換軸,因此影響水平軸的屬性將影響垂直軸。
請參閱 CodePen 上 DD (@Diegue) 的 Pen Flexbox @Toptal - Parent - `flex-direction` 屬性。
.wrapper { flex-direction: row || row-reverse || column || column-reverse; }
彈性包裝
如果您檢查第一個代碼示例,您會發現默認情況下子元素不會在 flex 包裝器中堆疊。 這就是flex-wrap
發揮作用的地方:
- nowrap (默認):防止 flex 容器中的項目包裝
- wrap:根據需要將項目包裝成多行(或列,取決於
flex-direction
) - wrap-reverse:就像
wrap
一樣,但行(或列)的數量隨著項目的包裝而以相反的方向增長
請參閱 DD (@Diegue) 在 CodePen 上的 Pen Flexbox @Toptal - Parent - `flex-wrap` 屬性。
.wrapper { flex-wrap: nowrap || wrap || wrap-reverse; }
彈性流
您可以將flex-direction
和flex-wrap
屬性組合成一個屬性: flex-flow
。
.wrapper { flex-flow: {flex-direction} {flex-wrap}; }
證明內容
該屬性用於控制子元素的水平對齊方式:
- flex-start (默認):元素左對齊(類似於帶有
text-align: left
內聯元素) - flex-end:元素向右對齊(類似於帶有
text-align: right
內聯元素) - center:元素居中(類似於帶有
text-align: center
內聯元素) - space-around (魔法開始的地方):每個元素將在每個項目周圍使用相同數量的空間進行渲染。 請注意,兩個順序子元素之間的空間將是最外層元素和包裝器側面之間空間的兩倍。
- space-between:就像
space-around
一樣,除了元素將被相同的距離分開並且包裝器的任一邊緣附近都沒有空間。
注意:記住
flex-direction
,當設置為column
或column-reverse
時,交換軸。 如果設置其中之一,justify-content
將影響垂直對齊,而不是水平對齊。
請參閱 CodePen 上 DD (@Diegue) 的 Pen Flexbox @Toptal - Parent - `justify-content` 屬性。
對齊項目
此屬性類似於justify-content
,但其效果的上下文是行而不是包裝器本身:
- flex-start:元素垂直對齊到包裝器的頂部。
- flex-end:元素垂直對齊到包裝器的底部。
- center:元素在包裝器中垂直居中(最後,實現這一點的安全做法)。
- 拉伸(默認):強制元素佔據包裝器的全高(應用於行時)和全寬(應用於列時)。
- 基線:將元素垂直對齊到它們的實際基線。
請參閱 CodePen 上 DD (@Diegue) 的 Pen Flexbox @Toptal - Parent - `align-items` 屬性。
對齊內容
此屬性類似於justify-content
和align-items
但它在垂直軸上工作,並且上下文是整個包裝器(而不是像前面的示例那樣的行)。 要查看其效果,您需要不止一行:
- flex-start:行與頂部垂直對齊(即從包裝器頂部堆疊)。
- flex-end:行與底部垂直對齊(即從包裝器底部堆疊)。
- center:行在包裝器中垂直居中。
- 拉伸(默認):通常,此屬性拉伸元素以利用包裝器的整個垂直高度。 但是,如果您設置了元素的某個特定高度,則該高度將被尊重,並且剩餘的垂直空間(在該行中,該元素下方)將為空。
- space-around:每一行都將在垂直方向(即,自身下方和上方)周圍以相同數量的空間進行渲染。 請注意,兩行之間的空間因此將是頂部和底部行與包裝邊緣之間的空間的兩倍。
- space-between :就像
space-around
一樣,除了元素將被相同的距離分開,並且包裝器的頂部和底部邊緣沒有空間。
請參閱 CodePen 上 DD (@Diegue) 的 Pen Flexbox @Toptal - Parent - `align-content` 屬性。
彈性成長
此屬性設置元素應使用的可用空間的相對比例。 該值應該是一個整數,其中 0 是默認值。
假設您在同一個 flex 包裝器中有兩個不同的元素。 如果兩者的flex-grow
值都為 1,它們將平均增長以共享可用空間。 但是,如果一個flex-grow
值為 1,另一個flex-grow
值為 2,如下例所示,則flex-grow
值為 2 的這個值將增長為第一個的兩倍。
.wrapper .elements { flex-grow: 1; /* Default 0 */ } .wrapper .elements:first-child { flex-grow: 2; }
請參閱 CodePen 上 DD (@Diegue) 的 Pen Flexbox @Toptal - Children - `flex-grow` 屬性。
彈性收縮
與flex-grow
類似,此屬性使用整數值設置元素是否“可收縮”。 與flex-grow
類似, flex-shrink
指定彈性項目的收縮係數。

請參閱 CodePen 上 DD (@Diegue) 的 Pen Flexbox @Toptal - Children - `flex-shrink` 屬性。
.wrapper .element { flex-shrink: 1; /* Default 0 */ }
彈性基礎
此屬性用於在分配可用空間並相應調整元素之前定義元素的初始大小。
提示:
flex-basis
不支持calc()
和box-sizing: border-box
在每個瀏覽器中,所以如果你需要使用其中之一,我建議使用width
(注意你還需要設置flex-basis: auto;
)。
請參閱 DD (@Diegue) 在 CodePen 上的 Pen Flexbox @Toptal - Children - `flex-basis` 屬性。
.wrapper .element { flex-basis: size || auto; /* Default auto */ }
柔性
您可以將flex-grow
、 flex-shrink
和flex-basis
屬性組合成一個屬性: flex
,如下所示:
.wrapper { flex: {flex-grow} {flex-shrink} {flex-basis}; }
提示:如果您打算使用
flex
,請確保定義每個值(即使您想使用默認值),因為某些瀏覽器可能無法識別它們(常見錯誤與未定義flex-grow
值有關)。
對齊自我
此屬性與align-items
類似,但效果單獨應用於每個元素。 可能的值是:
- flex-start:將元素垂直對齊到包裝器的頂部。
- flex-end:將元素垂直對齊到包裝器的底部。
- center:垂直居中包裝內的元素(最後是實現此目的的簡單方法!)。
- 拉伸(默認):拉伸元素以佔據包裝器的整個高度(應用於行時)或包裝器的整個寬度(應用於列時)。
- 基線:根據元素的實際基線對齊元素。
請參閱 CodePen 上 DD (@Diegue) 的 Pen Flexbox @Toptal - Children - `align-self` 屬性。
命令
Flexbox 中包含的最好的東西之一是能夠重新排序元素(使用order
屬性),而無需修改 DOM 或使用 JavaScript。 order
屬性的工作方式非常簡單。 就像z-index
控制項目的渲染順序一樣, order
控制元素在包裝器中的定位順序; 也就是說,具有較低order
值的元素(順便說一下,它甚至可以是負數)位於具有較高order
值的元素之前。
請參閱 CodePen 上 DD (@Diegue) 的 Pen Flexbox @Toptal - Children - `order` 屬性。
.wrapper .elements { order: 1; /* this one will be positioned second */ } .wrapper .elements:last-child { order: -1; /* this one will be positioned first */ }
將它們放在一起:Flexbox 的示例使用
在設計佈局時,Flexbox 釋放了無限可能。 下面,您可以找到一些 Flexbox 屬性的示例用法。
垂直對齊組件
使用 Flexbox,您可以垂直對齊任何東西,包括一次多個元素。 如果沒有 Flexbox,您需要使用定位或表格技術,這需要我們創建一個子元素來包含多個元素。 但是使用 Flexbox,您可以拋開這些繁瑣而脆弱的技術,只需在包裝器中定義一些屬性即可,無論容器內的內容更改多少次或更改的類型如何!
.wrapper { display: flex; /* always present for Flexbox practices */ flex-direction: column; /* elements stack */ justify-content: center; /* now that flex-direction is a column, the axis are swapped so this centers the content vertically */ min-height: 100vh /* make sure wrapper is taller enough */ }
請參閱 Pen Flexbox @Toptal - 我們可以提供的實際用途 - CodePen 上的 DD (@Diegue) 垂直對齊。
半/半佈局
“半/半”佈局是具有兩列的全高佈局,每列的內容垂直居中。 它通常在“首屏”實現(即,在頁面加載後用戶向下滾動之前)。
使用更傳統的技術,您可以使用浮動元素(每個寬度為 50%)創建此佈局,將浮動清除到包裝器中(“clearfix” :before
和:after
, overflow: hidden
或帶有clear: both;
的古怪<div>
: clear: both;
最後)。 然而,工作量很大,而且結果不如 Flexbox 提供的穩定。
在下面的代碼片段中,您將看到設置佈局是多麼容易,以及孩子如何成為 Flexbox 包裝器,因為所有內容也都是垂直對齊的。
外包裝:
.wrapper { display: flex; flex-direction: column; /* only for mobile */ }
內包裝:
.inner-wrapper { flex-grow: 1; /* Allow the element to grow if there is available space */ flex-shrink: 1; /* Elements shrink at the same rate */ flex-basis: 100%; /* Elements will cover the same amount, if is possible the 100% of the width */ }
請參閱 Pen Flexbox @Toptal - 我們可以提供的實際用途 - CodePen 上 DD (@Diegue) 的 Half-bleed 部分。
全角導航欄按鈕
無論元素數量如何,全寬導航欄都會在同一行導航欄項目中平均分配空間。
在下面的示例中,也有一些沒有此行為的標誌性按鈕,表明您可以以任何您想要的方式將兩者結合起來。 如果沒有 Flexbox,實現這些佈局將需要 JavaScript 代碼來計算可用空間,然後根據哪些按鈕跨越和哪些不跨越以編程方式分配它。
Flexbox 讓這變得簡單多了。
包裝器屬性:
.navbar { display: flex; }
跨越子屬性:
.navbar-item { flex-grow: 1; /* They will grow */ }
非跨越子屬性:
.navbar-other { flex-grow: 0; // They won't grow }
請參閱 Pen Flexbox @Toptal - 我們可以提供的實際用途 - CodePen 上的 DD (@Diegue) 的全出血按鈕導航欄。
簡介
你有多少次在不同的項目中實現了一組帶有圖標和文本的信息框?
這種元素的分佈在數字營銷中最有用,但在軟件開發中還有其他用途。 借助 Flexbox 的強大功能,您可以設置一種網格並對齊元素,無論有多少元素。
包裝器屬性:
.wrapper { display: flex; flex-wrap: wrap; }
子屬性:
.blurb { flex-grow: 0; /* elements don't grow */ flex-shrink: 0; /* elements don't shrink in a flexible way */ flex-basis: auto; /* the width of the elements will be set by proportions in `width` due to flex-basis not support workaround */ width: calc(33.33% - 60px); /* calculate proportional width without space taken by padding (workaround for IE 11) */ }
對於平板電腦和移動設備視口,寬度在 50% 和 100% 之間變化。
請參閱 Pen Flexbox @Toptal - 我們可以提供的真實用途 - CodePen 上的 DD (@Diegue) 的 Blurbs。
增強跨瀏覽器兼容性
Flexbox 的語法在不同的瀏覽器版本中發生了多次變化。 當使用 Flexbox 實現佈局並嘗試支持較舊的 Web 瀏覽器,尤其是較舊版本的 Internet Explorer 時,這可能是一個問題。
幸運的是,Flexbugs 中列出了許多讓您的代碼在最廣泛的 Web 瀏覽器中運行的技術和變通方法,這是一個很好的資源。 如果您遵循該站點上的信息,您將在不同的 Web 瀏覽器中獲得更好、一致的結果。
前綴任務在這方面特別有用。 要自動為 CSS 規則添加前綴,您可以選擇以下工具之一:
紅寶石:
- Autoprefixer Rails
- 中間人自動前綴
節點.js:
- PostCSS 自動前綴
- Grunt 自動前綴
- Gulp 自動前綴
開始構建智能佈局
Flexbox 是一個很好的工具,可以加快、完善和擴展我們的工作。 限制僅在開發人員的想像中。
如果你需要一些視覺幫助來規劃你的下一個佈局,你可以試試這個整潔的遊樂場:
請參閱 CodePen 上 DD (@Diegue) 的 Pen Flexbox @Toptal - Flexbox 遊樂場。
在新窗口中打開它。
隨著大多數用戶越來越多地採用現代 Web 瀏覽器,使用 Flexbox 可以讓您輕鬆創建令人驚嘆的佈局,而無需深入研究凌亂的 JavaScript 代碼或製作笨拙的 CSS。