Flexbox布局的正確使用姿勢

2020-12-16 TechWeb

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

Flexbox兼容性

PC端的兼容性

移動端的兼容性

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

Flexbox新舊屬性

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

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

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

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

flex-direction:row-reverse vs box-orient:horizontal;box-direction:reverse

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

不同點:

flex-direction:row-reverse:第一個伸縮項目向主軸起點對齊

box-orient:horizontal;box-direction:reverse:最後一個伸縮項目向主軸終點對齊

flex-direction:column-reverse vs box-orient:vertical;box-direction:reverse

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

不同點:

flex-direction:column-reverse:第一個伸縮項目向主軸起點對齊。

box-orient:vertical;box-direction:reverse:最後一個伸縮項目向主軸終點對齊。

oreder:integer vs box-ordinal-group:integer

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

不同點:

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

box-ordinal-group:integer:默認值為1;取值大於1。

flex-grow:number vs box-flex:number

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

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

flex-shrink:number vs box-flex:number

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

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

Flexbox分配空間原理

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

flex-grow:當伸縮項目在主軸方向的總寬度 flex-shrink:當伸縮項目在主軸方向的總寬度 > 伸縮容器,伸縮項目根據縮小因素分配總寬度超出伸縮容器的空間。 flex-basis:伸縮基礎,在進行計算剩餘空間或超出空間前,給伸縮項目重新設置一個寬度,然後再計算。

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

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

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

.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計算的結果和我們計算的結果是一致的。

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

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

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

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

.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計算的結果和我們計算的結果不一樣。

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

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

正確的公式是這樣的

