flex佈局精髓和填坑
說到flex佈局,大家可能並不陌生。對於基本概念,大家應該也有所瞭解。這裡可以推薦我看過的認為比較通俗易懂的部落格,它就是阮一峰老師的flex佈局部落格, 感謝阮一峰老師的無私分享。
那麼,瞭解過基本概念後。對於Flex佈局我們常見的幾個誤區和經常遇到的所謂的坑是什麼呢?這裡,相容性問題我就不講了,不是本次部落格的主要內容。下面我主要想講講flex佈局使用的幾個誤區和常遇到的問題。
1. Flex屬性的寫法
首先我們知道 flex: <number> <number> <length/percentage/cale> 實際上是flex-grow, flex-shrink, flex-basis三個屬性的縮寫。
flex: flex-grow flex-shrink flex-basis
那麼這三個屬性的初始值是什麼呢?
flex-grow: 0; flex-shrink: 1; flex-basis: auto; 根據內容大小分配
根據上面的基礎認知,下面我們介紹flex屬性的幾種常見寫法及解析
內建值寫法 flex: auto; 等價於 flex: 1 1 auto; 元素會根據自身的寬度與高度來確定尺寸,但是會自行伸長以吸收flex容器中額外的自由空間,也會縮短至自身最小尺寸以適應容器. flex: initial; 等價於 flex: 0 1 auto; 元素會根據自身寬高設定尺寸。它會縮短自身以適應容器,但不會伸長並吸收flex容器中的額外自由空間來適應容器. flex: none; 等價於 flex: 0 0 auto; 元素會根據自身寬高來設定尺寸。它是完全非彈性的:既不會縮短,也不會伸長來適應flex容器 單值法 One value, unitless number: flex-grow flex: <positive-number>; 等價於 flex: <positive-number> 1 0; 單值法 One value, unit number: flex-basis flex: <unit-number>; 等價於 flex: 0 1 <unit-number>;元素有一個自定義的主軸上的寬度/高度 (單值法) 雙值法 第一個值必須是無符號的 flex-grow | flex-shrink flex: <positive-number> <positive-number>; 等價於 flex: <positive-number> <positive-number> 0; 雙值法 第一個值必須是無符號的 flex-grow | flex-basis flex: <positive-number> <unit-number/percentage/calc()> 等價於 flex: <positive-number> 1 <unit-number/percentage/calc()> 三值法 flex: <positive-number> <positive-number> <unit-number/percentage/calc()>
2. flex-grow: 1 真的是等比分配嗎????
如下例子是我們所認為的平均分配嗎?
<div id="main" style="width: 1000px; height:200px;"> <div style="background-color:coral;">First</div> <div style="background-color:lightblue;">SecondI am long long long long long long long long long long long</div> <div style="background-color:khaki;">Third</div> <div style="background-color:pink;">Forth</div> <div style="background-color:lightgrey;">Fifth</div> </div>
#main { display: flex; div { flex-grow: 1;是等比分配嗎?請看執行結果 } }
執行結果: 覺得奇怪嗎?明明對每個div設定的都是 flex-grow: 1; 那麼,他們為什麼不是等比分配,全部是200px寬呢??? 這裡就需要我們回到上面定義的地方從新理解一下flex-grow的含義。請注意 flex-grow的含義,通俗的講, 是按使用者定義的比例去分配父元素剩餘的空閒空間(出去子元素本身所佔的空間之後剩餘的空間) 。這個地方通常是我們的誤區之一。認為只要設了等比例分配,那麼flex佈局就會按等比例去分配。no no no.
那麼,怎麼解決這個問題呢?其實再重新回到上面黃色部分的定義仔細讀幾遍,我們就會發現,問題實際上出在每個子元素本身所佔的空間是不一樣的,這才導致最終分配的全佔比是不一樣的。 子元素的寬度 = 子元素本身的寬度 + 剩餘空間的配比 。上面的案例,其實剩餘空間的配比是相等的,只是子元素原始本身的寬度不等,導致最終寬度是非等比例的。好的,知道問題就好解決了。 我們讓flex佈局在分配空間時忽略子元素本身的佔比就可以了,這裡我們肯定會想到屬性 flex-basis,它就是控制子元素本身佔比的,那麼我們設定它為 flex-basis: 0%;
#main { display: flex; div { flex-grow: 1; flex-basis: 0%; } }
再次測試一下:
ok, 很完美的解決了。我們上面的那種寫法是將flex-grow flex-shrink flex-basis 分開寫的情況。根據上面單值寫法的解析,其實我們直接寫成 flex: 1; 就不會出現上述問題。因為 flex: 1; 等價於 flex: 1 1 0;
flex-shink 屬性在使用時也有和flex-grow 屬性相同的需要注意的點。
下面談這個案例中另一個需要解決的問題, 當一個完整的單詞很長的話 ,如果只忽略子元素的原始大小還不太好用。依舊達不到等比分配的效果。如下
這時需要多加一個屬性設定 word-break: break-all/break-word ; 就解決了
3. flex 和 width的坑
專案中遇到一個問題。利用了flex佈局的元素,當該元素內部的子元素內容超過flex分配的空間後,flex分配比例失效。
<div class="view-list-item" [class.hyphens-words]="showHyphens"><div>{{ impact.currentState }}</div></div> <div class="view-list-item" [class.hyphens-words]="showHyphens"><div>{{ impact.futureStateName }}</div></div> <div class="view-list-item" [class.hyphens-words]="showHyphens"><div>{{ impact.changeDelta }}</div></div>
&:nth-child(3), &:nth-child(4), &:nth-child(5) { flex: 9; padding-right: 0px; > div { max-height: rem(60px); padding-right: rem(10px); overflow-y: auto; width: 100%; } }
解決方法: 在父的flex元素上設定 width:0px; 使得分配的空間大於設定的width;然後最終選擇分配的空間,從而規避這個問題
&:nth-child(3), &:nth-child(4), &:nth-child(5) { flex: 9; width: 0px; padding-right: 0px; > div { max-height: rem(60px); padding-right: rem(10px); overflow-y: auto; width: 100%; } }