若是閱讀過一些 Flex 入門的文章,會發現 Flex 的 Container 和 Item 的屬性加起來大概十幾個,雖然有些多,可是隻要花點時間,其實掌握起來仍是輕鬆加愉快的。不過當你高興地想用 Flex 大顯身手,處理複雜多變的佈局時,就可能會遇到像:最大/最小尺寸限制等邊界問題。這些在大部分 Flex 的介紹文檔裏都沒有太多筆墨描述。咱們來看一下例子。javascript
相信用過 bootstrap 或者 antd 等組件庫的同窗,都知道有一個佈局工具叫柵格。柵格系統的目的是讓設計遵循必定的規則,這樣可讓設計到實現徹底工業化(提升效率),也較大程度保證設計質量。相較於 float 的實現,flex 的柵格實現會簡單不少!css
柵格佈局中的一個很重要特性,是等寬佈局,這個在線的例子,用 Flex 能夠很是輕鬆的實現。 這例子,會獲得一個很完美的等寬佈局,嗯很開心😄。html
可是手一抖,就壞了😭。java
先給解決方案:git
overflow-x 解決方案准確的文檔定義,沒有找到,可是測試了一下,至關於設置了 min-width: 0
,若是你知道官方文檔如何定義歡迎留言交流。 不過剩下的其餘解決方案是什麼鬼,還能 width 和 min-width 爲 0?咱們帶着這個問題來學習一下 FlexBox 算法相關的概念。github
上圖中,其實漏掉了挺多信息,main size 能夠理解爲 main axis 上的尺寸,根據 flex-direction 的設置,能夠是 width 和 height。對應的 min/max main size 分別對應 min/max width 和 min/max height。 cross size 正好和 main size 垂直,根據 flex-direction 設置,也能夠取 width 或者 height。算法
min-width 的默認值,在 CSS2 標準的佈局類型(block/inline 等)中是 0。可是在 flex 佈局中,min-width 的默認值是最小 content 大小(min-content size)。劃重點,正是這個定義,致使了上文中 Grid System 被內容溢出撐大。當沒有明確設置 width 或者 min-width 的值時,flex-basis 的設置不會起做用,元素大小最後會受到 min-width 值的限制。bootstrap
the initial main size of the flex item, before free space is distributed according to the flex factors.antd
flex-basis 定義了 flex item 進行伸縮計算的基準值,如下是 flex-basis 的定義。ide
- Name: flex-basis
- Value: content | <‘width’>
- Initial: auto
- Applies to: flex items
- Inherited: no
- Percentages: relative to the flex container’s inner main size
- Computed value: specified keyword or a computed value
- Canonical order: per grammar
- Animation type: by computed value type
除了auto | content | <'width'>
,還能夠接受公共的一些值。
/* Specify <'width'> */
flex-basis: 10em;
flex-basis: 3px;
flex-basis: auto;
/* Intrinsic sizing keywords */
/* CSS3 Sizing 規範定義的通用屬性,目前兼容性不佳,不推薦使用 */
flex-basis: fill;
flex-basis: max-content;
flex-basis: min-content;
flex-basis: fit-content;
/* Automatically size based on the flex item’s content */
flex-basis: content;
/* Global values */
flex-basis: inherit;
flex-basis: initial;
flex-basis: unset;
複製代碼
這裏須要特別理解一下 auto 和 content 的取值。 當設置 auto 時,會使用 width 或 height 的取值,若是 width 或 height 的取值是 auto,那麼會看成 content 的取值來處理。 當設置 content 時,會按照 item 正常渲染出的 content width 或者 height 取值。
flex base size 由 flex-basis 屬性值計算而來,會直接用於計算壓縮和拉伸的結果。
中文直譯爲「假設的 main size」,表示在進行伸縮前,假設的 item 大小。該值等於 flex base size 被 min/max main size 限制的值,用於計算剩餘空間。下面是僞代碼。
hypothetical_main_size:
if flex_base_size > max_main_size:
return max_main_size
if flex_base_size < min_main_size:
return min_main_size
return flex_base_size
複製代碼
計算 free space 的時候,先肯定不伸縮的 item(frozen item),而且計算元素佔用的空間,規則以下:
if flex_shrink == 0 and flex_grow == 0:
return min_main_size
if flex_grow > 0 and flex_base_size > max_main_size:
return max_main_size
if flex_shrink > 0 and flex_grow == 0 and flex_base_size < min_main_size:
return min_main_size
複製代碼
flex container 首先會把 frozen items 的大小去掉,而後再去掉可伸縮 item 的 flex base size。獲得初始的 free space
main_size = flex_base_size + flex_grow_factor * free_space / SUM(flex_grow_factor of items)
複製代碼
scaled_flex_shrink_factor = flex_base_size * flex_shrink_factor
main_size = flex_base_size - scaled_flex_shrink_factor * free_space / SUM(scaled_flex_shrink_factor of items)
複製代碼
flex_base_size 越大的壓縮越多,或者說縮小得越快
若是超過 min/max main size 那麼須要取 min/max main size 值。
這個佈局就像一個三明治,兩邊是內容寬度不可伸縮,中間自適應伸縮。它有不少的應用場景,好比:Modal,Title,Page Frame,Select Option。 在沒有 flex 的時代,須要用 inline-block、float 等技術來實現,實現複雜,並且很難完美。尤爲在垂直方向的佈局,不能很好的自動撐開中間高度。用 flex 實現一切都會變得很是簡單。在線例子
除了三列,其實還有不少 2 列的佈局,也能夠間接地經過三明治佈局來實現。
文章做者:嚴文序(EE People 團隊)
邀請優秀的人一塊兒作有挑戰的事兒!字節跳動效率工程團隊研發職位招聘,想成爲技術大牛的夥伴快點進來看!職位介紹