伸縮項目縮小寬度 = (項目寬度或項目設置的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屬性縮寫陷阱

上面介紹的flex-grow、flex-shrink和flex-basis有一個縮寫的寫法flex。

flex: flex-grow [flex-shrink] [flex-basis]

flex各種縮寫的值

flex: initial == flex: 0 1 auto flex: none == flex: 0 0 auto flex: auto == flex: 1 1 auto flex: number == flex: number 1 0%

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

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

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

.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   

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

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

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

// 項目容器寬度  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在伸縮容器無效

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

1 2 我是個假文本 3 4 5

 

margin摺疊

伸縮容器和伸縮項目的margin不會摺疊 伸縮項目間的margin不會摺疊

舊版Flexbox的BUG

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

點讚 0

相關焦點

  • Flexbox 布局的正確使用姿勢
    還有部分人只使用「萬能」的flex:number屬性為伸縮項目分配空間,但有些特殊情景卻無法滿足,此文為此梳理了flexbox的新舊屬性區別和分配空間的原理,為大家用flexbox布局的項目通通渠。Flexbox兼容性PC端的兼容性移動端的兼容性
  • CSS布局:保持頁腳在底部:Flexbox vs Grid
    流程的插頁式頁面,例如確認動作產品列表頁日曆活動詳細信息There are two ways to handle this with modern CSS: flexbox and grid.使用現代CSS有兩種方法來處理這個問題:flexbox和grid。
  • 我對Flexbox布局模式的理解
    Flex容器 display:flex 當我們使用flexbox布局時候,需要先給父容器的display值定位flex(塊級)或者inline-flex(行內級)。 當使用了這個值以後,伸縮容器會為內容建立新的伸縮格式化上下文(FFC),它的上下文展示效果和BFC根元素相同(BFC特性:浮動不會闖入伸縮容器,且伸縮容器的邊界不會與其內容邊界疊加)。 伸縮容器不是塊容器,因此有些設計用來控制塊布局的屬性,在伸縮布局中不適用,特別是多欄(column),float,clear,vertical-align這些屬性。
  • Flexbox 布局的最簡單表單
    彈性布局(Flexbox)逐漸流行,越來越多人使用,因為它寫 CSS 布局真是太方便了。
  • CSS Flexbox 青蛙遊戲
    導語在學習CSS中,Flexbox是一個比較實用的CSS 布局屬性,但很複雜,有些人可能沒法很快掌握,今天我要推薦一個跟這個相關的遊戲,在遊戲中學習Flexbox,這豈不是一個讓人覺得很快樂的事嗎?遊戲介紹來看一下作者對這個遊戲的具體介紹吧。
  • 保持頁腳在底部:Flexbox vs Grid
    流程的插頁式頁面,例如確認動作產品列表頁日曆活動詳細信息There are two ways to handle this with modern CSS: flexbox and grid.使用現代CSS有兩種方法來處理這個問題:flexbox和grid。
  • 【第2052期】保持頁腳在底部:Flexbox vs Grid
    流程的插頁式頁面,例如確認動作產品列表頁日曆活動詳細信息There are two ways to handle this with modern CSS: flexbox and grid.使用現代CSS有兩種方法來處理這個問題:flexbox和grid。
  • 詳解CSS Flexbox,附帶示例
    英文 | https://medium.com/javascript-in-plain-english/css-flexbox-explained-with-examples
  • CSS Flexbox入門指南和示例
    在詳細介紹之前,我只想回答為什麼我們應該使用彈性框布局而不是使用顯示屬性,浮點屬性,位置屬性來做布局網頁的傳統方式使用Flexbox的優點Flexbox會平均分配項目的高度和寬度,即使項目是動態添加的,您也無需關心CSS屬性
  • 本月Firefox 65 將加入 Flexbox Inspector 開發者工具
    CSS Flexbox(彈性盒子)是一種越來越流行的布局模型,它是一種用於在行或列中布局元素的一維布局方法,彈性元素可填充頁面額外空間,也可以適當收縮以適合較小的空間,有助於構建強大的動態頁面,但是它的學習曲線非常陡峭。開發者在一篇博客上具體介紹了該功能的研發背景與特性。
  • 使用Java8 Optional 的正確姿勢
    這就是我們將要講到的使用好 Java 8 Optional 類型的正確姿勢.在裡約奧運之時, 新聞一再提起五星紅旗有問題, 可是我怎麼看都看不出來有什麼問題, 後來才道是小星星膜拜中央的姿勢不對.因此我們千萬也別對自己習以為常的事情覺得理所當然, 絲毫不會覺得有何不妥, 換句話說也就是當我們切換到 Java 8 的 Optional 時, 不能繼承性的對待過往 null 時的那種思維, 應該掌握好新的, 正確的使用 Java 8 Optional 的正確姿勢.
  • 眼霜的正確使用方法Pick起來 正確的姿勢才能對得起那麼貴的眼霜
    眼霜的正確使用方法Pick起來 正確的姿勢才能對得起那麼貴的眼霜時間:2020-11-26 13:15   來源:百思特購物網   責任編輯:沫朵 川北在線核心提示:原標題:眼霜的正確使用方法Pick起來 正確的姿勢才能對得起那麼貴的眼霜 其實很多人很早就開始使用眼霜了,甚至有一些人覺得面霜跟眼霜使用起來差別不大
  • 使用信用卡的正確姿勢:「套現」!
    現在很多朋友都有信用卡,而信用卡有廣泛的用途場景,有些人用來買買買,有些人用於資金周轉,還有些人用來付首付,但你知道使用信用卡的正確姿勢是什麼?「合理套現」第二步:你每使用一次信用卡,就相當於一次「套現」!因為你用了ETC信用卡,所以過收費站不用付現金,這樣就等於把過路費從信用卡中套出來了(其他卡同理),這筆錢在下一個還款日來臨前都是屬於你的。
  • 30分鐘帶你學透快應用界面開發的最正確姿勢
    對著文檔安裝好環境,熟悉hap-toolkit的使用 2. 對著文檔看下我們提供的教程部分 3. 看看官網提供的sample 的例子二、進入正題本文主要講解快應用的界面布局界面布局其實就是兩大塊: 1. 樣式:修飾頁面 2.
  • 我的世界手機版經驗球正確使用姿勢
    我的世界手機版經驗球可以增加一定的經驗值,小夥伴們可以使用經驗值修理裝備或者對裝備附魔,今天小編為大家帶來的是我的世界手機版經驗球使用正確自身,希望大家喜歡。
  • 吉他:撥片的正確姿勢和使用方法,掃弦、主音
    很多朋友問過小編,怎麼沒有一個撥片的說明,今天呢,小編就來和大家帶來撥片的一個使用方法和一個正確的姿勢,不管是彈唱也好,掃弦也好,主音也好,我們都是可以用一個撥片的方式,來展示自己的一個彈奏方式,當然用手指彈的話,是更好,不過撥片習慣了的話,也是非常好用的,先說一說一個撥片的正確姿勢和使用方法吧
  • 正確的減肥跑步姿勢
    核心提示:想要通過跑步的方法得到減肥的效果,跑步的姿勢是很重要的,因為不正確的姿勢消耗的熱量會很少,正確的姿勢消耗的熱量會比較多,在跑步時手臂一定要彎曲,從手肘的位置彎曲成九十度,然後從肩膀的部位來回擺動,在擺動的時候每次手臂向前都要儘量像上方揮動,幅度到手肘和肩膀同高。
  • android grid布局專題及常見問題 - CSDN
    CSS Grid 布局是 CSS 中最強大的布局系統。與 flexbox 的一維布局系統不同,CSS Grid 布局是一個二維布局系統,也就意味著它可以同時處理列和行。通過將 CSS 規則應用於 父元素 (成為 Grid Container 網格容器)和其 子元素(成為 Grid Items 網格項),你就可以輕鬆使用 Grid (網格) 布局。
  • 正確的走路姿勢是什麼?
    答|百度派 @張振如果要說正確的走路姿勢是什麼的話,那麼我們首先就應該從不同的人的身上進行剖析,然後再以客觀形成的大眾化意見為基準才可以發表來自個人的觀點。當然,還有很多種走路姿勢在這裡我就不一一列舉了,只要你們記住這些個走路的姿勢都是不正確的,或者說是不得體的。
  • 母乳餵養的正確姿勢
    母乳餵養的正確姿勢你掌握了嗎?母乳餵養過程中出現奶水過多或者不足、乳房炎、寶寶厭奶等諸多問題,你又知道如何處理嗎?趕緊跟著專家來學習吧! 掌握正確的哺乳姿勢,讓寶寶吃的更香甜,有助媽媽產後休息。 孩子出生後1-2小時內,媽媽就要做好抱嬰餵奶的準備,掌握正確的哺乳姿勢,可以幫助寶寶順利吮吸乳房,讓寶寶吃起奶來更順暢香甜。