万事起头难,只要不起头,就一点都不难了。
在这个充满着 CSS Frameworks 的年代,人人有功练,人人有版切,身为老屁股的我只能在沙滩上晒乾,而且还卖不到钱。
铁人赛就当作自己还有在喘气的证明。
其实写 CSS 框架应该比较多观众,但就一个码农来说,自己动手做会比较有趣一点。而且那些框架实在有点五花八门,就是你去 Google 一些关键字,诸如「超好用」「XX 天就上手」「20XX 热门框架」然後就会跑出一堆。
我没有阻止你用,只要能赚钱的框架就是好框架。
君不见 jQuery 的
$
还是屹立不摇。
不过 jQuery 有点离题了就是。
目前 w3c 对於 Flexbox, Grid 这两件事情算是有认真在更新。虽然说 Grid 已经 CR 不过又挂上 Draft,该吵的东西也还没有结论(例如 subgrid
会推迟到 Level 2 才可能会推出 #Issue958)。
Grid 从 2016 年 CR 至今也 5 个年头了,基本上在 Caniuse 上面也呈现出不错的支援度。热门的 TailwindCSS 基本上也有采用 Grid 来做排版,至於怎麽用不要来问我,我没有很熟(哈)。
Flexbox 就不用再多说,我在 2012 年看他 CR 後,又到了 2016 才慢慢被推广出来,算起来已经 9 年了。至於说为什麽那麽不红(或是不普及?),可能要去问一下前阵子才入土的 IE 吧。
至於所搭配的 Media Query 会在系列中提及,会顺便讲一点,不会着墨太多。
flex-basis
的魔术align-self
order
gap
grid-template-areas
的字串定义fr
fit-content(limit)
minmax(min, max)
<轨道格线>
<数字> <自订轨道名称>
span [<数字>, <自订轨道名称>]
auto
与 Grid 单元轨道重叠
stretch
)与留白(margin
)以上这些,其实就把超长篇幅的文章然後分割成 30 份这样吧(哈)。
其实我不知道 Flexbox 还有谁想看?
这年头好像用框架比较快,谁理你背後的原理是什麽呢?
我们先来看看可使用状况。基本上除了 IE 以外,是不用担心使用上的问题。
Flexbox 的基本盘是对应从 CSS2.1 以来的四种编排模式,
block
)inline
, inline block
)table
, 或各种资料集设计)position
的各种变化)虽然是这样讲,不过这就跟当年 CSS1/2/2.1 开始流行後,从 <table>
慢慢转向 <div>
後,接着到了 HTML5 开始讲语意化。出了一些很奇妙的事情,
<table>
退流行了所以我都用 <div>
很潮~<div>
就用 position
神马都可以排,超 DUE 的~float
简直凌波微步,我得意的飘~<div>
简直罪恶!其他的就不提了,我只想说,为了语意化而语意化真的挺恶心的。
Flexbox 区块元件主要构成如下,
如果你把 Flex 容器主轴方向设定为 column
的时候,上图的主要轴、交叉轴就会交换。
设定容器我们可以使用 display
来达成,容器可以设定成两种,
display: flex
亦即使用区块(Box Level)来设定容器。display: inline-flex
亦即使用行内(Inline Level)来设定容器。无轮你设定的是哪一种,需要留意 Flex 容器会忽略以下特性,
float
, clear
会被忽略。vertical-align
无法应用在 Flex 元件上。::first-line
, ::first-letter
这两个拟似元件无法套用至容器上。倘若元素指定
display: inline-flex
的话,在计算样式值(Computed Value)会呈现flex
而不是inline-flex
,这一点请留意。
在容器当中,以下列举常用的样式设定,
样式 | 值 | 预设值 |
---|---|---|
flex-direction |
row , row-reverse , column , column-reverse |
row |
flex-wrap |
nowrap , wrap , wrap-reverse |
nowrap |
flex-flow |
<flex-direction> <flex-wrap> |
无预设值 |
容器主要轴、交叉轴会因为方向性的不同而交换,其下属性所适用的方向也会不同。
另,轴方向也会因为
writing-mode
的影响而有不一样的呈现,关於 Write Mode 可以参考 w3c 上面的说明(CSS Writing Modes Level 4)。
容器中对於影响元件的属性有这些,
样式 | 值 | 预设值 |
---|---|---|
justify-content |
flex-start , flex-end , center , space-between , space-around |
flex-start |
align-items |
flex-start , flex-end , center , baseline , stretch |
stretch |
align-content |
flex-start , flex-end , center , space-between , space-around , stretch |
stretch |
需要留意的是 align-content
只能适用在多行的 Flex 容器当中,在预设的容器设定中使属於单行 Flex 容器,套用这个样式是无效的设定。
容器些样式设定会因为轴方向性的不同而应用在不同的方向上(会跟着轴转动)。请留意一个点,轴方向并不总是内容流向,我所举的例子都是以惯用方向为主(由左至右,由上到下)。
举个例子来说,
另外关於 align-content
则是在多行容器中才会套用到这个样式。所谓的 多行 的意思即是 wrap
的情况下,产生超过一行的 Flex 元件时,该样式就会被套用。
请留意
column
这个方向在没有容器尺寸的情况下,无法产生wrap
的效果,亦即并无 多行 的情况存在,且关於wrap
的相关样式也会失效。
举一个套用 wrap
产生多行 Flex 容器的例子,
跟其他两个样式相同,当轴方向转动时,align-content
也会跟着轴转动,亦即应用的方向会不同。
任何被 Flex 容器所包含的第一层子元件,都会被转成 Flex 元件,而自身属性会转换成 Flex 格式内容(Flex formatting context),可以当作一般区块元件看待,但实际上并不是(Like Box Model, bot NOT.)。如同上述所说,这些元件并无法使用 float
尔等设定,这一点需特别留意。另外,假设这些元件被定义了静态定位(position
为 static
, absolute
)时,该元件就不属於 Flex 容器预设的主轴流向,会跳脱任何关於 Flex 容器所带来的影响。
元件自身也可以使用 display: flex
来将自己转变成容器,这样的作法在需要复杂结构时,可以自由变化使用。
Flex 元件有以下样式可以使用,
样式 | 值 | 预设值 |
---|---|---|
flex-grow |
数字(负值无效) | 0 |
flex-shrink |
数字(负值无效) | 0 |
flex-basis |
auto , content 或 宽度 |
auto |
flex |
none 或 <flex-grow> <flex-shrink> <flex-basis> |
0 1 auto |
order |
数字(可为负值) | 0 |
align-self |
auto , flex-start , flex-end , center , baseline , stretch |
auto |
其中 flex
除了 none
外,还有几个关键字可以使用,
关键字 | 等值 |
---|---|
none |
0 0 auto |
initial |
0 1 auto |
auto |
1 1 auto |
<正整数> |
<正整数> 1 0 |
flex
, flex-grow
, flex-shrink
, flex-basis
在绝大多数的 CSS 框架中,我们比较常见的设定大多都是这些组合,
flex: 0 1 auto;
// 或
flex: 1 0 100%;
// 或
flex: 1 0 50%;
max-width: 50%;
然後就没有然後了。因为人家这样用所以你就跟着这样用,至於为什麽要这样用好像也不是挺重要的事情。
没关系,我们就来看看到底发生了什麽事情?
属性 | 说明 |
---|---|
flex-grow |
将元件依照此设定数字的权重来填满容器的剩余空间。 |
flex-shrink |
当容器剩余空间不足时,依照此权重来压缩元件。 |
flex-basis |
在水平(row )排列容器中,等同於 width 样式,在同时设定时将会忽略 width 的样式设定。但若为 auto 或 content 时,则 width 样式将会覆盖。而当你设定为 0 时,结果会跟 content 雷同,但权重不同。 |
flex-grow
计算方式,可以依照此公式来计算,
剩余空间 x <flex-grow> / sum(<flex-grow>)
剩余空间怎麽来的呢?
容器空间 - sum(<flex-basis>||<width>)
但是,
当你的 flex-grow
总和小於 1
的时候,事情就不是这样了。在所有 Flex 元件的 flex-grow
总和小於 1
时,该总和会直接当作 1
来使用。换句话说,上面的公式会变成,
剩余空间 x <flex-grow> / 1
这样计算下来,容器就可能会有剩余空间没有分配的情况。
另外,当你的 flex-grow
有搭配 max-width
使用时,所计算出来的元件若大於 max-width
,则会优先取用 max-width
的设定值来使用,计算出来的填满尺寸将会被忽略。这也是造成容器没有被填满的另外一个原因。
flex-shrink
计算方式,可以依照此公式来计算,
溢出空间 x <flex-shrink> * <width>) / sum(<flex-shrink> * <width>)
溢出空间的计算方式为(注意,这为负值),
容器空间 - sum(<flex-basis>||<width>)
与 flex-grow
雷同,当你的 flex-shrink
总和小於 1
的时候,他并不会拿所有的溢出空间来计算,你的真实的溢出空间要先经过这样的计算,
溢出空间 x sum(<flex-shrink>) / 1
算出新的溢出空间之後,才回头套用上面的公式去计算。
flex-basis
的魔术特别把这件事情拿出来讲的原因,是因为他跟 width
实在有说不清的爱恨纠葛。如同上述提及了一些优先权的事情,这边给一个比较清楚的比较表,
设定 | 宽度有效值 |
---|---|
flex-basis: 50px; |
50px |
flex-basis: 50px; width: auto; |
50px |
flex-basis: content; width: 60px; |
60px |
flex-basis: 70px; width: 60px; |
70px |
flex-basis: auto; width: 80px; |
80px |
flex-basis: 90%; width: 80px; |
90% |
flex-basis: 90%; max-width: 80%; |
80% |
基本上,只要 flex-basis
不是使用关键字 auto
, content
的情况下,优先权一律覆盖 width
的设定。但是,这个数值设定会受到 max-width
的影响而有所不同。
align-self
这个 Flex 元件属性有一个 必要条件,倘若以 row
为主轴方向,你的容器必须要有交叉轴的尺寸设定,不然这个属性是无法有效呈现的。
order
故名思义就是 Flex 元件顺序的设定,但请留意,如果你的元件使用了静态定位设定(position
为 static
, absolute
)时,因为元件会跳脱 Flex 主轴流向,所以此时的顺序设定会失效。
Flex 元件会有一个隐性的定义,在 order
样式混用的情况下,没有设定 order
样式的 Flex 元件,会带有一个 order: 0
的效果。所以,若你在多个元件使用 order
时,请务必确认每个元件都有设定你想要的 order
样式。
举例来说,
<div class="flex">
<div class="item item-1"></div>
<div class="item item-2"></div>
<div class="item item-3"></div>
</div>
.flex {
display: flex;
flex-flow: row;
}
.item {
flex: 1 0 33.333333%;
max-width: 33.333333%;
}
.item-1 {
order: 1;
}
.item-2 {
order: 3;
}
.item-3 {
order: 2;
}
最终呈现的结果如图,
有一点请留意,如果你的轴方向是反向(row-reverse
或 column-reverse
)的话,顺序的设定也会反过来。
以上这些是 Flexbox 的基本概念介绍,其实讲起来并没有很多艰深的东西,真正比较枯燥乏味的会再後面继续介绍,如果不想理解 Flexbox 的演算机制的可以跳过没关系(笑)。
本篇内容理论上可以应付五成以上的容器设定。为什麽只有五成?因为我还有 留白 的部分没有讲到,那些算一算大概是剩下的四成五左右。
下一篇会着墨於那个四成五,至於剩下的 5% 就放最後吧,反正都是一些很硬的演算机制。
同步放送:
[CSS] Flex/Grid Layout Modules, part 0
[CSS] Flex/Grid Layout Modules, part 1
>>: [想试试看JavaScript ] 运算子 (算术运算子)
今年的疫情蛮严重的,希望大家都过得安好,希望疫情快点过去, 能回到一些线下技术聚会的时光~今天要了解...
元件介绍 Breadcrumb 是一个导航元件,用於显示当前系统层级结构中的路径位置,并且点击路径能...
什麽是暂存器 register? 暂存器顾名思义就是可以存放资料的地方,那也就是记忆体的一种罗? 记...
聊了 HTTP 的基本概念(网站内容是怎麽被下载到电脑里的?、Method、Status Code)...
接续上一篇,第二种改善R^2的经验。 2 . 减少极端值的影响 所谓的模型输出的准确性,也可以这麽想...