
做前端这些年最容易被低估的一招就是CSS 渐变效果。很多人写页面卡片、按钮、图表底色清一色纯色填涂页面出来就是一股塑料感一问为什么不用渐变回答往往是写不准调半天不如贴张图。可真到了要改主题色、要做暗色模式、要把包体压下去的时候一张 200KB 的背景图就开始拖后腿了。我前后整理过三版渐变清单最后沉淀成这24 种 CSS 渐变效果每一种都附了可直接复制的源码覆盖线性、径向、锥形三大类以及它们在文字、边框、动画上的常见变体。这篇适合刚接触 CSS 的新手扫盲也适合写了几年但一直靠贴图偷懒的朋友回头补课。下面从最底层的规则讲起把为什么这么写和写出来长什么样一次讲透。1. 渐变不是颜色是一张图先把底层规则捋顺1.1 它返回的是 image不是 color这是整个渐变体系里最容易被忽略、也最容易导致代码没错但不生效的一条linear-gradient()、radial-gradient()、conic-gradient()三个函数的返回值类型都是image不是color。这个区别非常关键它决定了渐变能用在哪儿、不能用在哪儿。能用的地方background-image、border-image-source、mask-image、list-style-image、content配合伪元素等等凡是接受图像的位置都行。不能用的地方color、background-color、border-color、box-shadow的颜色位、text-decoration-color这类只认纯色的属性。新手最常见的错误写法就是background-color: linear-gradient(...)浏览器直接判为无效声明丢掉页面上一点反应都没有然后开始怀疑人生。顺带说一句background这个简写属性可以接渐变因为它是简写最终会落到background-image上所以background: linear-gradient(...)是合法的。但要小心简写会把之前设的background-size、background-position一起重置掉写多重背景的时候特别容易在这里翻车。1.2 方向语法关键字和角度其实是同一件事linear-gradient的第一个参数是方向可以用to top这类关键字也可以直接用角度。两者的对应关系是固定的但有一个反直觉的点0deg 指向上方角度顺时针增长。也就是说0deg等价于to top90deg等价于to right180deg等价于to bottom270deg等价于to left。关键字写法等价角度视觉方向to top0deg从下往上to right90deg从左往右to bottom180deg从上往下to left270deg从右往左to top left约315deg视宽高比变化从右下往左上to bottom right约135deg视宽高比变化从左上往右下最后两行是个隐藏的坑。to bottom right表达的是从左上角指向右下角这个向量的实际角度取决于容器的宽高比——宽 800 高 1000 的盒子它的对角线角度肯定不是 45 度。如果你想要的是绝对 45 度斜切必须显式写45deg别用to bottom right。我自己做斜纹背景时被这个坑过一次同一套样式在窄屏上条纹角度变了排查半天才发现是关键字惹的祸。1.3 色标的位置写法与硬边原理色标的完整写法是颜色 位置位置可以是百分比也可以是px、em、rem这些长度值。这里有三条规则值得单独说位置可省略。省略时浏览器会自动均分比如red, green, blue三色会落在 0%、50%、100%。两个色标落在同一位置就产生硬边。这是所有条纹、格子、饼图效果的根基linear-gradient(90deg, red 50%, blue 50%)不会有过渡带而是在中间直接切一刀。首尾色标的位置可以超出 0%~100%超出的部分不会显示但会改变中间色标的插值斜率做局部渐变的时候很有用。再补一个现代语法位置上可以写成区间red 0 30%, blue 30% 100%用两个值表示这段颜色从 0 到 30 都保持纯红。这种写法比在两个位置重复写同一个颜色更简洁Chrome 76、Firefox 72、Safari 12.2 都支持现在可以放心用了。我在第 2 章的硬边示例里会大量使用这种写法。2. 十二款线性渐变从四件套到硬边条纹2.1 基础方向四款效果 1–4这四款是地基任何渐变都是从这四种变形出来的。第一款是垂直双色最经典的天空蓝用在页头或者登录卡上几乎不会出错/* 效果 1垂直双色 */ .grad-1 { background-image: linear-gradient(to bottom, #4facfe, #00f2fe); }第二款是水平三色颜色从上到下改成从左到右中间多插一个色标视觉上会有一种扫过去的流动感。三色渐变的关键是中间色不能太脏否则过渡区会出现灰色比如红配绿一定要中间过黄或者过白千万不能直接红到绿/* 效果 2水平三色 */ .grad-2 { background-image: linear-gradient(to right, #f093fb, #f5576c, #ffc3a0); }第三款是 45 度斜向双色。这里务必用角度而不是to bottom right理由上一节已经讲过/* 效果 345 度斜向双色 */ .grad-3 { background-image: linear-gradient(45deg, #43cea2, #185a9d); }第四款是多色标 自定义位置用 135deg 做深紫到粉的过渡中间色标压到 50% 让过渡更陡。位置参数在这里的作用是控制过渡带有多宽两个色标离得越近颜色换得越急/* 效果 4多色标 自定义位置 */ .grad-4 { background-image: linear-gradient(135deg, #667eea 0%, #764ba2 50%, #f093fb 100%); }2.2 硬边系列四款效果 5–8硬边的本质就是让两个色标位置重合或者用现代区间语法明确划分。第五款是经典的双色对撞左右各占一半做对比卡片或者前后对比图特别好用/* 效果 5双色对撞 */ .grad-5 { background-image: linear-gradient(90deg, #ff6b6b 50%, #4ecdc4 50%); }第六款是三色等分用区间语法一次写完比重复写六次色标清爽得多。做步骤条、分段进度、三等分的图例底板都能直接用/* 效果 6三色等分 */ .grad-6 { background-image: linear-gradient(to right, #2b5876 0 33.33%, #4e4376 33.33% 66.66%, #7bc6cc 66.66% 100%); }第七款是等宽斜条纹用固定像素长度做色标这样无论容器多宽条纹宽度都稳定不变。如果用百分比容器一拉伸条纹就跟着变形这是做条纹图案时最容易忽略的一点/* 效果 7等宽斜条纹 */ .grad-7 { background-image: linear-gradient(45deg, #1f2933 0 10px, #3e4c59 10px 20px); }第八款是方格纸靠两组互相垂直的 1px 渐变叠出来配合background-size控制格子尺寸。这种写法在需要底纹、坐标纸、画布背景的场景下非常省资源比用 svg 还轻/* 效果 8方格纸底纹 */ .grad-8 { background-color: #0f172a; background-image: linear-gradient(rgba(255, 255, 255, .12) 1px, transparent 1px), linear-gradient(90deg, rgba(255, 255, 255, .12) 1px, transparent 1px); background-size: 24px 24px; }这里插一个经验点1px 细线的位置参数不能写 0要写1px否则线会被压在容器边缘外半像素在不同缩放比下时隐时现。同理做细线网格最好配合整数的background-size避免半像素模糊。2.3 repeating 系列三款效果 9–11repeating-linear-gradient的规则很简单它把整个渐变周期按你写的最后一个色标位置无限重复。第九款是斑马纹注意这里色标写的是0 12px和12px 24px重复周期就是 24px/* 效果 9斜向斑马纹 */ .grad-9 { background-image: repeating-linear-gradient( 45deg, #ffd93d 0 12px, #ff9f1c 12px 24px); }第十款是碳纤维质感用两组方向相反的细密重复渐变叠加一深一浅出来的效果很像编织纹理。这套写法在游戏类、硬件类页面里当按钮底板特别合适比贴图省事/* 效果 10碳纤维质感 */ .grad-10 { background-image: repeating-linear-gradient(45deg, #222 0 2px, #2e2e2e 2px 4px), repeating-linear-gradient(-45deg, rgba(255, 255, 255, .04) 0 2px, transparent 2px 4px); }第十一款是进度条填充这里用的是另一个思路——不重复而是靠background-size的百分比配no-repeat来控制填了多长。这种写法的好处是进度值可以直接用 CSS 变量驱动动画起来非常顺/* 效果 11进度条填充进度 68% */ .grad-11 { height: 10px; border-radius: 999px; background-color: #1e293b; background-image: linear-gradient(to right, #00b09b, #96c93d); background-size: 68% 100%; background-repeat: no-repeat; }2.4 透明渐隐效果 12第十二款是渐隐遮罩也是整个清单里被用得最多、却最容易被写错的一款。关键点是透明色要用rgba(0, 0, 0, 0)或者让位置直接落到transparent而不是用transparent去配一个彩色/* 效果 12底部渐隐遮罩 */ .grad-12 { background-image: linear-gradient(180deg, rgba(0, 0, 0, 0) 0%, #000 85%); }老版本的transparent会被浏览器解析成rgba(0, 0, 0, 0)如果你的渐变是黑色到 transparent完美但如果是白色到 transparent中间就会出现一段灰蒙蒙的过渡带因为插值是在白和透明黑之间算的。解决办法就是显式写成rgba(255, 255, 255, 0)颜色通道保持一致过渡才干净。这个小细节我在做图片蒙层的时候踩过排查了很久才反应过来是插值通道的问题。3. 九款径向与锥形光晕、涟漪、扇形与色相环3.1 径向渐变的三个参数位radial-gradient的完整语法是radial-gradient(形状 尺寸 at 位置, 色标...)三个参数位各有各的讲究形状circle正圆或ellipse椭圆默认是ellipse。尺寸可以是closest-side、farthest-side、closest-corner、farthest-corner四个关键字也可以是具体长度如120px。默认是farthest-corner也就是从中心到最远那个角作为半径所以元素越扁默认的椭圆就越扁。位置at 50% 50%表示正中心也可以用at left top这类关键字。默认值组合起来是ellipse farthest-corner at center。很多为什么我写的圆形光晕变成了椭圆的问题根源就是没写circle。3.2 径向六款效果 13–18第十三款是基础圆形光晕加了circle关键字无论容器多扁都是正圆/* 效果 13圆形光晕 */ .grad-13 { background-image: radial-gradient(circle at center, #ffd86f, #fc6262); }第十四款是边缘光斑把一个半径 60% 的白色光斑放在左上角下面垫一层深色底。这种点光效果在暗色主题的卡片上非常提气/* 效果 14角落光斑 */ .grad-14 { background-image: radial-gradient(circle at 30% 20%, rgba(255, 255, 255, .35), transparent 60%), #111827; }第十五款是椭圆渐隐用farthest-corner让半径刚好覆盖到最远的角做整块面板的柔和过渡最自然/* 效果 15椭圆渐隐 */ .grad-15 { background-image: radial-gradient(ellipse farthest-corner at 50% 50%, #5ee7df, #b490ca); }第十六款是球体高光。核心在于光源位置要偏移到32% 28%而不是正中心同时高光色标要压在 18% 以内。这三点凑一起二维圆形才有三维感/* 效果 16球体高光 */ .grad-16 { width: 120px; height: 120px; border-radius: 50%; background-image: radial-gradient( circle at 32% 28%, #ffffff 0%, #9ec9ff 18%, #2a5bd7 70%, #142a6b 100%); }第十七款是涟漪扩散用repeating-radial-gradient重复同心圆周期由两组色标决定。做加载动画的底纹、或者水波纹装饰很合适/* 效果 17涟漪扩散 */ .grad-17 { background-image: repeating-radial-gradient( circle at center, #06beb6 0 4px, #48b1bf 4px 20px); }第十八款是同心靶心靠硬边色标一圈圈铺开每一圈占比 20%。这个思路可以直接扩展成环形图/* 效果 18同心靶心 */ .grad-18 { background-image: radial-gradient(circle at center, #ef4444 0 20%, #ffffff 20% 40%, #ef4444 40% 60%, #ffffff 60% 80%, #ef4444 80% 100%); }3.3 锥形三款效果 19–21conic-gradient是近几年最值得掌握的一个它沿角度方向插值天生适合做扇形图、色相环、扫描光。语法是conic-gradient(from 起始角 at 位置, 色标...)。第十九款是扇形饼图。色标用百分比表示角度占比30% 就是 108 度。注意必须先给border-radius: 50%否则就是个方块被斜着切/* 效果 19扇形饼图 */ .grad-19 { width: 160px; height: 160px; border-radius: 50%; background-image: conic-gradient( #ff6b6b 0 30%, #4ecdc4 30% 55%, #ffd93d 55% 80%, #5f6caf 80% 100%); }第二十款是色相环七个色标首尾闭环。因为红色在 0deg 和 360deg 位置重合天然无缝/* 效果 20色相环 */ .grad-20 { width: 160px; height: 160px; border-radius: 50%; background-image: conic-gradient( from 0deg, red, yellow, lime, cyan, blue, magenta, red); }第二十一款是雷达扫描光用from 90deg决定扫描起点的朝向让高亮部分在 25% 的角度内衰减到全透明。换个from的值就能改扫描方向/* 效果 21雷达扫描光 */ .grad-21 { background-image: conic-gradient(from 90deg at 50% 50%, rgba(0, 255, 200, .9), rgba(0, 255, 200, 0) 25%, transparent 100%), #06131a; }锥形渐变有个实际限制值得提前知道它在角落处容易出现明显的色带banding因为角度插值在远离中心的区域跨度大。缓解办法是在深色区域加一层极轻的噪点或者把半径做小一些、外面套一层同色遮罩视觉上会平滑很多。4. 多重背景叠加把渐变当图层用4.1 图层顺序是从上往下的效果 22多重背景的写法是在background-image里用逗号分隔多组值先写的在上层后写的往下叠。这一点和 z-index 的直觉相反新手经常搞反。下面这款科技感网格就是三层叠出来的上层横向网格线、中层纵向网格线、底层锥形光晕/* 效果 22科技感网格底纹 */ .grad-22 { background-color: #050b14; background-image: linear-gradient(rgba(0, 255, 200, .10) 1px, transparent 1px), linear-gradient(90deg, rgba(0, 255, 200, .10) 1px, transparent 1px), conic-gradient(from 200deg at 80% 10%, rgba(0, 200, 255, .35), transparent 40%); background-size: 32px 32px, 32px 32px, 100% 100%; }这里有个必须配对的细节background-size的值也是逗号分隔的而且必须和background-image的数量一一对应。如果你只写了两个 size 但有三层 image第三层会取默认的auto auto。字号越小、图层越多的样式越容易在这里出问题我一般写完会用浏览器开发者工具逐层临时关掉确认一遍。4.2 暗角与景深效果 23第二十三款是经典的暗角vignette中间透明、四周压黑套在任何图片或者卡片上都能立刻产生聚焦中心的景深感。它是从中心向外的径向渐变所以透明区在中间深色在边缘/* 效果 23暗角 */ .grad-23 { background-image: radial-gradient( ellipse at center, transparent 45%, rgba(0, 0, 0, .75) 100%); }这个效果用在轮播图上特别划算不需要额外切图只要给遮罩层加这个背景图片本身的明暗过渡就统一了。想调强度就改两个位置45% 越小聚焦感越强75% 的透明度越低压得越暗。4.3 文字渐变效果 24第二十四款是文字渐变实现依赖三步组合先给背景铺渐变再把背景裁剪到文字轮廓最后把文字颜色设为透明。/* 效果 24文字渐变 */ .grad-24 { background-image: linear-gradient(90deg, #f7971e, #ffd200); -webkit-background-clip: text; background-clip: text; color: transparent; }这三步缺一不可。只写background-clip: text不写color: transparent文字会把背景盖住只写color: transparent不写裁剪你会看到一个纯色方块。另外-webkit-background-clip虽然是非标准前缀但目前仍然是 Safari 的必需项两个都写上最稳。还有一个隐藏问题文字渐变之后文字就不能被选中高亮了——因为color是透明的选中态看不出来。解决办法是给::selection单独设一个可见的背景色用户体验立刻回来。这个细节在正式项目里被设计师提过好几次。5. 渐变落地到页面文字、边框、动画与性能5.1 渐变边框的两种做法渐变边框是高频需求但border-image和border-radius天生不兼容一加圆角边框就断。我一般用两种绕开的思路第一种是双背景 padding 裁切外层给渐变内层给纯色中间用padding留出边框宽度.grad-border { border: 2px solid transparent; border-radius: 12px; background: linear-gradient(#0f172a, #0f172a) padding-box, linear-gradient(135deg, #f7971e, #ffd200) border-box; }第二种是伪元素方案用::before铺渐变并做mask裁切适合边框很细或者需要做动画的场景。第一种成本更低能覆盖八成需求我默认都用它。5.2 渐变动画的正确姿势想让渐变流动起来最容易想到的是动background-image的色标位置但这一招在大多数浏览器里不可动画写上去不会报错但也不会有任何效果。可行的做法是动background-position或者transformkeyframes grad-flow { 0% { background-position: 0% 50%; } 100% { background-position: 200% 50%; } } .grad-anim { background-image: linear-gradient(90deg, #4facfe, #00f2fe, #4facfe); background-size: 200% 100%; animation: grad-flow 3s linear infinite; }关键点有三个渐变首尾颜色必须相同否则循环会跳变、background-size要放大到 200% 以上、动画走linear才匀。这套组合我用来做呼吸感加载条比 GIF 小了几百倍也不会有明显的接缝。5.3 性能上的一点实情渐变本身由 GPU 参与合成的成本并不高真正的开销在改变什么属性上。动background-position会触发重绘动background-image会触发更重的绘制。如果你要做大面积、长时间的渐变动画更稳的思路是把渐变画在一个固定层上然后用transform: translateX()去推动一个遮罩让合成层干活。另外移动端要克制超大面积的径向渐变叠加。之前有个项目在首屏堆了四层渐变做氛围光桌面端没问题中低端机型上滚动明显掉帧。后来砍到两层、并且把光晕区域限制在首屏 60% 高度以内问题就消失了。渐变是视觉效果但它不是免费的。属性是否可动画代价建议background-color是低纯色过渡首选background-position是中重绘流动渐变常用background-image色标基本不可动画高不要依赖opacity/transform是低合成大范围动画首选6. 写坏了怎么查渐变不生效的排查清单6.1 按顺序过一遍这七条渐变没效果的原因其实高度集中我通常按这个顺序排查基本前三步就能定位是不是写到了background-color上。渐变是 image写到只认颜色的属性上会被整条丢弃。色标数量是不是少于两个。只有一个色标的渐变是无效的浏览器会当成none。位置值是不是递减的。red 80%, blue 20%这种写反了不会报错浏览器会按 20% 那一端去修正视觉上就是颜色糊在一起。逗号是不是用了中文全角。从文档里复制粘贴最容易中招尤其是和,长得太像。background简写是不是把前面写的background-image冲掉了。同一规则块里先写 image 再写简写前面的全废。元素尺寸是不是 0。渐变在 0 宽或者 0 高的元素上什么都看不见检查一下有没有设高度。background-clip和color有没有配对。文字渐变少写任何一个都出不来。6.2 一个实测有效的二分调试法如果上面七条都排掉了还是不生效我会用二分法先把整个渐变替换成linear-gradient(red, blue)。这一步是排除色值问题——如果红蓝能显示说明是颜色或者色标写错了如果连红蓝都不显示说明是属性、尺寸或者选择器的问题跟渐变本身无关。确认是色值问题之后再逐个把色标换回来换到哪个崩就是哪个的问题。这招听起来笨但比对着代码一行行看快得多尤其是多层叠加的情况我一般还会顺手在开发者工具里逐个勾掉background-image里的图层一层层确认是谁挡住了谁。6.3 浏览器差异与兼容口径渐变本身是老技术了现代浏览器基本无脑支持真正需要注意的是几个新语法特性支持情况备注不带前缀的linear-gradient主流浏览器均支持不需要加-webkit-老前缀conic-gradientChrome 69 / Safari 12.1 / Firefox 83需要覆盖较老内核时准备降级色色标区间语法red 0 30%Chrome 76 / Safari 12.2 / Firefox 72老设备上建议拆成两个色标写文字渐变需-webkit-background-clip: text两个前缀都写关于降级我的做法是给容器先设一个同色系的background-color渐变写在background-image上。这样即使遇到不支持的场景页面也是一块纯色而不是一片白观感上不会崩。生产环境里我没遇到过真的不支持线性渐变的设备但conic-gradient在部分老旧内核上确实要留个心眼。最后分享两个调参的小手感。第一渐变的过渡带宽度不靠感觉调就用位置值量化想让某个颜色多停留一会儿把它的两个位置拉开想让过渡干脆就把两个位置贴近距离小于 2% 时基本等同于硬边。第二色彩搭配上相邻色相慢慢过渡永远比撞色急转安全真要撞色中间务必垫一个高亮或者白色作为缓冲视觉上会舒服很多——这条经验我在给四个不同产品线配色时都验证过屡试不爽。