主题
Filter 滤镜与WEB 字体(Day13 4/4)
本页对应 Day13_CSS3,共 6 段视频,约 1 小时 3 分。
学习目标
- 能使用
radial-gradient()编写径向渐变,正确设置圆心、半径和颜色位置,并说明其常见适用场景。 - 能使用
repeating-linear-gradient()或repeating-radial-gradient()实现重复渐变纹理,如笔记本横线效果,并正确补全起始颜色位置。 - 能使用
filter的blur()与grayscale()实现图片模糊、悬停变清晰及整页灰度效果,并解释常用参数含义。 - 能通过
@font-face引入外部字体文件并在元素上应用,说明 Web 字体的工作原理及中文字体文件体积过大的问题。 - 能使用字体定制工具生成仅包含所需字符的字体文件,并将其正确引入页面应用。
- 能使用阿里图标库的 Unicode 字符方式和
iconfont类名方式显示图标,并通过 CSS 调整图标字体的大小和颜色。
知识点
为什么需要滤镜
滤镜这个词,本来是图像处理软件里的专业术语——调亮度、调对比度、加模糊、转灰度,都是修图时干的事。CSS 把这一套搬进了浏览器,用一条 filter 属性就能对元素做整体处理。
对开发者来说,滤镜函数虽然多,但真正常用的只有两个:模糊和灰度。模糊适合做“默认模糊、鼠标移上去变清晰”的图片效果;灰度适合在重大纪念日让整站变灰——一行代码就能搞定,不用设计师重新出一套图。剩下的函数更像是“闲着没事玩一玩”,实际项目里很少让前端自己去调对比度、调色相,那本来就是设计师把图做好再交给你的活。
filter 的基本写法
filter 是一个属性,值是“滤镜函数(参数)”的形式:
css
filter: 滤镜函数(参数);理解它的关键有两点:第一,函数名后面必须跟小括号,参数写在小括号里;第二,滤镜作用于整个元素,不管是图片还是文字,都会被一起处理。转写稿里演示给 body 加灰度时特别强调:“甭管是图片还是文字,都是灰的”——这就是整体作用的体现。
常用滤镜函数一览
| 滤镜函数 | 描述 |
|---|---|
| blur() | 设置模糊,值是长度,值越大越模糊,百分比无效。 |
| brightness() | 设置亮度,值是数字或者百分比,0全黑,1无效果,可以比1大,默认1。 |
| saturate() | 设置饱和度,值是数字或者百分比,0完全不包含,1无效果,可以比1大,默认1。 |
| contrast() | 设置对比度,值是0~1之间的数字或者百分比,0全灰,1无效果,可以比1大,默认1。 |
| grayscale() | 设置灰度,使用0~1之间的数字或百分比,值越大灰度越高,0无效果,1灰度最高,默认0 |
| sepia() | 设置深褐色度,使用0~1之间的数字或百分比,值越大深褐色度越高,0无效果,1深褐色最高,默认0 |
| hue-rotate() | 设置色相旋转,值是0~360deg之间的角度 |
| invert() | 设置反转,使用0~1之间的数字或百分比,0无效果,1彻底反转,默认0 |
| opacity() | 设置不透明度,使用0~1之间的数字或百分比,0完全透明,1完全不透明,默认1 |
| drop-shadow() | 设置阴影,需要设置偏移位置、模糊值、颜色 |
| url() | 使用svg设置滤镜 |
需要说明的是:笔记原表里 opacity() 那一行把 0 和 1 的效果写反了,sepia() 的“1灰度最高”也应是“深褐色最高”,上面表格已按实际效果更正。
blur():模糊
怎么想:模糊的本质是让像素互相“晕开”,所以参数必须是一个长度,值越大晕得越厉害。百分比对它无效,因为百分比没法换算成“晕开多少距离”。
怎么做:新建 01滤镜.html,写一个 h1 写“滤镜”两个字,再用 img 引入一张图:
css
img {
width: 400px;
filter: blur(2px);
}刷新后图片就糊了。转写稿里试过:“写个一像素啊,其实就挺模糊的”“你要敢写个 100 像素,模糊死你,都看不出来是个图了”。也可以写小数,比如 0.2、0.8,按需要微调。
易错点:单位不能丢;数值不要贪大,超过原图细节能承受的范围就成了一团色块。
用 hover 做“模糊变清晰”
为什么需要:图片默认模糊、鼠标放上去变清晰,是模糊滤镜最典型的用法。
怎么做:在 :hover 里把模糊值改成 0:
css
img:hover {
filter: blur(0);
}转写稿的演示效果是“本来不清晰,鼠标一放就清了”。注意 :hover 里要重新写完整的 filter 声明,而不是只改一个数字。
brightness()、saturate()、contrast()
这三个函数的默认值都是 100%,小于 100% 是“减弱”,大于 100% 是“增强”,可以超过 1。转写稿的描述很直观:亮度低于 100% 会暗、高于 100% 会更亮;饱和度低于 100% 颜色变淡、高于 100% 颜色更鲜艳;对比度低的时候“灰蒙蒙的”,对比度高的时候“字儿都凸得很明显”。
grayscale():灰度
为什么需要:重大纪念日整站变灰,是灰度滤镜最现实的用途。
怎么做:先写一段带渐变背景的文字做对照:
css
p {
width: 600px;
padding: 20px;
background: linear-gradient(90deg, red 50%, #009 50%);
color: #fff;
}此时页面里图片和文字颜色都很鲜艳。然后给 body 加一句:
css
body {
filter: grayscale(100%);
}刷新后整页全灰。转写稿的原话是“一行代码就搞定”。
易错点:grayscale() 默认值是 0(无效果),100% 才是顶格灰;写成 1 和 100% 等价,但别写成 100(无单位)以外的奇怪值。
其余函数速览
sepia() 和灰度类似,只是最高值变成褐色;invert() 像底片,颜色整个反过来;hue-rotate() 按角度旋转色相,红的能转成绿的;opacity() 控制不透明度;drop-shadow() 做阴影,需要偏移、模糊值、颜色;url() 则挂载 SVG 滤镜,是这些里最高级的一种形式,转写稿里那几个“鼠标一放变清晰”的复杂案例就是用它做的。
易错点汇总
第一,blur() 只认长度,百分比无效,且值过大会糊到认不出图。第二,亮度、饱和度、对比度的基准是 100%,不是 1,虽然写 1 也等价。第三,opacity() 的 0 和 1 别记反:1 是完全不透明,0 是完全透明。第四,滤镜作用在整个元素上,给 body 加就是全页生效,调试时先确认你加在了哪一层。第五,实际项目里优先掌握 blur() 和 grayscale() 这两个,其余函数知道名字、查得到用法即可,不必死记。
这一节到底在解决什么问题
普通 font-family 只能使用“用户电脑上已经安装的字体”。如果客户端没有这个字体,CSS 写了也白写。Web 字体的思路是:把字体文件放到服务器或网络上,在 CSS 里通过 @font-face 告诉浏览器“字体文件在哪里、这个字体叫什么名字”,然后在元素上用 font-family 使用它。这样用户不需要提前安装字体。转写稿里反复强调的核心就是:先定义字体,再使用字体。
用 @font-face 引入 Web 字体
为什么需要:字体文件不是图片,不能直接写 background-image;必须先用 @font-face 注册。怎么想:font-family 后面的名字是“我们自己起的名字”,可以和原字体名无关;src 才是字体文件真实地址。怎么做:把转写稿中的操作整理成下面结构。
css
@font-face {
font-family: "小乐体";
src: url("./fonts/xxx.woff2") format("woff2"),
url("./fonts/xxx.woff") format("woff"),
url("./fonts/xxx.ttf") format("truetype");
}
.book {
font-family: "小乐体", sans-serif;
}转写稿中演示了多个格式:EOT、WOFF、TTF 等,主要是为了兼容不同浏览器;现在常见项目不必记一堆格式,直接使用工具生成的 CSS 即可。易错点:src 路径必须改对;font-family 的名字要和后面使用时一致;不要以为定义了 @font-face 就自动生效,还要给具体元素设置 font-family。
中文 Web 字体为什么容易“拖慢网页”
转写稿里用了一个很关键的对比:英文字体只需设计 26 个字母、大小写和标点,文件通常不大;中文字体要设计大量汉字,文件可能达到几 MB 甚至十几 MB。演示中强制刷新后字体迟迟不出现,就是在下载大字体文件。结论不是“Web 字体不能用”,而是:中文整站大规模使用 Web 字体要谨慎。易错点:不要拿一个很大的中文字体文件直接给整站用;不要只看本地缓存下很快,要强制刷新观察真实加载。
定制字体:只做标题需要的几个字
为什么需要:整站中文字体太大,但标题可能只有几个字。怎么想:如果字体文件里只包含标题用到的字,体积就会很小。转写稿中定制“小乐的交友网站”这类标题,生成的文件只有几 KB。怎么做:用定制字体工具选择字体、输入需要的文字、生成并下载,再按 @font-face 引入,给 h1 设置 font-family。易错点:这个字体文件只包含定制过的字,段落里写其他字不会生效;转写稿中演示“乐”能显示、其他字不行,就是这个原因。调试时要先确认“这个字是否在字体文件里”。
阿里图标:本质是“把图标做成字体”
为什么需要:小图标用图片放大会失真,改颜色也不方便;图标字体本质还是文字,可以放大不失真,也能用 color、font-size 控制。怎么做:转写稿演示了两种方式。第一种是 Unicode 方式:引入字体文件,定义 .iconfont,在元素里放 demo 给出的特殊字符。
css
@font-face {
font-family: "iconfont";
src: url("./source/iconfont/iconfont.ttf") format("truetype");
}
.iconfont {
font-family: "iconfont";
font-style: normal;
}html
<span class="iconfont"><!-- 这里放 demo 中复制的特殊字符 --></span>第二种是类名方式:直接引入下载包里的 iconfont.css,然后写两个类名。
html
<link rel="stylesheet" href="./source/iconfont/iconfont.css">
<span class="iconfont icon-图标名"></span>易错点:路径要按自己项目改;类名以下载包 demo 为准;转写稿中 font-size 不生效,是因为选择器权重不如图标库里的类名,需要提高选择器权重。i 标签常被拿来放图标,但它本身没有图标语义,只是开发者觉得像 icon 的首字母;更稳妥的是用行内元素并配合类名。
调试时先怀疑什么
转写稿里的排错过程很有代表性:路径写错、引号写到外面、阿里字体地址少了冒号、复制代码后没有改本地路径、选择器权重不够。遇到“字体没生效”时,按顺序查:@font-face 是否定义、src 是否 200、名字是否一致、元素是否设置 font-family、字体文件是否包含目标文字、样式是否被更高权重覆盖。这样比盯着页面发呆有效。
作业说明与拆解
本节笔记只有两条作业:1. 渐变文字;2. 发廊灯 黑白条纹。转写稿里对应的核心知识是“渐变是背景图像,不是颜色”和“重复线性渐变”。下面把两条作业分别拆成:为什么需要 → 怎么想 → 怎么做 → 易错点。笔记里没有配图和现成代码,下面补的是可直接运行的最小示例代码。
作业一:渐变文字
为什么需要 普通文字颜色只能用 color 设一个纯色,做不出从红到蓝、从亮到暗的过渡。设计师给标题做渐变时,如果直接截图当图片,改字、改大小、改颜色都不方便,放大还可能失真。用代码做渐变文字,文字仍是文字,样式可调。
怎么想 转写稿提醒:渐变本身是一个背景图像,不是颜色;要把这个背景图像“只显示在文字上”。思路就是:先给文字元素铺一张渐变背景图,再把背景裁剪到文字形状里,最后让文字本身透明,露出下面的渐变。也就是说,不是给 color 写渐变,而是“背景渐变 + 文字透明”。
怎么做 给标题加线性渐变背景,并用 background-clip: text 裁剪到文字;同时加 -webkit-background-clip: text 兼容,color: transparent 让文字透明。
html
<h1 class="gradient-text">渐变文字作业</h1>css
.gradient-text {
font-size: 64px;
font-weight: 700;
background-image: linear-gradient(90deg, #ff0000, #0000ff);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
}易错点
- 只写
background-image不写background-clip: text,看到的是整块矩形背景,不是文字渐变。 - 忘记
color: transparent,文字颜色会盖住背景,看起来“没效果”。 - 把渐变写到
color上,例如color: linear-gradient(...),这是无效的,因为color不接受渐变图像。 - 选择器权重不够时,标题原有颜色可能覆盖透明色;调试时先检查最终生效样式。
- 多行文字、行高很小时,背景裁剪范围要配合
line-height和padding调整,否则边缘可能被裁掉。
作业二:发廊灯 黑白条纹
为什么需要 发廊灯是典型重复条纹:黑、白、黑、白不断循环。如果每条都切图片,文件多、改颜色麻烦、放大还可能糊。用重复线性渐变可以用一行 CSS 画出条纹,颜色、宽度、角度都能改。转写稿也明确说:发廊灯“其实就是红白条纹、黑白条纹,也是用重复渐变做的”,鼠标放上会动的效果先不做,本次先做静态。
怎么想 不要一上来写很多条。先想“一个循环单元”:一条黑段 + 一条白段。然后用 repeating-linear-gradient() 让这个单元不断重复。转写稿在做笔记本格子时反复强调:重复渐变要写清楚色标起止,例如 0 到 29 是纯白,29 到 30 才过渡到黑;并且前面要加 repeating-,否则只渐变一次,后面就纯色了。发廊灯同理:每段条纹要有明确起点和终点。
怎么做 做一个长条容器,用 45 度重复线性渐变,黑色 0–20px,白色 20–40px,就会循环出黑白斜条纹。
html
<div class="barber-pole"></div>css
.barber-pole {
width: 120px;
height: 360px;
border-radius: 12px;
background-image: repeating-linear-gradient(
45deg,
#000 0 20px,
#fff 20px 40px
);
}如果要做成横向发廊灯,把角度改成 90deg 或 0deg,再调整宽高即可。转写稿里“鼠标放上去会动”属于后续动画内容,本次作业先交静态版本。
易错点
- 写成
linear-gradient()而不是repeating-linear-gradient(),只会出现一段渐变,不会循环。 - 色标只写一个位置,例如
#000 20px, #fff 40px,中间会产生过渡,条纹边缘发虚;要写成#000 0 20px、#fff 20px 40px这种“起止都明确”的写法。 - 角度和尺寸不匹配,条纹会太密或太疏;先固定
20px/40px调通,再改大小。 - 容器没有宽高时背景不显示,误以为渐变没生效。
- 忘记本节只要求静态,先不要被“会动”带偏;把重复渐变写对再谈动画。
提交前检查
渐变文字重点检查三件套:background-image、background-clip: text、color: transparent。发廊灯重点检查:repeating- 前缀、每段色标的起止位置、容器宽高。两条作业都不需要图片素材,能直接用 CSS 完成;如果调试没效果,先看选择器权重和属性拼写,再检查浏览器最终计算样式。
课堂画面






代码示例
示例一:filter 滤镜(模糊 + 灰度)
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>滤镜</title>
<style>
h1 { font-size: 32px; }
/* 图片默认是模糊的 */
.pic {
width: 400px;
filter: blur(2px); /* 值是长度,值越大越模糊 */
transition: filter .3s;
}
/* 鼠标移上去变清晰:用 0 覆盖掉原来的模糊值 */
.pic:hover {
filter: blur(0);
}
/* 一段鲜艳的文字,方便对比灰度效果 */
.txt {
width: 600px;
padding: 20px;
color: #fff;
background-image: linear-gradient(90deg, #f00 50%, #009 50%);
}
/* 重大纪念日:给 body 加灰度,整页一行代码全灰 */
body {
/* filter: grayscale(100%); */
}
</style>
</head>
<body>
<h1>滤镜</h1>
<img class="pic" src="./images/bg04.jpg" alt="">
<p class="txt">这是一段文字,颜色挺鲜艳的,方便对比灰度效果。</p>
</body>
</html>要点解释 / 易错点
filter是属性,值必须写成“滤镜函数(参数)”的形式,如blur(2px)、grayscale(100%),函数名后的小括号不能省。blur()的参数只能是长度,写百分比无效;值越大越模糊,写100px会糊到看不出原图。grayscale()、saturate()、contrast()、sepia()、invert()、opacity()这类默认值都是 0 或 1(或 100%),可以写数字也可以写百分比,允许超过 1。hue-rotate()的参数是角度(0~360deg),不是数字。- 用
:hover让模糊变清晰,关键是写blur(0)把原值覆盖掉,而不是不写。 grayscale(100%)加在body上,图片和文字会一起变灰——这就是纪念日全站变灰的常用做法。- 实际开发中用得最多的就两个:
blur()和grayscale(),其余太专业,了解即可。
示例二:repeating-linear-gradient 做笔记本格子
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>重复渐变 - 笔记本格子</title>
<style>
* { margin: 0; padding: 0; }
.book {
width: 600px;
height: 1000px;
margin: 20px auto;
border: 1px solid #ccc;
box-shadow: 0 0 10px #999;
padding: 20px;
/* 默认方向就是从上到下,可省略方向;重复渐变必须写起始位置 0 */
background: repeating-linear-gradient(
#fff 0,
#fff 29px,
#999 30px
) content-box; /* 一个值同时设置 origin 和 clip */
}
/* 让段落正好压在格子上:行高 = 格子间距 */
.book p {
line-height: 30px;
margin: 30px 0;
text-align: justify;
}
</style>
</head>
<body>
<div class="book">
<p>重复渐变其实就是渐变完了再来一次、再来一次,不停地重复同一个渐变单元,用它就能做出笔记本上的横格纸效果。</p>
<p>这里每一格的高度是 30px,前 29px 是纯白,最后 1px 是浅灰色的横线,所以看上去就是一条一条的格线。</p>
<p>文字要和格子对齐,就得把 line-height 也设成 30px,并且用 background-origin 让背景从内容区开始绘制。</p>
</div>
</body>
</html>要点解释 / 易错点
- 重复渐变就是在渐变函数前加
repeating-:repeating-linear-gradient()、repeating-radial-gradient()。 - 最关键的易错点:不重复的渐变可以省略起始颜色位置,但用了
repeating-之后,必须把起始位置0也写出来,否则格子出不来(只会变成纯色)。 - 每个颜色停靠点要写清楚,本例是
#fff 0→#fff 29px→#999 30px,即 0~29px 纯白、29~30px 渐变到灰线,然后自动开始下一轮。 - 文字和格子对不齐,是因为背景从边框盒开始画、而文字只排在内容盒上。解决办法是
background-origin: content-box让背景从内容区开始,再配合background-clip: content-box裁掉内容区以外的部分。 background复合属性里只写一个content-box,相当于同时设置了background-origin和background-clip,效果一样。- 这再次说明渐变就是一张背景图像,
background-origin/background-clip/background-repeat这些都能对它生效。
示例三:@font-face 使用 web 字体
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>web 字体</title>
<style>
/* @font-face 是一种规则,不是选择器,一般写在最前面 */
@font-face {
font-family: "xiaole"; /* 名字自己起,和原字体名无关 */
src: url("./fonts/xiaole.woff2") format("woff2"),
url("./fonts/xiaole.woff") format("woff"),
url("./fonts/xiaole.ttf") format("truetype");
}
.book01 {
width: 600px;
padding: 20px;
background-color: #f5f5f5;
font-family: "xiaole"; /* 哪个元素要用,就给哪个元素加 */
}
.book02 {
width: 600px;
padding: 20px;
margin-top: 20px;
background-color: #f5f5f5;
/* 没有设置 font-family,仍然是默认字体,做对比 */
}
</style>
</head>
<body>
<div class="book01">小乐的交友网站 English ABC</div>
<div class="book02">小乐的交友网站 English ABC</div>
</body>
</html>要点解释 / 易错点
@font-face的写法是@font-face { ... },前面没有选择器,它是在“定义一种字体”,不是给元素设样式。font-family里的名字是自己起的,叫什么都可以,跟字体文件原名没有关系,但后面使用font-family时名字必须和这里完全一致。src的路径最容易写错:必须写成url("./fonts/xxx.woff2")这种带./的相对路径,路径写错或漏了引号,字体就静默失效,页面回到默认字体。- 写多个
src是为了兼容不同浏览器(eot / woff / ttf / svg 等),现代浏览器基本只需要woff2。 - web 字体打破了“客户端电脑上必须装了这个字体”的限制,但中文字体文件动辄几兆到十几兆,会严重拖慢加载,所以中文网站一般不整站使用;常见做法是用定制字体工具只生成标题里那几个字(几 KB),或直接截图用图片。
- 图标字体本质上也是字体:引入后用
font-size改大小、color改颜色,且放大不失真(矢量图),这正是它比小图片好用的地方。
常见错误
- 现象:
blur()写了百分比或数值不带单位,图片完全不模糊。原因:blur()只接受长度值,百分比无效。修法:改用px、rem等长度单位,并从1px左右开始调试。 - 现象:把
filter: opacity(.5)和opacity: .5当成完全等价,或滤镜链中顺序混乱导致效果不对。原因:前者是滤镜链的一环,后者是元素合成属性;链式顺序会影响最终渲染。修法:需要与其他滤镜组合时用filter,单纯整体透明优先用opacity;调试时逐个函数删减排查。 - 现象:
drop-shadow()照搬box-shadow写spread、inset,阴影不生效或形状怪异。原因:drop-shadow()参数更少,且按元素 alpha 轮廓投影。修法:去掉spread、inset,只保留偏移、模糊、颜色,并用透明背景图验证轮廓。 - 现象:
repeating-linear-gradient()只写终点色标,结果整片纯色或纹理不出现。原因:重复渐变需要一个明确闭合的周期,起点色标缺失时周期不成立。修法:补齐0和终点色标,先做成一个完整条纹周期,再加repeating-。 - 现象:
@font-face已写,页面仍是默认字体,控制台常见 404。原因:src路径相对 CSS 文件而非 HTML;自定义font-family名与使用处不一致;格式顺序或地址写错。修法:先看 Network 确认字体是否 200,再核对路径、名字、format(),保留woff2/woff等回退。 - 现象:图标字体颜色能改,
font-size改不动。原因:图标库自带类名选择器权重更高。修法:提高选择器权重或写更具体的选择器,先看 Computed 面板确认哪条规则生效,慎用!important。 - 现象:中文 Web 字体加载很久,部分文字仍不变。原因:全量中文字体文件过大;定制字体只包含少量字形。修法:中文正文优先系统字体,标题用子集化/定制字体,并准备回退字体和缺字预案。
练习
- 做一个图片卡片:默认
blur模糊,鼠标悬停变清晰;再加一个“全站灰度”开关,切换body上的灰度滤镜。 - 用重复线性渐变完成“发廊灯”黑白条纹,要求条纹周期可调;进阶:让条纹缓慢移动,但先保证静态版本正确。
- 完成“渐变文字”:线性渐变背景 + 文字裁剪 + 透明文字色,并准备不支持时的回退方案。
- 用
@font-face引入一个英文字体,页面上放两个标题做对比:一个使用自定义字体,一个使用默认字体;打开 Network 和 Computed 面板记录排查过程。 - 用图标字体做一个三项导航:分别用
span、i、em承载图标,设置大小和颜色,并解释为什么某个font-size可能不生效。
原视频对照
| # | 视频 | 时长 |
|---|---|---|
| 1 | 径向渐变 | 07:00 |
| 2 | 重复渐变 | 11:21 |
| 3 | 滤镜 | 07:39 |
| 4 | web字体的使用 | 13:16 |
| 5 | 定制字体 | 07:19 |
| 6 | 阿里图标 | 17:19 |
小结
filter生产环境优先掌握blur()和grayscale(),其余函数按需查表,不要为了炫技堆复杂滤镜链。- 滤镜调试要建立“逐个函数删减”的习惯,先确认单个函数有效,再组合和调顺序。
- 重复渐变的核心不是“重复”二字,而是先构造一个闭合、可预测的周期。
- Web 字体排错顺序应是:Network 是否 200 → 路径是否正确 → 字体名是否一致 → 选择器是否命中。
- 中文全量 Web 字体要谨慎,正文用系统字体更稳;定制字体适合固定短标题,不适合正文。
- 图标字体本质仍是文字,优势是颜色、大小可控且放大不失真;但要留意选择器权重和语义标签选择。
- 交付前多看 Network 和 Computed 面板,字体 404、滤镜不生效、样式被覆盖大多能在面板中直接定位。
- 能用代码稳定实现的渐变和图标优先代码实现;过于复杂或维护成本高的视觉,截图、SVG 或图片也是合理工程选择。