数学不会背叛你,数学不会就是不会。
我现在写三角函数都是去 Google 的,不要问。注意!本篇可能会出现大量的加减乘除,如有出现头晕目眩、恶心想吐、手脚冰冷无力等状况,请立即关闭本篇文章,闪光洽关心您的身体健康。
或者你要去验孕也是可以的。
前几篇有提到剩余空间、元件填充等等,我们现在就来看一下实际上 Flex 容器是怎麽做运算的。首先是 flex-grow
的计算方式,在数值总和大於 1 的一般情况下来看,但且记得,必须容器上有存在 剩余空间 的情况下才能被分配。
所以我们来描述一下我们的容器跟元件,
600px
主要轴尺寸。200px
,flex-grow
设定为 1
。100px
,flex-grow
设定为 2
。首先,我们可以得知剩余空间为,
剩余空间 = 600px - (200px + 100px) = 300px
然後我们就能依照 flex-grow
来分配,
Flex 元件 1 扩充宽度 = 300px x 1 / (1 + 2) = 100px
Flex 元件 2 扩充宽度 = 300px x 2 / (1 + 2) = 200px
所以画面最後会得到,
Flex 元件 1 宽度 = 200px + 100px = 300px
Flex 元件 2 宽度 = 100px + 200px = 300px
看起来是不是没有很难,只要会加减乘除就好了。然後,我在一开始有提到 flex-grow
总和小於 1
的情况,
600px
主要轴尺寸。200px
,flex-grow
设定为 0.1
。100px
,flex-grow
设定为 0.2
。剩余空间就不赘述了,但是分配的方式不太一样。
Flex 元件 1 扩充宽度 = 300px x .1 / 1 = 30px
Flex 元件 2 扩充宽度 = 300px x .2 / 1 = 60px
所以你会发现最终我们得到的总宽度是,
Flex 元件 1 宽度 = 200px + 30px = 230px
Flex 元件 2 宽度 = 100px + 60px = 160px
这也是为何容器虽然有 flex-grow
但是没有被填满的情况。至於 flex-shrink
的部分基本上也是雷同的,只是从扩充变成压缩方向相反了而已。
对於 flex-grow
, flex-shrink
这两件事情,被干扰的机率其实颇高,
min-width
, max-width
min-content
, max-content
max()
, min()
如果不确定自己在做什麽,尽量不要在使用 flex-grow
或 flex-shrink
的情况下,使用这些设定、函数或关键字,还要预期会得到相对应的尺寸。
基本上在弹性设计结构的状况下,Flex 元件尺寸应该是提供一种 确保 空间使用的状况符合预期,请尽量不要把 Flex 元件尺寸当作是期待值。如果你要这麽做,请确保你使用的是 flex: 0 0 auto
,并且保证你的元件都有相对应尺寸。
至於 minmax()
,在 w3c 有特别说明 minmax()
这个 CSS Function 是给 Grid Layout 使用,所以你在 Flexbox 元件上并无法使用这个函示来计算尺寸。
回到一开始我们提到的 flex-basis
的相关描述,我们再来补充一点看起来比较 没用 少用的写法,这里的重点,
请留意
width
何处会失效
设定 | 宽度有效值 |
---|---|
flex-basis: max(10vw, 50rem); |
计算数值,取当下最大值 |
flex-basis: max(10vw, 50rem); width: 60px |
计算数值,取当下最大值 |
flex-basis: min(10vw, 50rem); width: 60px |
计算数值,取当下最小值 |
flex-basis: min(10vw, 50rem); width: content |
计算数值,取当下最小值 |
flex-basis: auto; width: min(10vw, 50rem); |
计算数值,取当下最小值 |
flex-basis: auto; width: content; |
计算数值,取容器内容尺寸 |
flex-basis: min(10vw, 50rem); max-width: 80px; |
80px |
flex-basis: min(10vw, 50rem); min-width: 100rem; |
100rem |
总结来说,除了 max-width
, min-width
会强迫覆写 flex-basis
以外,扣除 auto
会被 width
覆写,其余的设定都还是以 flex-basis
为准。换句话说,如果你使用以下的写法,就会遇到一些很神奇的事情,
.flex-container {
width: 600px;
}
.flex-item {
flex: 0 0 content;
width: 200px;
}
如果我们所使用的 HTML 结构像是这样,
<div class="flex-container">
<div class="flex-item">1</div>
<div class="flex-item">2</div>
<div class="flex-item">3</div>
<div class="flex-item">4</div>
</div>
根据简单的数学,我们有 4 个容器元件,每个容器元件定义了 width: 200px
,所以我们理论上会得到,4 x 200px = 800px
总共是 800px
的元件尺寸。然而,当我们的元件容器使用 flex: 0 0 content
时,我们的想像是,
还记得我们 第一篇 写了这个结果吗?
设定 | 宽度有效值 |
---|---|
flex-basis: content; width: 60px; |
60px |
所以真的吗?我们来看看实际结果,
惊不惊喜?意不意外?
然而,当我们把他分开来写的时候,
.flex-item {
flex-grow: 0;
flex-shrink: 0;
flex-basis: content;
width: 200px;
}
在这个时候他会恢复正常,这才是我们觉得不被压缩的样子。
为什麽?
官方有这样的说明,
A unitless zero that is not already preceded by two flex factors must be interpreted as a flex factor. To avoid misinterpretation or invalid declarations, authors must specify a zero <‘flex-basis’> component with a unit or precede it by two flex factors.
因为 flex: 0 0 content
这样的设定,是两个 0 的无单位因子,再加上 content
这种无单位 flex-basis
设定,所以会造成混淆。他会被当作单一弹性因子来看待,也就是等同於只设定了 flex-grow
跟 flex-basis
两组设定而已。
为何只有这两组?请看原始 flex
的设定值,
none | [ <‘flex-grow’> <‘flex-shrink’>? || <‘flex-basis’> ]
这样可以理解为何会出错了吧。由於 flex-shrink
预设为 1
,所以当我们照刚刚的写法来做的时候,就会被转成 flex: 0 1 content
这样的结果,并不会是你所设定的 flex: 0 0 content
, 後者的设定是不太合法 的写法。
不能说写错,而是在理解上官方的规定如此。
auto
不在此限。
另外一点,虽然你可以定义 Flex 元件尺寸,但不代表这个元件尺寸不会发生零尺寸(zero-sized)的情况。根据 Flex 容器的特性,这些所谓的零尺寸元件,会尽可能的被放在同一行,也就是说,在多行的情况下,即便第一行最後一个元件刚好填满容器,在下一行开始之前的零尺寸元件,都会被放在上一行里面。
其实零尺寸元件除了是空白元件外,也可能是宽度设定为 0
的元件。
gap
在 CSS Box Alignment Module Level 3 当中,已经提供了 gap
的样式可以使用,目前的支援度来说也算不错,
前几篇提到了 gap
这件事情,有这个样式就能解决使用 padding
或 margin
的宽度问题。
.flex-container {
display: flex;
gap: 10px;
}
请留意,gap
还是有分轴方向,所以会有以下几种写法,
column-gap
交叉轴方向的间隔。row-gap
主要轴方向的间隔。gap
两个轴方向的间隔,等於上述两个缩写。但是,这不是没有後遗症的。
<div class="flex-container">
<div class="flex-item"></div>
<div class="flex-item"></div>
<div class="flex-item"></div>
<div class="flex-item"></div>
</div>
我们在这种结构下使用 gap
的设定,
.flex-container {
display: flex;
width: 800px;
gap: 10px;
}
.flex-item {
flex: 0 0 auto;
width: 200px;
}
最终会造成什麽结果呢?
请注意,如果你的元件 flex-shrink
设定为 0
。那麽,gap
的空间就会将 Flex 容器撑开,也就是,当你的 Flex 容器使用 overflow: hidden
的话,最後一个 Flex 元件会被切断(因为超出了原本宽度设定了)。
而,若你将 flex-shrink
设定为非零值,那麽,你的 Flex 容器尺寸会生效,gap
的尺寸加上 Flex 元件尺寸,会视为 溢出尺寸 来处理,只是,gap
尺寸是 永远不会被压缩,所以倒楣的就是 Flex 元件。
Flexbox 其实也没有很复杂,最麻烦的其实还是尺寸处理。剩下的就交给上天安排就可以了,如果发现不对劲可以掷茭问一下妈祖也是可以的。
Flexbox 告一段落,明天会开始讲 Grid 的部分。其实无论是 Flex 还是 Grid,多半都会牵扯到很多其他的模组,不过全部拉进来讲会过於离题,所以 Flex 的部分就到此为止。
Flexbox 小游戏,有兴趣的可以玩玩看。
https://flexboxfroggy.com
目录与小节:
[CSS] Flex/Grid Layout Modules, part 1
部落格同步放送:
[CSS] Flex/Grid Layout Modules, part 5
<<: [Day 2] SRE - 你的服务死後不要让人担心嘛
>>: IIS WordPress 永久连结如何移除 index.php 路径
今天,我们要来看看在使用 Angular CLI 後,专案的架构会长什麽样? angular.jso...
Python 内建的数值类函式 数值类函式 执行结果 功能 abs(-10) 10 取绝对值 min...
**制作目标 ** 资料库搜寻 在输入料理搜寻模式後,会让使用者输入料理名称或一项食材,再从资料库里...
本篇同步发文在个人Blog: 一袋.NET要扛几楼?打造容器化的ASP.NET Core网站!系列文...
但是老师教我用var宣告变数,但我也看到有同学用 let 与 const 宣告变数,这是怎麽一回事...