
CSS3 变换和过渡
上一章我们介绍了盒子模型和布局相关知识点,并且为大家扩展了更多类型的选择器,帮助我们更好地调整页面样式。这一章我们将继续深入介绍CSS3的更多内容,比如二维、三维变换、函数等。
盒子模型进阶
上一章我们介绍了盒子模型,这一章我们接着介绍盒子模型中一些更加高级的用法。
最大宽度和最小宽度
在常规的width和height之外,CSS还提供了最大/最小宽度和高度的设置,这在响应式布局中非常有用,可以防止元素在不同尺寸的屏幕下变得过宽或过窄。
max-width: 设置元素的最大宽度。当内容或浏览器窗口宽度小于max-width时,元素的宽度会自适应;但当其试图超过max-width时,宽度将被限制在这个最大值。min-width: 设置元素的最小宽度。即使内容很少,元素的宽度也不会低于这个值。max-height: 设置元素的最大高度。min-height: 设置元素的最小高度。
比如我们希望盒子的宽度始终保持为父元素宽度的80%,但是最大不能超过500px最小不能低于320px,此时我们就可以使用上面提到的几个属性:
.container {
width: 80%; /* 宽度为父元素的80% */
max-width: 500px; /* 但最大不超过500px */
min-width: 320px; /* 最小不低于320px */
margin: 0 auto; /* 在大屏幕上水平居中 */
}
可以看到,当盒子的宽度超过设定的最大值时,就不会继续增加宽度了:

这种用法在很多时候都是非常实用的,我们的网站内容不可能跟随页面的宽度无限增加,否则其中的内容会变形得越来越奇怪,一般常见的网站都会设置一个最大的页面宽度来保证内容不会过度变形,一旦浏览器窗口超出最大限度,页面会自动居中并留出两边的空间:

注意,如果我们要设置盒子的固定大小,请正常使用之前的width和height属性,最大最小宽度虽然在某些情况下能够和普通的宽度效果一致,但是难免会存在特殊情况。
盒子轮廓
轮廓(outline)是绘制在元素border(边框)之外的一条线,用于突出元素。它与边框非常相似,但有几个关键区别:
- 不占据空间:轮廓是在元素之上绘制的,不会影响元素的尺寸或布局,它不是盒子模型的一部分,仅仅只是装饰,因此不会增加元素的总宽度或总高度。
- 在盒子的边框外进行绘制:轮廓是在盒子的边框外进行绘制,不会占用盒子内部的区域,但是可能会遮挡外部的其他元素。
我们可以使用outline属性来控制盒子的轮廓:
.container {
height: 100px;
width: 200px;
background-color: gray;
outline-style: solid; /* 轮廓采用实现绘制,可用的属性和border一样 */
outline-width: 2px; /* 创建一个宽度为2px的轮廓 */
outline-color: black; /* 边框的颜色 */
}

可以看到,此时盒子的边上就出现了一圈轮廓,看起来非常像边框,但是实际上并不是边框,盒子所占据的区域依然是上面设定的宽度。
同样的,如果盒子出现了圆角,那么轮廓也会按照盒子的实际形状展示:

针对于以上三个属性,我们也可以使用边框的简写属性outline一步到位:
outline: 2px solid black;
是不是感觉用起来和边框差不多,当然,轮廓也有一些比较特殊的属性,比如我们可以控制轮廓和盒子边缘的距离:
.container {
height: 100px;
width: 200px;
background-color: gray;
outline: 2px solid black;
outline-offset: 5px; /* 表示边框距离盒子边缘的距离 */
border-radius: 10px;
}

注意这个值可以是负数,负数表示轮廓往盒子里面跑:

实际上我们在之前的学习中,就已经遇到过出现轮廓的情况了,比如input标签,在默认情况下,浏览器用户代理样式会为其添加一个蓝色的轮廓:
<input type="text" placeholder="请输入文本">

我们也可以通过前面学习的伪类来取消掉聚焦状态下的轮廓:
input:focus {
outline: none;
}
盒子阴影
使用 box-shadow 属性可以为元素的框添加阴影效果,这里需要用到几个属性:
box-shadow: offset-x offset-y blur-radius spread-radius color;
这里我们分别介绍一下这些属性有什么用:
- offset-x - 水平方向的偏移,默认情况下阴影在盒子的正下方。
- offset-y - 垂直方向的偏移,默认情况下阴影在盒子的正下方。
- (可选) blur-radius - 模糊半径,值越大,阴影越模糊。
- (可选) spread-radius - 扩展半径,正值使阴影扩大,负值使阴影缩小,不填等于没有阴影。
- color - 阴影的颜色。
比如,下面这个例子就是:
.container {
width: 200px;
height: 100px;
background-color: #d5d5d5;
box-shadow: 0 0 10px gray; /* 这里我们创建了一个模糊半径为10px的灰色阴影 */
}
这里填写 0 0 10px gray 表示创建一个水平和垂直方向上都不偏移,扩展半径为10px的灰色阴影:

