还记得老式电视机没信号时满屏的“雪花”吗?那种灰白噪点闪烁的画面,现在用CSS渐变就能复刻出来。没错,就是平时用来做背景过渡的linear-gradient、conic-gradient这些东西,加上一点“反走样bug”的骚操作,直接变身噪点生成器。下面手把手盘一盘怎么把渐变的锯齿缺点变成视觉炸裂的雪花特效。
渐变锯齿咋就成了噪点
CSS渐变在硬色标交界处经常翻车——比如black 50%, white 50%这种写法,浏览器渲染时会因为亚像素计算产生狗牙边。正常思路是加0.5%的缓冲区间来平滑,但反其道而行之:把缓冲区间压到极小,比如black 49.9999%, white 50.0001%,锯齿会恶化成密密麻麻的碎点。这碎点不就是电视雪花的雏形么?
打个比方:正常渐变像用喷枪画画,边缘柔和;硬色标像用尺子划线,边缘毛糙;而极端小数值的硬色标,相当于拿针扎出无数小孔,凑近看全是颗粒。下面这段代码就是最简噪点生成器:
.noise-bg {
background: conic-gradient(
#000 0.0001%,
#fff 0.0002%,
#000 0.0003%
);
background-size: 100% 100%;
}放大看还是能隐约看到圆锥渐变的放射状纹路,需要继续缩小色标间隔并放大背景尺寸来掩盖痕迹。实际操作时把渐变尺寸拉到3000px见方,再用background-position: 60% 60%偏移中心,纹路就彻底糊成随机噪点。
手搓纯静态雪花屏
方案一:单层渐变硬怼
- 新建一个HTML文件,弄个全屏
<div>,class取tv-static。 - 给这个div加上背景:选用
repeating-conic-gradient,色标值全部写成0.0001%这种级别的小数,颜色在纯黑、深灰、浅灰、纯白之间来回跳。 - 背景尺寸不要用默认的auto,而是固定成
2500px 2500px,再用background-position: 55% 48%把渐变圆心挪到屏幕外。 - 如果颗粒感不够密,把色标数量增加到8个以上,比如黑、灰、白、深灰、浅灰、黑这样循环。
.tv-static {
width: 100vw;
height: 100vh;
background: repeating-conic-gradient(
#000 0.0001%, #333 0.0002%, #666 0.0003%,
#999 0.0004%, #ccc 0.0005%, #fff 0.0006%,
#aaa 0.0007%, #444 0.0008%
);
background-size: 3000px 3000px;
background-position: 42% 57%;
}需要注意:不同浏览器对小数点后位数的处理不一样,Chrome和Edge能扛住6位小数,Firefox可能到第4位就开始摆烂。如果看到大片空白或者渐变条纹,就把小数点后位数减到3位试试。另外背景尺寸越大性能越吃紧,3000px在笔记本上风扇可能会起飞——可以在开发完把尺寸降到2000px,肉眼几乎看不出区别。
方案二:双层渐变混合消纹路
单层渐变在某些角度下还是能看出淡淡的放射状线条,加一层radial-gradient混合就能完美解决。
- 保留上面方案一的代码,但把
background拆成两个背景层,中间用逗号隔开。 - 第一层用
conic-gradient,色标更随机一些;第二层用radial-gradient,圆心偏移到不同位置。 - 添加
background-blend-mode: difference或exclusion,让两层噪点相互干扰,纹路彻底消失。
.tv-static-blend {
background:
repeating-conic-gradient(
#000 0.0001%, #555 0.0002%, #fff 0.0003%,
#222 0.0004%, #888 0.0005%
) at 70% 30%,
repeating-radial-gradient(
circle at 20% 80%,
#000 0.0001%, #aaa 0.0002%, #fff 0.0003%,
#333 0.0004%
);
background-size: 2500px 2500px, 1800px 1800px;
background-blend-mode: exclusion;
}混合模式别用multiply或screen,那会让噪点变灰蒙蒙一片。difference出来的颗粒对比度最强,接近老电视那种生猛雪花。如果觉得太亮,overlay模式也能压暗一些。
让雪花动起来:老电视故障动画
静态雪花不够带劲,加个CSS动画让噪点疯狂闪烁,再配合位置偏移模拟信号干扰。
方案三:0.1秒极速位移
- 在方案二的基础上定义一个
@keyframes动画,只改变background-position。 - 第一帧
0%时位置是40% 50%,第二帧100%时位置变成60% 45%。 - 动画时长设置成
0.1s(也就是100毫秒),循环次数infinite,步长用steps(5)制造跳跃感。
@keyframes snowMove {
0% { background-position: 40% 50%, 20% 70%; }
100% { background-position: 60% 45%, 80% 30%; }
}
.tv-static-animated {
animation: snowMove 0.1s steps(3) infinite;
}steps()很重要——如果用linear或ease,噪点会平滑滑动,看起来像液体流动,完全不像雪花。steps(3)让背景每帧粗暴跳变,闪烁感直接拉满。但注意动画时长不能低于0.05s,否则浏览器刷新率跟不上,反而卡成PPT。0.08s到0.12s之间是最佳区间。
方案四:叠加filter和伪元素制造扫描线
想要更复古的效果,可以再加一层伪元素做扫描线或信号失真。
- 给
.tv-static添加position: relative,然后用::before伪元素覆盖同样大小的区域。 - 伪元素背景用重复线性渐变,做几条半透明黑条,模拟CRT电视的扫描线。
- 再叠加一个
filter: blur(0.5px)让噪点稍微糊一点点,接近老电视的低分辨率质感。
.tv-static {
position: relative;
overflow: hidden;
}
.tv-static::before {
content: "";
position: absolute;
inset: 0;
background: repeating-linear-gradient(
to bottom,
rgba(0,0,0,0.2) 0px,
rgba(0,0,0,0.2) 2px,
transparent 2px,
transparent 4px
);
pointer-events: none;
filter: blur(0.3px);
mix-blend-mode: overlay;
}pointer-events: none保证伪元素不干扰鼠标点击。扫描线的半透明黑条宽度不要超过2px,否则会遮住太多噪点细节。blur值超过1px噪点就变成一片灰雾,失去颗粒感。
给图片套上雪花滤镜
把噪点效果叠在图片上,不用PS也能秒变老照片。
方案五:伪元素混合模式叠图
- 准备一张
<img>或者带背景图的div,给它的父容器设置position: relative。 - 父容器用上面的动态噪点代码作为
::after伪元素,并且设置mix-blend-mode: overlay或hard-light。 - 把伪元素的
background-blend-mode去掉(因为只需要单层噪点),但保留动画。
.image-wrapper {
position: relative;
width: 600px;
height: 400px;
}
.image-wrapper img {
width: 100%;
height: 100%;
object-fit: cover;
}
.image-wrapper::after {
content: "";
position: absolute;
inset: 0;
background: repeating-conic-gradient(
#000 0.0001%, #fff 0.0002%, #444 0.0003%,
#bbb 0.0004%, #111 0.0005%
);
background-size: 2000px 2000px;
background-position: 30% 70%;
mix-blend-mode: overlay;
pointer-events: none;
animation: snowMove 0.09s steps(4) infinite;
}overlay模式会让图片暗部噪点更明显,亮部噪点减弱,很有胶片颗粒的感jio。如果图片偏亮,改用multiply模式噪点会更重。鼠标悬停时想取消噪点?加个.image-wrapper:hover::after { opacity: 0; }就行。
方案六:纯CSS文字噪点特效
让文字也沾上雪花,但不是给文字加背景,而是把噪点裁剪到文字轮廓内。
- 写一段
<h1>标题,比如“雪花屏文字”,设置大号字体和粗体。 - 给这个标题设置
background为上述任一种噪点渐变,同时加上background-clip: text和-webkit-background-clip: text。 - 文字颜色设成透明,噪点就会透过文字形状显示出来。
.noisy-text {
font-size: 80px;
font-weight: 900;
background: repeating-radial-gradient(
circle at 20% 30%,
#fff 0.0001%, #333 0.0002%, #666 0.0003%,
#000 0.0004%, #999 0.0005%
);
background-size: 1500px 1500px;
-webkit-background-clip: text;
background-clip: text;
color: transparent;
animation: textNoiseMove 0.12s steps(5) infinite;
}
@keyframes textNoiseMove {
0% { background-position: 10% 20%; }
100% { background-position: 80% 70%; }
}文字噪点有个坑:background-clip: text在Firefox下需要显式加color: transparent,不然文字底色会盖住渐变。另外文字字号太小的话噪点细节看不清,建议至少40px以上。想玩花的可以再加个text-shadow模拟旧电视的残影。
所有方案的核心就是抓住渐变反走样bug:硬色标间隔越小,像素级错位越严重,错位到极致就是完美雪花。不过这东西属于浏览器渲染的非标准行为,保不齐哪天Chrome更新就把这bug修了,到时候噪点秒变彩虹渐变。所以拿来整活做个人网站、创意实验或者404页面完全没问题,但商业项目还是老老实实用SVG或者Canvas。跑起来之后记得多换几个浏览器瞅瞅效果,Chrome和Edge最稳,Safari可能会直接摆烂成一坨色块。
