《现代Web布局》小册的学习笔记。
这篇不是系统的记录知识点,对于我已经掌握的或者我认为基础的知识不会记录。
Flex布局
Flex布局中有两条轴,主轴和侧轴,轴的方向会受 CSS 的derection
、writing-mode
和 HTML 的dir
属性值的影响。
空间分配属性和对齐属性
- 空间分配属性:
justify-content
、align-content
、place-content
(前两者简写align在justify在后) - 对齐属性:
align-self
、align-items
align-content
和align-items
区别
align-content
可以让所有 Flex 行,在侧轴上分配剩余空间。align-items
让 Flex 项目在自己行内的侧轴上对齐,Flex 容器中的每一行都有自己的主轴方向和侧轴方向,也就是说,当 Flex 容器有多行出现时,使用align-items: center
无法让它们在 Flex 容器中垂直居中(只能在所在 Flex 行中垂直居中)。align-content
属性必须要在flex-wrap
属性值为 wrap 或 wrap-reverse 条件下才能正常工作,但align-items
属性则不需要,因为单行使用align-items
足矣。- 如果同时设置了
align-content
和align-items
,优先使用align-content
。
align-self
和margin
align-self
用于某一个 Flex 项目在侧轴上对齐。在容器设置了align-content
或align-items
时,该属性行为会有差异:- 只有
align-content
属性值为 stretch 时,align-self
属性的值才有效。 - 而碰上
align-items
时不会有类似限制,只不过 Flex 项目的align-self
属性取值为 auto 时,不会覆盖 Flex 容器上align-items
的效果。
- 只有
- Flex 容器不存在 justify-items 和 justify-self ,因为 Flex 项目在 Flex 容器的主轴上被当作一个组。因此没有将单个 Flex 项目从该组中分离出来的概念,Grid 布局有这个概念。但可以使用
margin
来实现类似效果。
flex
属性
flex-grow
、 flex-shrink
、 flex-basic
简写,常见简写含义:
- 默认值:0 1 auto;
- flex: 1:1 1 0%;
- flex: none:0 0 auto;
- flex: auto:1 1 auto;
flex-basic
- 优先级公式:content => width => flex-basic
意思是,如果 Flex 项目未显式指定flex-basic
属性,那么flex-basic
将使用width
值;如果 width
也没有,那么flex-basic
基于 Flex 项目的内容计算宽度 。当然,最终都会被min-width
和max-width
限制(或者height)。
- 如果 Flex 项目的
flex-basic
和width
取初始值 auto 时,Flex 项目的初始化尺寸是fit-content
;但当flex-shrink
显式重置为0,Flex 项目不可收缩时,Flex 项目的初始化尺寸就是max-content
。 - ⚠️当 Flex 容器产生不足空间,即使 Flex 项目的
flex-shrink
是非0值,Flex 项目宽度也不会小于min-content
或者内部固定元素宽度。所以通过flex: 1
想让每一个项目都等宽是不可靠的,可以设置min-width: 0
来解决这个问题。
flex-grow
和flex-shrink
flex-grow
默认值为0。当所有 Flex 项目的flex-grow
总和小于 1 时,Flex 容器剩余空间分不完。flex-shrink
默认值为1。同理flex-shrink
总和小于 1 时,Flex 容器不足空间分不完。
Grid布局
Grid布局中有两条轴,块轴和内联轴,轴的方向会受 CSS 的derection
、writing-mode
和 HTML 的dir
属性值的影响。
- 块轴(列轴):定义网站文档(元素块)流,CSS 的书写模式
writing-mode
会影响块轴的方向。 - 内联轴(行轴):定义网站的文本流方向,也就是文本的阅读方式,CSS 的
derection
或 HTML 的dir
会影响内联轴的方向。
但需要注意的是,列轴和行轴方向是始终不变的,这两个轴只是现实中网格的概念,拿来方便理解。
fr单位
fr
单位只用于定位网格轨道的四个属性:grid-template-column
、grid-template-row
、grid-auto-column
、grid-auto-row
。fr
是网格轨道弹性系数,是一个类似于Flex
弹性特性的单位,计算公式是:网格轨道尺寸 = 网格轨道弹性系数 ✖️ 网格容器可用空间 ➗ 所有网格轨道弹性系数总和
。其中网格容器可用空间不一定等于网格容器宽度,会减去已确定的网格轨道宽度,比如某些轨道宽度单位是百分比、px等,就算是已确定的宽度。- 当所有网格轨道
fr
相加不大于1,代表网格容器空间还会有剩余。
⚠️需要注意的是:所有轨道设置为1fr
并不代表它们的列宽(或行高)都是相等的,1fr
最小不会小于网格项目的min-content
,当某个轨道宽度计算完之后小于其min-content
,会把少的这部分按各fr
所占比例减在其他轨道上。
在底层1fr === minmax(auto, 1fr)
,意味着min=auto
(即min-width=min-content
),max=1fr
。
这个问题可以通过两种方式解决:
- 定义网格轨道时,用
maxmin(0, 1fr)
代替1fr
。 - 给网格项目设置
min-width: 0
。
可用于Grid布局的函数
repeat(重复次数, 宽度列表)
用来设置网格轨道的重复片段,接收了两个参数:
- 第一个参数:重复次数,支持
auto-fill
、auto-fit
两个关键词,用于在保证网格项目不溢出网格容器之下,创建最多数量的网格列(或行)轨道。- auto-fill:如果网格容器在内连轴上具有确定的大小或最大大小,则重复次数是最大可能的正整数。
- auto-fit:作用同
auto-fill
,区别是会折叠所有空轨道,也就是将空轨道宽度折叠为0px,这会影响fr
单位的计算,因为一旦出现折叠现象,网格容器就会出现剩余可用空间,从而就会影响到fr
的计算。所以使用auto-fit
可能会扩展网格项目去填补剩余空间。需要注意的是,并不是比auto-fill
创建的少,只是空轨道被折叠为0px。
看个例子
<!DOCTYPE html>
<html lang="zh">
<head>
<style>
.grid-container {
display: grid;
width: 800px;
grid-auto-rows: 100px;
gap: 10px;
}
.grid-container1 {
grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
}
.grid-container2 {
grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
}
.grid-container .item {
border: 2px solid #0909;
}
</style>
</head>
<body>
<div class="grid-container grid-container1">
<div class="item"> 1 </div>
<div class="item"> 2 </div>
<div class="item"> 3 </div>
<div class="item"> 4 </div>
</div>
<div class="grid-container grid-container2">
<div class="item"> 1 </div>
<div class="item"> 2 </div>
<div class="item"> 3 </div>
<div class="item"> 4 </div>
</div>
</body>
</html>
- 两者相同点:当网格容器无法容纳网格轨道时(有网格项目的),会自动创建新的一行。所以通过
repeat
可以轻松实现如下布局效果(RAM布局):
.container {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
gap: 10px;
}
![Kapture 2023-03-20 at 21.18.25.gif](https://img-blog.csdnimg.cn/img_convert/7b2a7d48f923ea8fa0a4081e7e3a41a8.gif#averageHue=#2a3237&clientId=u54c77816-c98b-4&from=paste&height=401&id=u026499d9&name=Kapture 2023-03-20 at 21.18.25.gif&originHeight=801&originWidth=1562&originalType=binary&ratio=2&rotation=0&showTitle=false&size=4340597&status=done&style=none&taskId=uffaceaf1-5872-46db-90b9-ba45e533831&title=&width=781)
- 第二个参数:轨道宽度列表值,一般有如下几个写法(注意repeat不能嵌套repeat)
.grid-container {
grid-template-columns: repeat(2, 1fr);
/*1fr 1fr*/
grid-template-columns: repeat(2, 1fr, 200px);
/*1fr 200px 1fr 200px*/
grid-template-columns: repeat(2, minmax(min(300px, 100%), 1fr));
/*minmax(min(30px, 20%), 1fr) minmax(min(30px, 20%), 1fr)*/
grid-template-columns: repeat(2, min-content);
/*min-content min-content*/
grid-template-columns: repeat(2, 1fr [col]);
/*1fr [col] 1fr [col]*/
grid-template-columns: repeat(2, [col-start] 1fr [col-end]);
/*[col-start] 1fr [col-end col-start] 1fr [col-end]*/
}
minmax(MIN, MAX)
表示一段长度范围的闭区间,用于定义轨道宽度。
- 当MAX小于MIN时,不算无效,会忽略MAX,返回MIN的值。
- 如果MIN和MAX都是百分比,则没有不得小于
min-content
的限制,网格容器缩小时会无限跟着缩小。 - 只有MAX能用
fr
单位。 - 使用
auto
时:- 当
auto
作为MAX时,auto
相当于max-content
,即minmax(100px,auto)===minmax(100px,max-content)
。 - 当
auto
作为MIN时,当min-width
等和最小有关的属性小于min-content
时,auto
相当于这个属性指定的值,否则相当于min-content
。
- 当
min()、max()、clamp()
不专用于Grid布局,是CSS比较函数,支持使用加减乘除表达式作为值。
- clamp:接收三个参数:最小值、首选值、最大值。作用是把一个值限制在一个上限和下限之间,当这个值超过最小值和最大值的范围时,在最小值和最大值之间选择一个值使用,小于最小值返回最小值,大于最大值返回最大值。
clamp(MIN, VAL, MAX)
相当于max(MIN, min(VAL, MAX))
。
在实际使用中,更建议将CSS比较函数与minmax
函数以及关键词min-content
或max-content
结合起来使用。
fit-content()
将给定大小夹紧为可用大小
公式:fit-content(<length-percentage>) = max(minimum, min(limit, max-content))
。
- minimum:代表最小值,一般等于
min-content
,除非指定了最小相关属性,比如min-width
。 - limit:传给
fit-content
的值,类型为<length-percentage>
,也就是只支持或。
也就是说,如果给fit-content()
传入的值大于max-content
,返回值介于min-content
和max-content
之间,反之,返回值介于min-content
和参数之间,总之,fit-content()
返回的值不会小于min-content
。比如fit-content(200px)
,代表不会超过200px,并且可以在内容很短的情况下缩小到200px以下,但不会小于min-content
。
fit-content
关键字,就是介于min-content
和max-content
之间。两个概念合在一起更好理解。
grid-auto-flow
grid-auto-flow
默认为row
,也就是当出现没有指定网格区域的网格项目时,优先从左到右从上到下放置,当显式网格不够用时,优先创建行轨道。- 可以设置为
colomn
,效果和row
相反,优先从上到下从左到右放置,当显式网格不够用时,优先创建列轨道。 - 网格布局默认采取稀疏算法,放置网格项目时不会考虑网格空洞(没有放置项目的网格区域),这是由于某个网格项目偏大或偏小产生的。当
grid-auto-flow
加上dense
时,就会使用紧凑算法,放置时就会优先考虑可以放得下的网格空洞。属性值需要定义为row dense
或者column dense
,只定义一个dense
相当于row dense
。
网格项目重叠
网格项目可以使用grid-row
(或对应的start\end)、grid-column
(或对应的start\end)、grid-area
来指定所放置的网格区域,如此一来就可能会出现网格项目重叠的现象,和定位一样,可以使用z-index
来说明重叠的网格项目在 Z轴 上的层级,没有z-index
则会由网格项目在文档中出现的先后顺序来决定,越往后层级越高。
可以利用网格项目重叠实现如下的布局:
<!DOCTYPE html>
<html lang="zh">
<head>
<style>
.grid-container {
display: grid;
width: 600px;
margin: auto;
gap: 5px;
}
.grid-container1 {
grid-template-columns: repeat(4, 150px);
grid-template-rows: repeat(4, 150px);
}
.grid-container1 div {
line-height: 300px;
text-align: center;
font-size: 25px;
font-weight: bold;
}
.grid-container div:nth-child(1) {
grid-area: 1 / 1 / 3 / 3;
}
.grid-container div:nth-child(2) {
grid-area: 1 / 3 / 3 / 5;
}
.grid-container div:nth-child(3) {
grid-area: 3 / 1 / 5 / 3;
}
.grid-container div:nth-child(4) {
grid-area: 3 / 3 / 5 / 5;
}
.grid-container div:last-child {
grid-area: 2 / 2 / 4 / 4;
background-color: rgb(164, 159, 159);
border-radius: 50%;
}
.grid-container .item {
background-color: #0909;
}
</style>
</head>
<body>
<div class="grid-container">
<div class="item"> 1 </div>
<div class="item"> 2 </div>
<div class="item"> 3 </div>
<div class="item"> 4 </div>
<div class="item"> </div>
</div>
</body>
</html>
网格布局中的对齐方式
分为网格项目和网格轨道的对齐
- 网格项目对齐:
justify-items
和justify-self
沿内连轴方向对齐网格项目,align-items
和align-self
沿块轴方向对齐网格项目,其中*-items
被用于网格容器,相当于给每个项目设置*-self
(*-self
用于网格项目)。 - 网格轨道对齐:
align-content
沿着块联轴方向对齐网格轨道,justify-content
沿着内联轴方向对齐网格轨道,都被用于网格容器。 - 以上所有属性可以通过
place-*
来简写,place-items
、place-self
、place-content
,align在justify在后。
网格轨道布局:
对于网格轨道的对齐,通常只有网格容器有剩余空间时才会使用,当没有时,*-content
各值的效果都相同,等于start(默认值)。如果轨道溢出网格容器,*-content
会影响溢出方向,比如两侧溢出,start溢出等。
margin:
因为Flex布局不存在jestify-items
和justify-self
,通常会用margin
来实现某些对齐样式,margin
对于网格布局同样有效(用于网格项目上),需要注意的是,网格项目上设置margin
值时,网格项目会向里收缩。