注意,阴影和前面介绍的轮廓一样,不会占用盒子空间,但是可能会受到父盒子尺寸的影响,比如下面这种情况:
.outer-box {
width: 220px;
height: 120px;
overflow: hidden; /* 隐藏超出部分 */
}
.container {
width: 200px;
height: 100px;
background-color: #d5d5d5;
box-shadow: 0 0 50px gray; /* 这里我们创建了一个模糊半径为50px的灰色阴影 */
}

当外层盒子的尺寸大小不足以容纳阴影且禁止超出部分显示时,我们的阴影会被截断,然后变得很难看。
当然,除了编写一个阴影之外,我们还可以同时给盒子添加多个阴影:
.container {
width: 200px;
height: 100px;
background-color: #d5d5d5;
box-shadow: /* 多个阴影可以逐行编写,但是注意需要用逗号分割 */
0 -4px 3px rgba(0, 42, 255, 0.12),
0 4px 8px rgba(255, 0, 0, 0.2);
}
此外,阴影既然可以作为外阴影展示,同样的也可以在内侧展示,我们只需要添加一个inset即可表示这是一个内阴影:
.container {
width: 200px;
height: 100px;
background-color: #d5d5d5;
box-shadow: 0 0 10px gray inset; /* 这里我们创建了一个模糊半径为10px的灰色内侧阴影 */
}

阴影和前面介绍的轮廓一样,是跟随盒子的形状进行变化的:

除了将阴影作为一个普通的阴影使用之外,我们也可以使用阴影来解决之前遇到的边框宽度被系统缩放影响的问题。
不同系统的 DPI / 缩放比例,会导致 CSS 的“1px”并不总是等于屏幕上的 1 个物理像素。
.box {
box-shadow: 0 0 0 1px #ccc;
}
这里我们只需要创建一个扩展半径为1px且无模糊半径的阴影即可,它实际的展示效果等价于宽度为1px的边框。
除了盒子可以创建阴影之外,还有一个text-shadow属性,它能实现文字的阴影效果:

可以看到它是在文字的周围增加描边阴影,用法和盒子阴影大致相同。
行内纵向对齐
经过HTML阶段的学习,我们知道,行内元素是可以任意穿插的,我们直接编写的文本内容、a标签、b标签等都算行内元素。包括一些既具有行内元素特性也具有块级元素特性的比如img标签,也能和文本实现穿插效果:
<div class="test">
带回家撒大家卡仕达手机卡三等奖哈三等奖卡仕达酱卡好的卡仕达可接受的
<a href="index.html">点我啊</a>
<img width="120" src="https://img1.baidu.com/it/u=1005000719,311741344&fm=253&fmt=auto&app=138&f=JPEG">
</div>

不过虽然行内元素和行内块元素都可以穿插使用,但是有些时候可能并不是我们想要的效果。比如这里的图片,它展示的位置似乎并不是以文字的底部进行对齐的,看着像是有点漂移的感觉。
这实际上是因为vertical-align属性在控制纵向对齐规则:
.test img {
vertical-align: baseline; /* 默认情况下,行内元素的纵向对齐是baseline */
}
那么什么是baseline呢?这里需要介绍一下vertical-align的几种值:

这里出现了四种对齐方式,分别对应不同的标准线:
- **顶线:**这一行文本行高的顶部,注意不是文字顶部,而是行高的顶部,随行高变化而变化。当行高和文字大小一致时,才是中文文字的顶部(英文文字会小一些)
- **中线:**文字的垂直中心点,也就是小写字母
x的中心交叉位置。 - **基线:**英文小写
x字母的下边缘,设置基线是为了给注入g、j这种带尾巴的字母留出空间。 - **底线:**同顶线,只不过相反,跑到行高的底部去了。
当我们修改行内或行内块元素的vertical-align属性时,会产生如下效果:
baseline- 让行内或行内块元素的底线和文本的基线对齐。top- 让行内或行内块元素的顶线和文本的顶线对齐。bottom- 让行内或行内块元素的底线和文本的底线对齐。middle- 让行内或行内块元素的中线和文本的中线对齐。
注意vertical-align只针对于行内元素或者行内块元素有效,它对于块级元素是无效的。
精灵图
精灵图(也称“雪碧图”)是一种网页图片应用处理方式。它将一个页面涉及到的所有零星图片都包含到一张大图中,然后利用 CSS 的 background-image、background-position 和 width、height 属性来显示大图中的特定部分。
优点:通过将多个图片合并成一张,减少了HTTP请求的数量,从而加快了页面加载速度。
这种用法在计算机发展的早期,很多网页、游戏都喜欢采用,比如早期的微博:

