詳解flex布局的元素如何分配容器的剩余空間
文章主要介紹了詳解flex布局的元素如何分配容器的剩余空間,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習...
文章主要介紹了詳解flex布局的元素如何分配容器的剩余空間,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
自從開始開學習 CSS 布局,想要比較靈活的把父元素的空間分配給各個子元一直是各個前端程序員的夢想。
在 flex 之前,如果不是專門去搜索相關的解決方案,一般人幾乎想不出非常靈活的三(多)欄等高布局方案,而即使看了解決方案,很多人也會大呼奇技淫巧。
不得不感慨在 flex 之前 CSS 的布局功能之弱:基本只能使用一些并非為布局而設計的屬性來實現想要的布局——float、inline-block、position、甚至是 table 等。而使用這些屬性來實現各種布局效果,往往又會遇到相當多另外的坑:比如浮動的閉合、inline-block 的垂直對齊、position 的定位原點以及 table 的不夠靈活等。
直到出現了 flex
flex 可以說是一次性解決了前端布局的所有的問題(當然,并沒有完全解決,要不然也不會有 grid layout 了),以前很難實現的布局效果在 flex 下簡直不能更簡單,以至于一些其它平臺也開始吸納 flex 的布局思想,也有些開源項目把 flex 的布局方式移植到其它平臺。
中文社區也有不少寫 flex 的文章,比如 ruanyifeng。然而個人覺得不少寫 flex 的文章都有個通病,就是一上來就整一堆 flex 相關的術語,比如 flex container,flex item,main axis(主軸),cors axis(交叉軸),不禁讓人望而生畏,都還沒搞清楚怎么回事,就來一堆術語。
然而這還不是最大的問題,最大的問題是很多文章并沒有把 flex 布局的詳細計算方式講清楚,尤其是連 ruanyifeng 的文章也沒把這事說清楚,但是在 Google 搜索 flex 相關的文章,他的文章卻會出現在第一頁。因為我覺得他寫的并不好,所以就不貼地址了,想看的同學可以自己搜一下,就在第一頁。
即使是 MDN 以及《The Book Of CSS3》里也沒把 flex-grow 和 flex-shrink 的計算方式說清楚。
所以我決定寫這一篇文章,把 flex-grow 與 flex-shrink 的詳細計算方式講清楚。
flex 如何解決傳統常見布局問題
在傳統布局中最常見也是急需的當然就是在從左往右把父元素的空間分配給子元素以實現多欄布局了:按比例也好,定寬也好,更靈活的定寬加占用剩余空間也好。
那我們就從使用 flex 如何實現三欄布局開始吧。
想要實現三欄等高布局,且兩邊的側欄寬度固定而中間一欄占用剩余的空間,如下代碼就足夠了:
<style>
section {display: flex;}
.left-side,
.right-side {width: 200px;}
.content {flex-grow: 1;}
</style>
<section>
<div class="left-side"></div>
<div class="content"></div>
<div class="right-side"></div>
</section>
其中 section 元素的寬度將會像 block 元素一樣盡量的寬,對外面的元素來說,它的行為很像一個 block 塊。三個元素會從左往右占據父元素的空間(這很顯然)。左右側邊欄的寬度都是 200px,中間 .content 元素的寬度將會占據 section 元素的剩余寬度。
另外,section 的高度會自動被最高的一個子元素撐開,同時其它子元素的高度也會被拉到跟 section 元素一樣高,而如果給 section 元素設置了高度,而所有子元素的高度設置為 auto ,所有的子元素也都會自動跟父元素一樣高,這簡直就是在傳統布局中做夢都想要的功能!
總之,在高度方面,flex 的表現是相當符合直覺的。
另外,如果不給 flex 子元素設置寬度和 flex-grow,它會盡量的窄。
flex-grow 的計算方式
上面 demo 中最值得注意的是 .content 元素的 flex-grow 屬性,設置為 1 它就可以占滿水平剩余空間。這也是本文的重點:講清 flex-grow 與 flex-shrink 屬性的詳細計算方式。
flex-grow 屬性決定了父元素在空間分配方向上還有剩余空間時,如何分配這些剩余空間。其值為一個權重(也稱擴張因子),默認為 0(純數值,無單位),剩余空間將會按照這個權重來分配。
比如剩余空間為 x,三個元素的 flex-grow 分別為 a,b,c。設 sum 為 a + b + c。那么三個元素將得到剩余空間分別是 x a / sum, x b / sum, x * c / sum,是為權重也。
舉個例子:
父元素寬度 500px,三個子元素的 width 分別為 100px,150px,100px。
于是剩余空間為 150px
三個元素的 flex-grow 分別是 1,2,3,于是 sum 為 6
則三個元素所得到的多余空間分別是:
150 * 1 / 6 = 25px
150 * 2 / 6 = 50px
150 * 3 / 6 = 75px
三個元素最終的寬度分別為 125px,200px,175px。
100px + 25px = 125px
150px + 50px = 200px
100px + 75px = 175px
可以打開這個 demo(下文中所有的 demo 都在這個頁面) 然后用開發工具查看一下。注意不要用截圖工具量,可能量不準,因為高分屏和放大等諸多因素都會影響測量結果。
然而!不止這些,還有一種情況:
當所有元素的 flex-grow 之和小于 1 的時候(注意是 1,也就是說每個元素的 flex-grow 都是一個小數如 0.2 這樣的),上面式子中的 sum 將會使用 1 來參與計算,而不論它們的和是多少。也就是說,當所有的元素的 flex-grow 之和小于 1 的時候,剩余空間不會全部分配給各個元素。
實際上用來分配的空間是 sum(flex-grow) / 1 * 剩余空間,這些用來分配的空間依然是按 flex-grow 的比例來分配。
還是上面一個例子,但是三個元素的 flex-grow 分別是 0.1,0.2,0.3,那么計算公式將變成下面這樣:
150 * 0.1 / 1 = 15px
150 * 0.2 / 1 = 30px
150 * 0.3 / 1 = 45px
150px - 15px - 30px - 45px = 60px,即還有 60px 沒有分配給任何子元素。
三個元素的最終寬度分別為:
100px + 15px = 115px
150px + 30px = 180px
100px + 45px = 145px
如上所述即是 flex-grow 的計算方式。
另外,flex-grow 還會受到 max-width 的影響。如果最終 grow 后的結果大于 max-width 指定的值,max-width 的值將會優先使用。同樣會導致父元素有部分剩余空間沒有分配。
flex-shrink 的計算方式
前文已經說到,flex 幾乎一次性解決了前端布局的所有問題。
那么既然可以在空間有多余時把多余空間分配給各個子元素,當然也可以在空間不夠時讓各個子元素收縮以適應有限的空間了。
這就是 flex-shrink 屬性的作用。
你可能會覺得 flex-shrink 的計算方式跟 flex-grow 很類似,然而事情并沒有這么簡單。
flex-shrink 屬性定義空間不夠時各個元素如何收縮。其值默認為 1。很多文章對此基本是一筆帶過:“flex-shrink 屬性定義了元素的收縮系數”,根本就不說它具體是怎么計算的。
flex-shrink 定義的僅僅只是元素寬度變小的一個權重分量。
每個元素具體收縮多少,還有另一個重要因素,即它本身的寬度。
舉個例子:
父元素 500px。三個子元素分別設置為 150px,200px,300px。
三個子元素的 flex-shrink 的值分別為 1,2,3。
首先,計算子元素溢出多少:150 + 200 + 300 - 500 = -150px。
那這 -150px 將由三個元素的分別收縮一定的量來彌補。
具體的計算方式為:每個元素收縮的權重為其 flex-shrink 乘以其寬度。
所以總權重為 1 150 + 2 200 + 3 * 300 = 1450
三個元素分別收縮:
150 1(flex-shrink) 150(width) / 1450 = -15.5
150 2(flex-shrink) 200(width) / 1450 = -41.4
150 3(flex-shrink) 300(width) / 1450 = -93.1
三個元素的最終寬度分別為:
150 - 15.5 = 134.5
200 - 41.4 = 158.6
300 - 93.1 = 206.9
同樣,當所有元素的 flex-shrink 之和小于 1 時,計算方式也會有所不同:
此時,并不會收縮所有的空間,而只會收縮 flex-shrink 之和相對于 1 的比例的空間。
還是上面的例子,但是 flex-shrink 分別改為 0.1,0.2,0.3。
于是總權重為 145(正好縮小 10 倍,略去計算公式)。
三個元素收縮總和并不是 150px,而是只會收縮 150px 的 (0.1 + 0.2 + 0.3) / 1 即 60% 的空間:90px。
每個元素收縮的空間為:
90 0.1(flex-shrink) 150(width) / 145 = 9.31
90 0.2(flex-shrink) 200(width) / 145 = 24.83
90 0.3(flex-shrink) 300(width) / 145 = 55.86
三個元素的最終寬度分別為:
150 - 9.31 = 140.69
200 - 24.83 = 175.17
300 - 55.86 = 244.14
當然,類似 flex-grow,flex-shrink 也會受到 min-width 的影響。
總結
雖然上面的公式看起來很復雜,其實計算過程還是比較簡單的:如果所有元素的 flex-grow/shrink 之和大于等于 1,則所有子元素的尺寸一定會被調整到適應父元素的尺寸(在不考慮 max/min-width/height 的前提下),而如果 flex-grow/shrink 之和小于 1,則只會 grow 或 shrink 所有元素 flex-grow/shrink 之和相對于 1 的比例。grow 時的每個元素的權重即為元素的 flex-grow 的值;shrink 時每個元素的權重則為元素 flex-shrink 乘以 width 后的值。
關于CSS中@support實現漸進式網頁設計實例代碼
文章主要給大家介紹了關于CSS中@support實現漸進式網頁設計的相關資料,文中通過示例代碼介紹的非常詳細,對大家學習或者使用CSS具有一定的參考學習價值前言特性查詢賦予了我們...
詳解移動端網頁設計實現內滾動的四種解決方案
這篇文章主要介紹了關于移動端實現內滾動的四種解決方案,實現的效果就是在一個區域內只允許部分區域產生滾動的效果,而其余部分則不能移動,需要的朋友可以參考借鑒,下面來一起看看吧。...
網頁設計如何優雅的實現垂直居中
這篇文章主要給大家介紹了關于如何優雅的實現垂直居中的相關資料,文中分別給大家介紹了已知寬高的元素、未知寬高的元素以及基于 Flexbox 的解決方案,都分別給出了示例代碼供大家參考學習,需要的朋友們下面隨著小編來一起學習學習吧...
網頁設計:淺談網頁基本性能優化規則小結
這篇文章主要介紹了淺談網頁基本性能優化規則小結的相關資料,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧...
用戶需求導致營銷型網頁設計
我們的每期話題,團隊在內部都會通過郵件進行一番討論,隨著討論的激烈,往往能碰撞出很多有意義的觀點,因此,將討論內容分享出來,有興趣的朋友可以接著話題討論下去。Junchen:期望不是從石頭里面蹦出來的,所有期望都是受到外界影響、結合自身需求的一個外在表現...
網頁設計柵格就是你對頁面版式的規劃
英文原文:http://desktoppub.about.com/od/grids/l/aa_gridsorder.htm柵格就是你對頁面版式的規劃你日常所見的許多頁面都有柵格存在。你可能注意不到,但它確實存在,并且支撐著設計內容,建立整體的架構,引導著頁面的元素。柵格是隱形的架構,用于指導你頁面...
網頁設計內容網頁中關于圖片預覽的設計
之前有寫過《內容頁頁碼的預覽導航》跟《照片預覽導航分析》兩個文章,想說明的是預覽這一功能在用戶心理所占有的比重是很大的,如果僅僅只是給出一排順序數字做為鏈接的標題,用戶的心理會產生不安全感。雖然給出一排順序數字做為鏈接幾乎是整個互聯網的默認分頁鏈接模...
網頁設計:腳本素材重構用戶體驗
設計網站的同志背景主要有兩種:學計算機、學藝術。基本上會寫代碼的不懂設計,會設計的不懂代碼,這個格局似乎到今天還沒變。某些學計算機的同學,有自己的審美品位,也能夠做出看起來不錯的網站,但學藝術的同學普遍難搞懂代碼...
網頁設計實現復選框(checkbox)和單選框(radio)對齊的方法
本文主要介紹了實現checkbox&radio對齊的具體方法,對大家的頁面布局具有很好的參考價值,需要的朋友一起來看下吧...
2016年網頁設計趨勢:卡片式設計如何在占盡優勢?
有數據顯示2014年移動端使用率遠遠高于桌面端,網頁設計都能很好的適應小屏幕。這個結論就是:簡單的界面風格,比如:扁平化設計,極簡設計,尤其是卡片設計比往年都要流...