當前位置:
首頁 > 最新 > Flexbox 布局的正確使用姿勢

Flexbox 布局的正確使用姿勢

在項目中,我們還會大量使用到flexbox的新舊屬性,但大多數人一般只會寫新屬性,舊屬性交由autoprefixer處理,但其實完成同樣功能的新舊屬性表現形式卻不盡相同。還有部分人只使用「萬能」的flex:number屬性為伸縮項目分配空間,但有些特殊情景卻無法滿足,此文為此梳理了flexbox的新舊屬性區別和分配空間的原理,為大家用flexbox布局的項目通通渠。

Flexbox兼容性

PC端的兼容性

移動端的兼容性

如上圖,為了兼容IE10-11和Android4.3-,UC,我們仍需要使用Flexbox的舊屬性。

Flexbox新舊屬性

Flexbox的新屬性提供了很多舊版本沒有的功能,但是目前Android4.x和UC仍有一定市場佔有率需要兼容,因此目前只使用新舊屬性都有的功能。

能實現相同功能的Flexbox新舊屬性如下表:

但想像是美好的,現實是殘酷的,新舊屬性里有那麼幾個頑固分子並不能乖乖的表現的一樣,總有那麼一點不同。

下面我們來看看是哪些新舊屬性有不同:

vs

相同點:改變主軸方向和伸縮項目的排列順序;在ltr下伸縮項目從右到左排列。

不同點:

:第一個伸縮項目向主軸起點對齊

:最後一個伸縮項目向主軸終點對齊

相同點:改變主軸方向和伸縮項目的排列順序;在ltr下伸縮項目從下到上排列。

:第一個伸縮項目向主軸起點對齊。

:最後一個伸縮項目向主軸終點對齊。

相同點:定義伸縮項目顯示順序。

:默認值為0;可以為負值。

:默認值為1;取值大於1。

相同點:定義伸縮項目的擴展因素。

不同點: 同時定義了伸縮項目的縮小因素。

相同點:定義伸縮項目的縮小因素。

不同點: 同時定義了伸縮項目的擴展因素。

Flexbox分配空間原理

影響Flexbox布局分配空間的屬性有三個,分別是 、 和 。

:當伸縮項目在主軸方向的總寬度

:當伸縮項目在主軸方向的總寬度 > 伸縮容器,伸縮項目根據縮小因素分配總寬度超出伸縮容器的空間。

:伸縮基礎,在進行計算剩餘空間或超出空間前,給伸縮項目重新設置一個寬度,然後再計算。

我們先來看看如何計算計算拉伸後的伸縮項目寬度,先簡單明了的給個公式,再通過栗子來驗證。

伸縮項目擴展寬度 = (項目容器寬度 – 項目寬度或項目設置的 總和) * 對應的 比例

拉伸後伸縮項目寬度 = 原伸縮項目寬度 + 擴展寬度