可以看到所有的小图标都被做到了一张图中,这样就可以反复使用同一个背景图,通过定位来选取自己需要的区域。
.vip-icon {
display: inline-block;
width: 40px;
height: 40px;
background-position: -57px 0;
background-image: url("/img/sprites.png");
}

如果网站存在大量的小型图标需要展示,也可以考虑使用这种方式去节省网络资源。
颜色渐变
CSS3 渐变 (gradients) 让你可以在两个或多个指定颜色之间平稳地过渡,实现渐变色效果。渐变色需要使用 background-image 属性来进行设置,列举一些常用的颜色渐变函数:
- 线性渐变 (Linear Gradients):颜色沿着一条直线过渡。
- 径向渐变 (Radial Gradients):颜色从一个中心点向外辐射过渡。
这里我们先来看看最简单的线性渐变:
.container {
width: 300px;
height: 50px;
background-image: linear-gradient(red, yellow); /* 使用红色和黄色进行线性渐变 */
}
默认情况下,颜色渐变方向是从上往下进行渐变:

我们可以添加to right表示采用从左往右的线性渐变:
.container {
width: 300px;
height: 50px;
background-image: linear-gradient(to right, red, yellow);
}

同样的,to bottom right还能实现从左上角斜着渐变到右下角的效果,所有的情况如下:
| 写法 | 含义 |
|---|---|
| to bottom | 上 → 下(默认) |
| to top | 下 → 上 |
| to right | 左 → 右 |
| to left | 右 → 左 |
| to right bottom | 左上 → 右下 |
针对于自定义的角度,我们也可以使用角度单位来定义:
linear-gradient(45deg, red, blue)
我们可以添加多种颜色让渐变看起来更丰富:
background-image: linear-gradient(to right, red, orange, yellow, green, blue, purple);

我们可以自行控制不同颜色占有的比例,比如我们希望红色部分更多一些再进行黄色渐变,我们可以在颜色的后面添加一个百分比,表示颜色延伸的位置:
background-image: linear-gradient(to right, red 80%, yellow);

或是黄色多一些:
background-image: linear-gradient(to right, red, yellow 20%, yellow);

虽然颜色渐变使用的也是background-image属性,但是这并不代表我们就无法使用图片作为背景了,我们可以使用逗号分割不同类型的背景图片:
background:
linear-gradient(rgba(0,0,0,.4), rgba(0,0,0,.4)),
url(bg.jpg);
此外,我们在上一章没有提到,background-clip还支持在盒子模型的指定区域内展示背景图片或渐变效果,比如我们只希望在盒子的内容区域展示渐变颜色,而不作用到边框和内边距上:
.container {
width: 300px;
height: 50px;
padding: 20px;
background:
linear-gradient(to right, red, blue) content-box; /* 表示只有内容盒子变色 */
border: 2px solid gray;
}

此时盒子只有内容区域是渐变色,当然,除了content-box之外,还有padding-box表示只延伸到内边距区域,或是border-box表示完整的整个盒子,利用这种特性,我们就能实现彩色边框:
.container {
width: 300px;
height: 50px;
border-radius: 10px;
background:
linear-gradient(to right, white, white) padding-box, /* pading+内容区域采用白色 */
linear-gradient(to right, red, blue) border-box; /* border+pading+内容区域采用渐变 */
border: 2px solid transparent; /* 注意边框的颜色会覆盖背景,这里弄个透明的 */
}

这样,一个好看的渐变色边框就出现了。
我们接着来看径向渐变,径向渐变是由中心向外发散的渐变效果,比较适合球形盒子:
.container {
width: 200px;
height: 100px;
background-image: radial-gradient(red, yellow);
}

可以看到,径向渐变的颜色是有内而外,并且会以椭圆形样式适应盒子的宽高,我们还可以将渐变背景颜色直接改变为一个标准的圆形:
background-image: radial-gradient(circle, red, yellow);

可以看到,现在渐变变成了标准圆形,但是由于我们的盒子并非一个正方形,导致这个渐变的圆形有一部分像是被遮挡一样,我们可以通过以下参数来调整扩散范围:
| 值 | 含义 |
|---|---|
| closest-side | 到最近边 |
| farthest-side | 到最远边 |
| closest-corner | 到最近角 |
| farthest-corner | 到最远角(默认) |
比如我们希望颜色渐变以最矮的一边为准:
background-image: radial-gradient(circle closest-side, red, yellow);

