40个css布局技巧
1、水平垂直居中
在flexbox布局模块中,不管是单行还是多行,要让它们在容器中垂直居中都很容易,而且方法也有很多种。最常见的是在Flex容器上设置对其方式,在flex项目上设置margin: auto;
先来看看看在flex容器上设置对其方式。
Flex容器和Flex项目上设置对其方式
几乎所有人都知道在flex容器上设置justify-content、align-items的值为center时,可以让元素在Flex容器中达到水平垂直居中的一个效果。
<!-- HTML -->
<div class="flex__container">
<div class="flex__item"></div>
</div>
/* CSS */
.flex__container {
display: flex;
justify-content: center;
align-items: center;
}
效果如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gfBuSSsW-1668419176792)(C:\Users\zheng_mingzhuo\AppData\Roaming\Typora\typora-user-images\image-20221114134754498.png)]
这种方式特别适应于让icon图标在容器中水平垂直居中,不同的是在Icon图标容器上显示设置display: inline-flex。比如下面这个示例:
<!-- HTML -->
<div class="flex__container">
<svg> </svg>
</div>
/* CSS */
.flex__container {
display: inline-flex;
align-items: center;
justify-content: center;
}
效果如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2fUCVRJT-1668419176793)(C:\Users\zheng_mingzhuo\AppData\Roaming\Typora\typora-user-images\image-20221114135517385.png)]
在这种模式之下,如果要让多个元素实现水平垂直居中的效果,那还需要加上flex-direction:column,比如:
<div class="flex__container">
<div class="avatar">:)</div>
<div class="media__heading"></div>
<div class="media__content"></div>
<div class="action"></div>
</div>
/* CSS */
.flex__container {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VYloLLVD-1668419176793)(C:\Users\zheng_mingzhuo\AppData\Roaming\Typora\typora-user-images\image-20221114135737984.png)]
在flex布局中,还可以像下面这样让Flex项目在Flex容器中达到水平垂直居中的效果:
<!-- HTML -->
<div class="flex__container">
<div class="flex__item"></div>
</div>
/* CSS */
.flex__container {
display: flex; // 或inline-flex
justify-content: center;
}
.flex__item {
align-self: center;
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-r1fhERnP-1668419176794)(C:\Users\zheng_mingzhuo\AppData\Roaming\Typora\typora-user-images\image-20221114135928614.png)]
如果在Flex容器中有多个Flex项目的时候,该方法同样有效:
.flex__container {
display: flex; // 或inline-flex
justify-content: center;
gap: 20px;
}
.flex__container > * {
align-self: center;
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-A4kMaLEX-1668419176794)(C:\Users\zheng_mingzhuo\AppData\Roaming\Typora\typora-user-images\image-20221114140458117.png)]
除此以外,还可以使用place-content: center让Flex项目实现水平垂直居中:
.flex__container {
display: flex;
place-content: center;
}
.flex__item {
align-self: center;
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yCTF5S8Z-1668419176795)(C:\Users\zheng_mingzhuo\AppData\Roaming\Typora\typora-user-images\image-20221114140724441.png)]
或者换:
.flex__container {
display: flex;
place-content: center;
place-items: center;
}
效果如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4l5T3gvY-1668419176795)(C:\Users\zheng_mingzhuo\AppData\Roaming\Typora\typora-user-images\image-20221114140857436.png)]
这两种方式同样适用于Flex容器中有多个Flex项目的情景:
.flex__container {
display: flex;
flex-direction: column;
place-content: center;
}
.flex__container > * {
align-self: center;
}
// 或
.flex__container {
display: flex;
flex-direction: column;
place-content: center;
place-items: center;
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DxG9fGVZ-1668419176796)(C:\Users\zheng_mingzhuo\AppData\Roaming\Typora\typora-user-images\image-20221114141043847.png)]
place-content是align-content和justify-content的简写属性;而place-items是align-items和justify-items的简写属性。即:
.flex__container {
place-content: center;
place-items: center;
}
等效于:
.flex__container {
align-content: center;
justify-content: center;
align-items: center;
justify-items: center;
}
在flex项目上设置margin-auto
如果在Flex容器中只有一个Flex项目,还可以显示在Flex项目显示设置margin的值为auto,这样也可以让Flex项目在Flex容器中水平垂直居中。例如:
.flex__container {
display: flex; // 或 inline-flex
}
.flex__item {
margin: auto;
}
效果如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vSI7S5Cz-1668419176796)(C:\Users\zheng_mingzhuo\AppData\Roaming\Typora\typora-user-images\image-20221114141917029.png)]
设置margin-left: auto;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-szZcOLZn-1668419176797)(C:\Users\zheng_mingzhuo\AppData\Roaming\Typora\typora-user-images\image-20221114142129869.png)]
设置margin-right: auto;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DPgdEqVj-1668419176797)(C:\Users\zheng_mingzhuo\AppData\Roaming\Typora\typora-user-images\image-20221114142211354.png)]
设置margin-top: auto;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-swWzBljt-1668419176798)(C:\Users\zheng_mingzhuo\AppData\Roaming\Typora\typora-user-images\image-20221114142255622.png)]
设置margin-bottom: auto;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GrpmeTMN-1668419176802)(C:\Users\zheng_mingzhuo\AppData\Roaming\Typora\typora-user-images\image-20221114142402728.png)]
设置 margin-left、margin-right为auto:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mJ9Pz0lf-1668419176802)(C:\Users\zheng_mingzhuo\AppData\Roaming\Typora\typora-user-images\image-20221114142458805.png)]
设置 margin-top、margin-bottom为auto:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WQ35eFFg-1668419176803)(C:\Users\zheng_mingzhuo\AppData\Roaming\Typora\typora-user-images\image-20221114142527687.png)]
Grid中实现水平垂直居中
CSS Grid布局可以说是现代Web布局中的银弹。它也是到目前为止布局系统中唯一一个二维布局系统。
在CSS Grid布局中,只需要仅仅的几行代码也可以快速帮助我们实现水平垂直居中的效果。比如:
<!-- HTML -->
<div class="grid__container">
<div class="grid__item"></div>
</div>
/* CSS */
.grid {
display: grid; // 或 inline-grid
place-items: center
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Lh285yIU-1668419176803)(C:\Users\zheng_mingzhuo\AppData\Roaming\Typora\typora-user-images\image-20221114142848685.png)]
在css Grid布局模块中,只要显式设置了display:grid(或 inline-grid) 就会创建Grid容器和Grid项目,也会自动生成网格线,即行和列(默认为一行一列)。
在没有显式地在Grid容器上设置grid-template-columns和gird-template-rows,浏览器会将Grid容器默认设置为Grid内容的大小:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-otJStpat-1668419176804)(C:\Users\zheng_mingzhuo\AppData\Roaming\Typora\typora-user-images\image-20221114143201715.png)]
这种方法也适用于CSS Grid容器中有多个子元素,比如:
<!-- HTML -->
<div class="grid__container">
<div class="avatar">:)</div>
<div class="media__heading"></div>
<div class="media__content"></div>
<div class="action"></div>
</div>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lI86Dkfj-1668419176805)(C:\Users\zheng_mingzhuo\AppData\Roaming\Typora\typora-user-images\image-20221114143449657.png)]
而且place-items适用于每个单元格。这意味着它将居中单元格的内容。比如下面这个示例:
<!-- HTML -->
<div class="grid__container">
<div class="grid__item">
<h3>Special title treatment</h3>
<p>
With supporting text below as a natural lead-in to additional content.
</p>
<div class="action">Go somewhere</div>
</div>
<div class="grid__item">
<h3>Special title treatment</h3>
<p>
With supporting text below as a natural lead-in to additional content.
</p>
<div class="action">Go somewhere</div>
</div>
</div>
<style>
body{
background-color: #7be78e;
}
/* CSS */
.grid__container {
display: grid;
place-items: center;
width: 80%;
margin: auto;
grid-template-columns: repeat(2, 1fr);
gap: 20px;
}
.grid__item {
display: grid;
place-items: center;
background-color: #d8863b;
padding: 20px;
}
</style>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-28weBeP0-1668419176805)(C:\Users\zheng_mingzhuo\AppData\Roaming\Typora\typora-user-images\image-20221114144352086.png)]
2、等高布局
等高布局也是Web布局中非常常见的一种布局方式,而且实现等高布局的方案也有很多种。这里我们主要来看Flexbox布局模块和Grid布局模块给我们带来了什么样的变化。
在Flexbox和Grid布局模块种,让我们实现等高布局是非常简单的了,比如:
<!-- Flexbox -->
<flex__container>
<flex__item></flex__item>
<flex__item></flex__item>
<flex__item></flex__item>
</flex__container>
/* CSS */
.flex__container {
display: flex; // 或 inline-flex
}
简单地说,在容器上显示设置了display的值为flex或者是inline-flex,该容器的所有子元素的高度都相等,因为容器的align-items的默认值设置为stretch。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EovRwjzt-1668419176806)(C:\Users\zheng_mingzhuo\AppData\Roaming\Typora\typora-user-images\image-20221114150059408.png)]
在Grid布局模块种类似:
<!-- HTML -->
<grid__container>
<grid__item></grid__item>
<grid__item></grid__item>
<grid__item></grid__item>
</grid__container>
/* CSS */
.grid__container {
display: grid;
grid-template-columns: 20vw 1fr 20vw; /* 根据需求调整值*/
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qyVO8uPn-1668419176806)(C:\Users\zheng_mingzhuo\AppData\Roaming\Typora\typora-user-images\image-20221114150233788.png)]
如果需求有所调整,比如在Flex项目或Grid项目的子元素高度和容器高度相同。
<!-- HTML -->
<flex__container>
<flex__item>
<content></content>
</flex__item>
</flex__container>
/* CSS */
.flex__container {
display: flex;
}
.content {
height: 100%
}
// 或
.grid__container {
display: grid;
grid-auto-flow: column;
}
.content {
height: 100%;
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8IBWSqri-1668419176806)(C:\Users\zheng_mingzhuo\AppData\Roaming\Typora\typora-user-images\image-20221114150437318.png)]
3、Sticky Footer
首先用下图来描述什么是Sticky Footer布局效果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VlQDpRj2-1668419176810)(C:\Users\zheng_mingzhuo\AppData\Roaming\Typora\typora-user-images\image-20221114151307415.png)]
Sticky Footer实现方案和等高、垂直居中一样,同样有很多种方案可以实现。
比如下面这种结构:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>css sticky footer</title>
<style>
* {
margin: 0;
}
html, body {
height: 100%;
}
.wrapper {
min-height: 100%;
margin-bottom: -32px;
}
.footer {
height: 32px;
}
.push {
height: 32px;
}
</style>
</head>
<body>
<div class="wrapper">
<div class="content">
<p>内容</p><p>内容</p><p>内容</p><p>内容</p><p>内容</p><p>内容</p><p>内容</p><p>内容</p><p>内容</p><p>内容</p>
<p>内容</p><p>内容</p><p>内容</p><p>内容</p><p>内容</p><p>内容</p><p>内容</p><p>内容</p><p>内容</p><p>内容</p>
<!-- <p>内容</p><p>内容</p><p>内容</p><p>内容</p><p>内容</p><p>内容</p><p>内容</p><p>内容</p><p>内容</p><p>内容</p>
<p>内容</p><p>内容</p><p>内容</p><p>内容</p><p>内容</p><p>内容</p><p>内容</p><p>内容</p><p>内容</p><p>内容</p> -->
</div>
<div class="push"></div>
</div>
<div class="footer" style="background: yellow">footer</div>
</body>
</html>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ygErAhIL-1668419176812)(C:\Users\zheng_mingzhuo\AppData\Roaming\Typora\typora-user-images\image-20221114154045297.png)]
原理分析:
margin为负值的意义:
margin是盒模型的外边距,当为正时,表示盒模型向外扩张,当为负的时候,表示盒模型向内收缩,收缩从而留出的空间可以给外部元素使用。而这部分空间会占据原来盒模型的内边距和内容盒子,所以有可能会影响到盒模型内容。
内容区内容不多时
如果想要页脚始终在视口底部,那么内容区一定要占满视口(但需要留下页脚占据的空间)。要想达到这一步,首先内容区的高度就必须是视口高度的100%(视口可能会调整大小,所以只能用百分数),其次是要通过margin-bottom为负值来给页脚留出出空间。这时候在内容区内容不多时可以达到效果。内容区的高度与设为100%的前提时,其父元素有确定高度才行,所以body和html也需要设为100%(因为html元素是body的父元素,html元素的百分数相对与视口大小)。为了不让页脚遮住内容取得内容,需要在内容区域下方增加一个空白元素,让页脚遮住这个空白元素,所以空白元素高度与页脚一致。
html, body {
height: 100%;
}
.wrapper {
height: 100%;
margin-bottom: -32px;
}
.push {
height: 32px;
}
.footer {
height: 32px;
}
内容区内容很多超过视口高度
此时出现滚动条,页脚在视口底部,会遮住内容区的。因此我们需要将内容区域的高度增加,这个时候应该让内容区的高度随着内容的高度自动增加,所以不能再使用height属性了,我们使用min-height属性来解决这个问题。
4、均分列
在web布局中,很多时候会对列做均分布局,最为常见的就是在移动端底部的bar,比如下图这样的一个效果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-h8YweWSv-1668419176812)(C:\Users\zheng_mingzhuo\AppData\Roaming\Typora\typora-user-images\image-20221114164433536.png)]
在Flexbox和Grid还没出现之前,如果真正的做到均分效果,可以用100% (或者是100vw)除以具体的列数。比如:
<!-- HTML -->
<container>
<column></column>
<column></column>
<column></column>
</container>
/* CCSS */
.container {
inline-size: 50vw;
min-inline-size: 320px;
display: flex-row;
}
.column {
float: left;
width: calc(100% / 3);
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8LYrSntQ-1668419176812)(C:\Users\zheng_mingzhuo\AppData\Roaming\Typora\typora-user-images\image-20221114164731050.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3ho01y82-1668419176813)(C:\Users\zheng_mingzhuo\AppData\Roaming\Typora\typora-user-images\image-20221114164745448.png)]
在Flexbox和Grid布局中,实现上面的效果会变得容易很多。先来看下FlexBox中的布局:
<!-- HTML -->
<flex__container>
<flex__item></flex__item>
<flex__item></flex__item>
<flex__item></flex__item>
</flex__container>
/* CSS */
.flex__container {
inline-size: 50vw;
display: flex;
}
.flex__item {
flex: 1;
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xxxmChlx-1668419176813)(C:\Users\zheng_mingzhuo\AppData\Roaming\Typora\typora-user-images\image-20221114165045727.png)]
在Flexbox布局模块中,当flex取得值是一个单值(无单位的数),比如示例中的flex:1,它会当作显示地设置了flex-grow:1.浏览器计算出来的flex:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tXSDzSEV-1668419176813)(C:\Users\zheng_mingzhuo\AppData\Roaming\Typora\typora-user-images\image-20221114165207746.png)]
接下来看Grid中如何实现上例的效果:
<!-- HTML -->
<grid__container>
<grid__item></grid__item>
<grid__item></grid__item>
<grid__item></grid__item>
</grid__container>
/* CSS */
.grid__container {
display: grid;
grid-template-columns: repeat(3, 1fr); /*这里的3表示具体的列数*/
}
最终的效果是相同的:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Hf9uqjYD-1668419176814)(C:\Users\zheng_mingzhuo\AppData\Roaming\Typora\typora-user-images\image-20221114165615651.png)]
这样的布局方式也适用于其他的布局中。但不管是flexbox还是Grid布局中,都存在一定的缺陷,当容器没有足够的空间容纳Flex项目(或Grid项目)时,Flex项目或Grid项目会溢出(或隐藏,如果Flex容器或Grid显式设置了overflow:hidden):
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6RdoY6XZ-1668419176814)(C:\Users\zheng_mingzhuo\AppData\Roaming\Typora\typora-user-images\image-20221114165944489.png)]
修复这种现象最简单的方式是在Flex容器或Grid容器显式地设置一个min-width(或min-inline-size)
.flex__container {
min-inline-size: 300px;
}
不过话又说回来,比如我们的Flex项目(或Grid项目)是一个卡片,每张卡片宽度是相等之外,更希望容器没有足够空间时,Flex项目(或Grid项目)会自动断行排列。
我们继续通过示例向大家展示。先来看Flexbox实现方案:
.flex__container {
display: flex;
flex-wrap: wrap;
}
.flex__item {
flex: 0 1 calc((100vw - 18vh) / 4); /* calc(100vw -18vh) / 4 是flex-basis的基准值 */
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3AH7CKCD-1668419176815)(C:\Users\zheng_mingzhuo\AppData\Roaming\Typora\typora-user-images\image-20221114170416295.png)]
你可以尝试着调整浏览器的视窗宽度,当浏览器的视窗越来越小时,Flex容器宽度也就会越来越小,当Flex容器小到没有足够的空间容纳四个Flex项目(就此例而言),那么Flex项目就会断行排列:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-REcJue7I-1668419176815)(C:\Users\zheng_mingzhuo\AppData\Roaming\Typora\typora-user-images\image-20221114170514659.png)]
基于该例,如果把Flex项目的 flex 值改成:
.flex__item {
flex: 0 0 400px;
}
这个时候,当Flex容器没有足够空间时,Flex项目会按 flex-basis: 400px 计算其宽度,Flex容器没有足够空间时,Flex就会断行:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-adZQsSUf-1668419176815)(C:\Users\zheng_mingzhuo\AppData\Roaming\Typora\typora-user-images\image-20221114170550995.png)]
反过来,如果Flex项目的值 flex 改成:
.flex__item {
flex: 1 0 400px;
}
当Flex容器没有足够空间排列Flex项目时,Flex项目会按 flex-basis: 400px 计算其宽度,Flex会断行,并且同一行出现剩余空间时,Flex项目会扩展,占满整个Flex容器:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qav03B1O-1668419176816)(C:\Users\zheng_mingzhuo\AppData\Roaming\Typora\typora-user-images\image-20221114170650027.png)]
在Grid中实现类似的效果要更复杂一点,可以使用repeat()函数,1fr以及auto-fit等特性:
.grid__container {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 2vh;
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mtX3QyK3-1668419176816)(C:\Users\zheng_mingzhuo\AppData\Roaming\Typora\typora-user-images\image-20221114170837378.png)]
其实在Grid中与 auto-fit 对比的值还有一个叫 auto-fill。但两者的差异是非常地大,用下图来描述 auto-fit 和 auto-fill 的差异:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MJqLF1sJ-1668419176817)(C:\Users\zheng_mingzhuo\AppData\Roaming\Typora\typora-user-images\image-20221114171436645.png)]
5、圣杯布局
圣杯布局时Web中典型的布局模式。看上去像下图这样:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FmRDRzde-1668419176817)(C:\Users\zheng_mingzhuo\AppData\Roaming\Typora\typora-user-images\image-20221114171649888.png)]
对于圣杯布局而言,html结构是有一定的要求,那就是内容为先:
<!-- HTML -->
<header></header>
<main>
<article></article> <!-- 主内容 -->
<nav></nav>
<aside></aside>
</main>
<footer></footer>
在这里主要还是和大家一起探讨,如何使用Flexbox和Grid布局模块来实现神隔壁布局。先来看Flexbox实现方案:
body {
width: 100vw;
display: flex;
flex-direction: column;
}
main {
flex: 1;
min-height: 0;
display: flex;
align-items: stretch;
width: 100%;
}
footer {
margin-top: auto;
}
nav {
width: 220px;
order: -1;
}
article {
flex: 1;
}
aside {
width: 220px;
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BMwQBGQC-1668419176818)(C:\Users\zheng_mingzhuo\AppData\Roaming\Typora\typora-user-images\image-20221114171915349.png)]
通过在 nav、aside 和 article 上显式设置 order 的值,可以很好的控制这三个区域的布局顺序。比如说,希望 在 之前排列,只需要在上面的示例基础上做一点点调整:
nav {
order: 0;
}
aside {
order: -1;
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SGzXxVXC-1668419176818)(C:\Users\zheng_mingzhuo\AppData\Roaming\Typora\typora-user-images\image-20221114172122309.png)]
注意,order的默认值为0,值越大越排在后面!
在上例的基础上,借助CSS媒体对象的特性,可以很容易实现响应式的圣杯布局效果:
@media screen and (max-width: 800px) {
main {
flex-direction: column;
}
nav, aside {
width: 100%;
}
}
在Grid布局模块中,实现圣杯布局要比Flexbox布局模块中更容易,而且更灵活。在CSS Grid布局模块中,HTML结构可以更简洁:
<!-- HTML -->
<body>
<header></header>
<main></main>
<nav></nav>
<aside></aside>
<footer></footer>
</body>
在CSS方面有很多种方案可以实现圣杯布局效果。我们先来看第一种:
body {
display: grid;
grid-template: auto 1fr auto / 220px 1fr 220px;
}
header {
grid-column: 1 / 4;
}
main {
grid-column: 2 / 3;
grid-row: 2 / 3;
}
nav {
grid-column: 1 / 2;
grid-row: 2 / 3;
}
aside {
grid-column: 3 / 4;
grid-row: 2 / 3;
}
footer {
grid-column: 1 / 4;
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HhCW0nWH-1668419176819)(C:\Users\zheng_mingzhuo\AppData\Roaming\Typora\typora-user-images\image-20221114172338587.png)]
和Flexbox布局类似,在媒体查询中可以改变每个网格区域的位置:
@media screen and (max-width: 800px) {
body {
grid-template-rows: auto;
grid-template-columns: auto;
}
header,
main,
nav,
aside,
footer {
grid-column: 1 / 2;
min-height: auto;
}
main {
grid-row: 3 / 4;
margin: 0;
}
nav {
grid-row: 2 / 3;
}
aside {
grid-row: 4 / 5;
}
footer {
grid-row: 5 / 6;
}
}
6、12列网格布局
7、 两端对齐
在Web布局中时常碰到两端对齐的需求。在Flexbox布局中,时常在Flex容器中显式设置 justify-content 的值:
.flex__container {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
width: 100%;
}
但在末尾行,如果和前面行的个数不相同(Flex项目)就会出现下图这样的效果:
像上图这样的效果,并不是我们所需要的,因为我们希望在最后一行的Flex项目不足够排列满一行时,希望Flex项目一个紧挨一个的排列:
在Flexbox要实现上图这样的效果,只需要在Flex容器中添加一个伪元素:
.flex__container::after {
content: "";
display: flex;
flex: 0 1 32vw;
}
注意,伪元素的 flex-basis 建议设置的和卡片的 flex-basis(或宽度)等同。这个时候你将看到像下面这样的示例:
不过这种方式也不是最佳的方式,当末尾行的个数不只少一个时,就会出现下图这样的效果:
面对这样的场景,我们需要给Flex容器添加额外的空标签元素:
占位符元素数量 = 每行最大的列数 - 2
但是 gap属性出现之后,要实现这样的效果就不难了:
body {
padding: 1vh;
}
.flex__container {
display: flex;
flex-wrap: wrap;
gap: 2vh;
width: 100%;
}
.flex__item {
flex: 0 1 calc((100vw - 8vh) / 4);
}
效果如下:
注意,gap 运用在Flexbox中到目前为止,仅得到了Firefox浏览器的支持。上面的示例,使用Firefox浏览器,你看到的效果如下:
在CSS Grid布局中,就可以直接使用 gap:
body {
padding: 1vh;
}
.grid__container {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 1vh;
}
效果如下:
8、 选择最佳的值
很多时候,针对不同的场景,设计师会为我们提供不同的设计风格,比如元素大小:
随着 clam() 函数的到来,这一切都变得容易地多。
clam() 函数接受三个参数,即 clam(MIN, VAL, MAX),其中 MIN 表示最小值,VAL 表示首选值,MAX 表示最大值。它们之间:
- 如果 VAL 在 MIN 和 MAX 之间,则使用 VAL 作为函数的返回值。
- 如果 VAL 大于 MAX,则使用 MAX 作为函数的返回值。
- 如果 VAL 小于 MIN,则使用 MIN 作为函数的返回值。
我们来看一个示例:
.element {
/**
* MIN = 100px
* VAL = 50vw ➜ 根据视窗的宽度计算
* MAX = 500px
**/
width: clamp(100px, 50vw, 500px);
}
比如浏览器视窗现在所处的位置是1200px的宽度,那么 .element 渲染的结果如下:
这个时候 .element 元素的 width 是 500px。此时,clamp(100px, 50vw, 500px) 相当于 clamp(100px, 600px, 500px),对应的 VAL 值是 600px,大于 MAX 值,那么这个时候 clamp() 函数返回的值是 MAX,即 500px,这个时候 .element 的 width 值就是 500px(即 MAX 的值)。
如果我们把浏览器视窗缩小至 760px:
这个时候 .element 元素的 width 是 50vw。此时,clamp(100px, 50vw, 500px) 相当于clamp(100px, 380px, 500px),对应的 VAL 值是 380px,该值大于 MIN 值(100px),小于 MAX 值(500px),那么这个时候 clamp() 函数返回的值是 VAL,即 50vw,这个时候 .element 的 width 值就是 50vw(即 VAL 的值)。
如果继续将浏览器的视窗缩小至 170px:
这个时候 .element 元素的 width 是 100px。此时,clamp(100px, 50vw, 500px) 相当于 clamp(100px, 85px, 500px),对应的 VAL 值是 85px,该值小于 MIN 值(100px),那么这个时候 clamp() 函数返回的值是 MIN,即 100px,这个时候 .element 的 width 值就是 100px(即 MIN 的值)。
就该示例而言,clamp(100px, 50vw, 500px) 还可以这样来理解:
- 元素 .element 的宽度不会小于 100px(有点类似于元素设置了 min-width: 100px)。
- 元素 .element 的宽度不会大于 500px(有点类似于元素设置了 max-width: 500px)。
- 首选值 VAL 为 50vw,只有当视窗的宽度大于 200px 且小于 1000px 时才会有效,即元素 .element 的宽度为 50vw(有点类似于元素设置了 width:50vw)。
9、Logo图标的对其
我想你在Web开发中可能碰到过类似下图的这样的场景:
正像上图所示,Logo图像的有大有小(宽度和高度都不一样)。面对这样的业务场景,很多时候都希望设计师能提供相同尺寸的图像。但这样势必会影响Logo图像的外观。
前段时间看到@Ahmad Shadeed专门写了一篇博文《Aligning Logo Images in CSS》,就是介绍如何实现上图这样的布局效果。
其实实现这样的布局效果,主要运用到的就是CSS的 object-fit 属性,而这个属性早在多年前就得到了各大主流浏览器的支持。
这里我们用一个简单的示例,来看看具体实现过程。先来看HTML结构:
<!-- HTML -->
<ul class="brands">
<li class="brands__item">
<a href="#">
<img src="img/logo.png" alt="">
</a>
</li>
<li> <!-- ... --> </li>
</ul>
居中对齐前面已经介绍过了,这里主要是看图像大小方面的处理:
.brands {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
grid-gap: 1rem;
}
.brands__item {
background: #eee;
}
.brands__item a {
display: flex;
justify-content: center;
align-items: center;
height: 100%;
}
.brands__item img {
width: 130px;
height: 75px;
object-fit: contain;
}
这样就能实现上图的效果。你可能发现了,有些Logo图像带有背景颜色,如果让效果更好一些,可以把CSS混合模式相关的特性运用进来:
.brands__item img {
width: 130px;
height: 75px;
object-fit: contain;
mix-blend-mode: multiply;
}
这个时候,你看到的效果如下:
object-fit 除了取值 contain 之外,还有其他几个值:
其实这个方案也适用于产品图片,人物头像等布局。