.flexbox-wrap{ width:550px; display: flex; } .flexbox-item{ &:nth-child(1){ width:60px; } &:nth-child(2){ width:70px; } &:nth-child(3){ flex-basis:80px; } &:nth-child(4){ flex-basis:90px; } &:nth-child(5){ flex-basis:100px; } } @for $i from 1 through 5 { .flexbox-item:nth-child(#{$i}){ flex-grow: $i; background-color: rgba(35 * (6-$i), 20 * $i, 35 * $i,1); } }

我們來計算一下上面栗子中第一個伸縮項目拉伸後的寬度。

對應著公式一步步計算:

// 項目容器寬度 container = 550 // 項目寬度或項目設置的flex-basis總和 itemSum = 60 + 70 + 80 + 90 + 100 = 400 // 第一個伸縮項目對應的flex-grow比例 flexRatio = 1 / ( 1 + 2 + 3 + 4 + 5 ) = 1/15 // 第一個伸縮項目擴展寬度 extendWidth = ( 550 - 400 ) * 1/15 = 10 // 第一個伸縮項目拉伸後的寬度 itemWidth = 60 + 10 = 70

計算後得到第一個伸縮項目拉伸後的寬度是70px,我們通過chrome上的盒子模型來看看是否正確

chrome計算的結果和我們計算的結果是一致的。

根據拉伸的計算公式是不是很容易就能推演出壓縮的計算公式呢?

伸縮項目縮小寬度 = (項目寬度或項目設置的 總和 – 項目容器寬度) * 對應的 比例

壓縮後伸縮項目寬度 = 原伸縮項目寬度 – 縮小寬度

繼續用個栗子來驗證公式是否正確

.flexbox-wrap{ width:250px; display: flex; } .flexbox-item{ &:nth-child(1){ width:60px; } &:nth-child(2){ width:70px; } &:nth-child(3){ flex-basis:80px; } &:nth-child(4){ flex-basis:90px; } &:nth-child(5){ flex-basis:100px; } } @for $i from 1 through 5 { .flexbox-item:nth-child(#{$i}){ flex-shrink: $i; background-color: rgba(35 * (6-$i), 20 * $i, 35 * $i,1); } }

我們來計算一下上面栗子中第一個伸縮項目壓縮後的寬度。

// 項目容器寬度 container = 250 // 項目寬度或項目設置的flex-basis總和 itemSum = 60 + 70 + 80 + 90 + 100 = 400 // 第一個伸縮項目對應的flex-shrink比例 flexRatio = 1 / ( 1 + 2 + 3 + 4 + 5 ) = 1/15 // 第一個伸縮項目縮小寬度 extendWidth = ( 400 - 250 ) * 1/15 = 10 // 第一個伸縮項目壓縮後的寬度 itemWidth = 60 - 10 = 50

計算後得到第一個伸縮項目壓縮後的寬度是50px,我們通過chrome上的盒子模型來看看是否正確

chrome計算的結果和我們計算的結果不一樣。

伸縮項目壓縮的計算方式和拉伸的不一樣,是因為壓縮會有極端情況,我們把第一個伸縮項目的 修改為10,此時縮小寬度為 ,縮小的寬度比原寬度要大,計算的壓縮後的寬度變成了負數。

為了避免這種極端情況,計算縮小比例是要考慮伸縮項目的原寬度。

正確的公式是這樣的

伸縮項目縮小寬度 = (項目寬度或項目設置的flex-basis總和 – 項目容器寬度)(對應的flex-shrink項目寬度或項目設置的flex-basis比例)

// 項目容器寬度 container = 250 // 項目寬度或項目設置的flex-basis總和 itemSum = 60 + 70 + 80 + 90 + 100 = 400 // 第一個伸縮項目對應的flex-shrink比例 flexRatio = (1*60) / (1*60+2*70+3*80+4*90+5*100) = 6/130 // 第一個伸縮項目縮小寬度 extendWidth = ( 400 - 250 ) * 6/130 ≈ 6.922 // 第一個伸縮項目壓縮後的寬度 itemWidth = 60 - 6.922 = 53.078

計算後得到第一個伸縮項目壓縮後的寬度是53.078px,和chrome上的盒子模型是一樣的。

Flexbox屬性縮寫陷阱

上面介紹的 、 和 有一個縮寫的寫法 。

: [ ] [ ]

各種縮寫的值

==

在實際項目中,會直接寫使用縮寫的 來給伸縮項目分配空間,但是使用縮寫屬性會留下一些陷阱,導致表現的結果不盡如人意。

分別使用 和 來把伸縮項目拉伸填滿容器,看看錶現的差異。

首先看看使用 拉伸伸縮項目的效果

.flexbox-wrap{ width:550px; display: flex; } .flexbox-item{ flex-grow:1; &:nth-child(1){ width:60px; } &:nth-child(2){ width:70px; } &:nth-child(3){ width:80px; } &:nth-child(4){ width:90px; } &:nth-child(5){ width:100px; } } @for $i from 1 through 5 { .flexbox-item:nth-child(#{$i}){ background-color: rgba(35 * (6-$i), 20 * $i, 35 * $i,1); } }

每個伸縮項目在原寬度上拉伸相同的寬度

通過上面的計算拉伸後的伸縮項目寬度,可以計算第一個伸縮項目拉伸後的寬度

// 項目容器寬度 container = 550 // 項目寬度或項目設置的flex-basis總和 itemSum = 60 + 70 + 80 + 90 + 100 = 400 // 第一個伸縮項目對應的flex-grow比例 flexRatio = 1 / ( 1 + 1 + 1 + 1 + 1 ) = 1/5 // 第一個伸縮項目擴展寬度 extendWidth = ( 550 - 400 ) * 1/5 = 30 // 第一個伸縮項目拉伸後的寬度 itemWidth = 60 + 30 = 90

然後我們把 替換成 ,下面是表現的效果,伸縮項目拉伸後的寬度變成一樣了。

從chrome的盒子模型可看到伸縮項目拉伸後寬度變成了 ,伸縮容器等分了容器的寬度。

展開後是 , 相當於 ,兩者的區別在於 的值不同。 為項目寬度重新設置了寬度為 ,所以可分配空間為整個容器,從公式計算上可以更直觀理解:

// 項目容器寬度 container = 550 // 項目寬度或項目設置的flex-basis總和 itemSum = 0 + 0 + 0 + 0 + 0 = 0 // 第一個伸縮項目對應的flex-grow比例 flexRatio = 1 / ( 1 + 1 + 1 + 1 + 1 ) = 1/5 // 第一個伸縮項目擴展寬度 extendWidth = ( 550 - 0 ) * 1/5 = 110 // 第一個伸縮項目拉伸後的寬度 itemWidth = 0 + 110 = 110需要注意的Flexbox特性無效屬性

column-*在伸縮容器無效

float和clear在伸縮項目無效

vertical-align在伸縮項目無效

::first-line and ::first-letter在伸縮容器無效

伸縮容器中的非空字元文本節點也是伸縮項目

12我是個假文本345

margin折

伸縮容器和伸縮項目的margin不會折

伸縮項目間的margin不會折

舊版Flexbox的BUG

伸縮項目為行內元素要加display:block;或display:flex

到此本文結束,如果還有什麼疑問或者建議,可以多多交流,原創文章,文筆有限,才疏學淺,文中若有不正之處,萬望告知。

如果本文對你有幫助,請點下贊或推薦,寫文章不容易。

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 推酷 的精彩文章:

劃重點!在為可穿戴設備設計時這11點超重要!
探討通過Feign配合Hystrix進行調用時異常的處理
功能開發SEO規範筆記
經典排序演算法總結與Go實現
全網營銷時代:關鍵詞拓展實現廣告全網霸屏效果

TAG:推酷 |

您可能感興趣

Facebook將對Oculus部門進行布局AR/VR
iOS版Microsoft Edge Beta繼續優化 iPad布局更和諧
沖Echo Show而來?Facebook智能音箱的布局不限於此
NetBooster Asia與Artefact完成併購,致力於加強區域布局
三星Galaxy Fold早期拆解:布局有些亂
Microsoft Store布局調整:新增「Departments」下拉菜單
Uber與Getaround合作布局分時租賃,全盤「滴滴」化
讀 SnapKit和Masonry 自動布局框架源碼
獲得Kyligence Cloud產品支持,阿里雲是何布局?
Apple Watch Series 4拆解:內部布局更周到
曝光:filecoin上線前布局IPFS礦機的真實原因!
布局大殺器—ConstraintLayout
華為Mate20Pro拆機,比iPhoneXSMax布局好
Chrome Canary的設置頁面布局 被調整得更加易於使用
從Xbox 360到Play Anywhere:微軟的十年布局和一招致勝
iRobot收購Root Robotics,布局教育機器人市場
Node Capital生態布局初成,部分項目差強人意
類索尼PS Vita布局風格,GPD Win Max Windows 10微型掌機曝光
Label顯示圖片,Pack布局控制項
T-Mobile與Sprint合併,美國運營商能否扭轉5G布局落後現況?