和线性渐变一样,我们可以使用百分比来控制渐变位置:
background-image: radial-gradient(red 5%, yellow 15%, green 60%);

我们也可以通过at来改变圆的中心点位置,比如我们希望从左上角开始径向渐变:
background-image: radial-gradient(circle at left top, red, yellow);

常见位置写法:
- center
- top / bottom / left / right
- x y(百分比或长度)
我们可以自由编写指定的百分比来控制位置,或是固定位置。
过滤
filter 是 CSS 中用于给元素添加图形处理效果的属性,常见于图片、背景、组件状态、UI 细节增强等场景。你可以把它理解为:在浏览器里对元素做 “PS 后期处理”。
比如现在有一个盒子:
<div class="container">
我是盒子里面的字,看着很漂亮很美丽
</div>
.container {
color: #227fd8;
width: 200px;
height: 100px;
padding: 10px 15px;
border-radius: 10px;
border: 2px solid #5aa9fd;
}

我们可以使用多种滤镜效果,来对盒子进行处理,比如高斯模糊效果,我们可以使用blur效果,它会使得我们的内容变模糊,我们可以自行调整模糊的强度:
.container {
filter: blur(5px); /* 添加高斯模糊滤镜 */
...
}

添加滤镜效果后,相信大家第一眼看到肯定分不清楚到底是自己近视了还是盒子问题。
我们接着来看下一个滤镜,brightness可以控制亮度,亮度越大,盒子的颜色就会变得越亮,亮度越小,盒子的颜色就会变得越灰暗:
.container {
filter: brightness(0.5);
...
}

默认情况下,亮度为1,当我们调整亮度为0.5之后,盒子颜色会变得昏暗,就像是把蓝色调的更黑一样。
我们接着来看下一个,contrast可以调节对比度,对比度越强,颜色展现就越鲜艳,反之颜色就越灰:

在一些特殊日子,常常有些网站喜欢把所有内容都调整为灰白色,以纪念历史上的今天,我们可以使用grayscale属性来控制页面的灰度效果,当调整为100%表示完全变为黑白效果:

类似的还有invert滤镜,它可以使得盒子变为相反的颜色,sepia会为盒子添加复古棕色效果,比较适合一些老照片,柏码官网还用到了hue-rotate效果,它可以将某种颜色整体变换为另一种颜色,以实现多种主题的切换。
此外,drop-shadow滤镜可以为盒子增加投影效果,这个与我们之前提到的box-shadow类似,但是它会根据盒子的具体绘制内容进行投影,而box-shadow只会按照盒子形状进行投影,我们可以对比一下两者:
.container {
/* 参数和box-shadow基本一致 */
filter: drop-shadow(0 0 4px gray);
color: #227fd8;
width: 200px;
height: 100px;
padding: 10px 15px;
border-radius: 10px;
border: 2px solid #5aa9fd;
}


可以看到,普通的盒子阴影只能针对于盒子的边框产生阴影效果,而滤镜则是更细致化的,针对于所有内容的阴影效果,只要是透明背景的区域,都会产生阴影。
以上介绍的滤镜并非只能使用其中一种,我们也可以将多种滤镜组合起来使用,实现更加高级的效果。
有关更多滤镜效果,请参阅:https://developer.mozilla.org/zh-CN/docs/Web/CSS/Reference/Properties/filter
背景过滤器
backdrop-filter 是 CSS 中用于“模糊/处理元素背后内容” 的属性,常见于毛玻璃、半透明浮层、弹窗背景等现代 UI 设计中。它与前面介绍的filter效果差不多,不过,它是作用于其之后的元素,而不是盒子本身。
我们可以来尝试一下:
<div class="card">我是卡片里面的文本</div>
body {
background-repeat: no-repeat;
background-size: cover;
background-image: url("https://img0.baidu.com/it/u=4012604816,607436490&fm=253&app=138&f=JPEG?w=889&h=500");
}
.card {
width: 150px;
height: 200px;
padding: 10px 15px;
border-radius: 15px;
background-color: #ffffff60;
backdrop-filter: blur(12px); /* 添加高斯模糊效果 */
}

可以看到,此时被盒子遮挡的背景部分,变成了高斯模糊效果。同样的,我们也可以试试看其他滤镜效果,比如灰度:

backdrop-filter 支持的函数和 filter 基本一致,这里各位可以自行尝试。
二维和三维变换
在 CSS3 中,transform 属性允许我们在不改变文档流的情况下,对元素进行移动、旋转、缩放和倾斜。这不仅能改变元素的外观,配合过渡和动画还能制作出丰富的交互效果。这一部分,我们就来研究一下transform的使用。