若是阅读过一些 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 团队)
邀请优秀的人一块儿作有挑战的事儿!字节跳动效率工程团队研发职位招聘,想成为技术大牛的伙伴快点进来看!职位介绍