径向渐变
radial-gradient() 从一个中心点向外混合颜色。和所有 CSS 渐变一样,它是一种图像,所以要写在 background-image(或 background 简写属性)里:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Radial gradient</title>
<style>
body { font-family: system-ui, sans-serif; font-size: 14px; }
.row { display: flex; gap: 12px; flex-wrap: wrap; }
.box { width: 220px; height: 120px; border-radius: 8px; margin-bottom: 4px; }
.ellipse { background-image: radial-gradient(#93c5fd, #1e3a8a); }
.circle { background-image: radial-gradient(circle, #93c5fd, #1e3a8a); }
.corner { background-image: radial-gradient(circle at top left, #fde68a, #f59e0b 40%, #b45309); }
</style>
</head>
<body>
<div class="row">
<div><div class="box ellipse"></div>ellipse (default)</div>
<div><div class="box circle"></div>circle</div>
<div><div class="box corner"></div>circle at top left</div>
</div>
</body>
</html>
完整语法是 radial-gradient(shape size at position, color stops)。颜色之前的部分都是可选的。
| 部分 | 可选值 | 默认值 |
|---|
| 形状 | circle、ellipse | ellipse |
| 大小 | closest-side、closest-corner、farthest-side、farthest-corner,或长度 | farthest-corner |
| 位置 | at center、at top left、at 30% 70%、at 20px 40px | at center |
| 色标 | 两个或更多颜色,每个颜色可以带一个位置 | |
大小关键字决定最后一个颜色在哪里到达:在盒子最近的边、最远的角,等等。修改这里的值,看看渐变如何重新绘制:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Radial gradient tester</title>
<style>
body { font-family: system-ui, sans-serif; }
#box { height: 160px; margin-top: 10px; border: 1px solid #d1d5db; border-radius: 8px; }
#out { font-size: 13px; }
</style>
</head>
<body>
<label>radial-gradient( <input id="val" value="circle closest-side at 30% 50%, #f59e0b, #2563eb" size="42"> )</label>
<div id="box"></div>
<code id="out"></code>
<script>
const box = document.getElementById('box');
const input = document.getElementById('val');
const show = () => {
const value = 'radial-gradient(' + input.value + ')';
const ok = CSS.supports('background-image', value);
if (ok) box.style.backgroundImage = value;
document.getElementById('out').textContent = ok ? value : 'invalid gradient';
};
input.addEventListener('input', show);
show();
</script>
</body>
</html>
试试 circle farthest-corner at 30% 50%, #f59e0b, #2563eb、ellipse at bottom, white, #16a34a 和 circle 40px, #f59e0b 99%, transparent(一个边缘分明的圆点)。
线性渐变
linear-gradient() 沿一条直线混合颜色。先写方向或角度,再写颜色:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Linear gradient</title>
<style>
body { font-family: system-ui, sans-serif; font-size: 14px; }
.row { display: flex; gap: 12px; flex-wrap: wrap; }
.box { width: 160px; height: 90px; border-radius: 8px; margin-bottom: 4px; }
.down { background-image: linear-gradient(#2563eb, #16a34a); }
.right { background-image: linear-gradient(to right, #2563eb, #16a34a); }
.angle { background-image: linear-gradient(45deg, #2563eb, #16a34a); }
.three { background-image: linear-gradient(to right, #dc2626, #f59e0b, #16a34a); }
</style>
</head>
<body>
<div class="row">
<div><div class="box down"></div>default (to bottom)</div>
<div><div class="box right"></div>to right</div>
<div><div class="box angle"></div>45deg</div>
<div><div class="box three"></div>three colors</div>
</div>
</body>
</html>
角度从指向上方的 0deg 开始,按顺时针旋转,所以 90deg 就是 to right,180deg 就是默认的 to bottom。在从右到左的页面中,to right 仍然是物理方向;如果渐变需要跟随阅读方向,就得自己做镜像。
色标与硬色标
每个颜色都可以有一个位置。不写位置时,颜色均匀分布。当两个颜色位置相同时,颜色会瞬间切换,条纹、旗帜和进度条就是这样画出来的:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Color stops</title>
<style>
body { font-family: system-ui, sans-serif; font-size: 14px; }
.bar { height: 40px; border-radius: 6px; margin: 4px 0 12px; }
.shifted { background: linear-gradient(to right, #2563eb 70%, #f59e0b); }
.hard { background: linear-gradient(to right, #2563eb 60%, #e5e7eb 60%); }
.stripes {
background: repeating-linear-gradient(45deg,
#f59e0b 0 12px, #111827 12px 24px);
}
.rings { height: 120px; background: repeating-radial-gradient(circle, #2563eb 0 8px, #bfdbfe 8px 16px); }
</style>
</head>
<body>
Solid until 70%, then blends
<div class="bar shifted"></div>
Hard stop at 60% (a progress bar)
<div class="bar hard"></div>
repeating-linear-gradient
<div class="bar stripes"></div>
repeating-radial-gradient
<div class="bar rings"></div>
</body>
</html>
一个色标也可以带两个位置,比如 #111827 12px 24px,它会画出一条从 12px 到 24px 的纯色带。
锥形渐变
conic-gradient() 围绕中心点扫过各种颜色,就像时钟的指针。配合硬色标,不用任何图片或 JavaScript 就能画出饼图:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Conic gradient</title>
<style>
body { font-family: system-ui, sans-serif; font-size: 14px; display: flex; gap: 24px; }
.pie {
width: 140px; height: 140px; border-radius: 50%;
background: conic-gradient(#2563eb 0 45%, #16a34a 45% 75%, #f59e0b 75%);
}
.wheel {
width: 140px; height: 140px; border-radius: 50%;
background: conic-gradient(red, yellow, lime, aqua, blue, magenta, red);
}
</style>
</head>
<body>
<div><div class="pie"></div>45%, 30%, 25%</div>
<div><div class="wheel"></div>A color wheel</div>
</body>
</html>
用 CSS 画的图表对屏幕阅读器是不可见的,所以也要用文字写出这些数字。
渐变文字
把渐变背景裁剪到字母的形状上,并让文字本身透明:
.gradient-text {
background: linear-gradient(90deg, #2563eb, #db2777);
-webkit-background-clip: text; /* older browsers need the prefix */
background-clip: text;
color: transparent;
}
记得考虑一个普通的 color 后备:如果裁剪失败,文字就会消失。渐变文字的对比度也不均匀,所以只在大标题上使用。
渐变可以和图片以及其他渐变一起叠加在同一个 background-image 列表里;背景图片一页讲解了图层、大小和位置。
常见错误
background-color: linear-gradient(...)。 渐变是一种图像:请用 background-image 或 background。
- 角度方向搞反了。 0deg 指向上方,而不是右方。
90deg 才是朝右。
- 在没有高度的元素上设置渐变。 什么都不会显示;给它内容或尺寸。
- 中间的颜色发灰发浑。 混合两个饱和度高的对立颜色(比如红和绿),在 sRGB 中会经过灰褐色。加一个中间色标,或者在另一个颜色空间里混合:
linear-gradient(in oklch, red, green)。
- 大面积的细微渐变出现色带。 在大面积上使用非常接近的颜色会显出台阶;让色标之间的对比稍大一些会有帮助。