CSS 渐变实战:线性、径向与锥形的常用写法
页面为什么总显得'差点意思'
很多页面不是功能不好,而是视觉上太平。按钮是纯色块,卡片只有硬边框,背景也没层次,整体看起来就像把组件直接铺上去了。渐变不是装饰品,它更像是一层很便宜、但很管用的光影修正。
做页面时我一般不会先想着'要不要加渐变',而是看这个地方需不需要一点明暗变化。按钮、卡片高光、遮罩、骨架屏,这些地方加得上,往往比单纯换个颜色更有效。
线性渐变:最常见,也最容易用过头
linear-gradient() 是最常用的渐变。它沿着一条直线过渡,适合按钮背景、条纹、遮罩层。
.fancy-button {
background: linear-gradient(red, blue);
}
默认情况下,渐变方向是从上到下。想改方向,可以用关键字,也可以直接写角度。
.left-to-right {
background: linear-gradient(to right, #ff6b6b, #4ecdc4);
}
.diagonal {
background: linear-gradient(to bottom right, #f093fb 0%, #f5576c 100%);
}
.angled {
background: linear-gradient(45deg, #667eea 0%, #764ba2 100%);
}
.weird-angle {
background: linear-gradient(-45deg, #12c2e9, #c471ed, #f64f59);
}
这里最容易踩的坑是角度。CSS 里的角度不是按大多数人直觉来的,0deg 指向上方,90deg 才是从左到右。第一次写的时候很容易反着想,调两次就记住了。
颜色停点别只写两个
.rainbow {
background: linear-gradient(to right, red 0%, orange 16.66%, yellow 33.33%, green 50%, blue 66.66%, indigo 83.33%, violet 100%);
}
.auto-rainbow {
background: linear-gradient(to right, red, orange, yellow, green, blue, indigo, violet);
}
.stripes {
background: linear-gradient(to right, #ff6b6b 0%, #ff6b6b 50%, #4ecdc4 50%, #4ecdc4 100%);
}
颜色停点决定了颜色在哪个位置出现。把两个相邻颜色的停点写成同一个值,就能做出硬切效果,条纹背景、进度条分段都能这么处理,不需要额外图片。
透明渐变更适合做遮罩
.overlay {
background: linear-gradient(to bottom, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0) 100%);
}
.hero-section {
background-image: linear-gradient(rgba(0,0,0,0.5),rgba(0,0,0,0.5)), url('hero.jpg');
}
这种写法比直接给元素加 opacity 更稳。opacity 会把整个元素都压暗,包括文字;渐变遮罩只影响背景层,阅读体验会好很多。
一个比较顺手的按钮写法
.pulse-button {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border: none;
padding: 15px 40px;
color: white;
font-size: 16px;
border-radius: 30px;
cursor: pointer;
transition: all 0.3s ease;
box-shadow: 0 4px 15px rgba(118, 75, 162, 0.4);
}
.pulse-button:hover {
background: linear-gradient(135deg, #764ba2 0%, #667eea 100%);
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(118, 75, 162, 0.6);
}
.pulse-button:active {
transform: translateY(0);
box-shadow: 0 2px 10px rgba(118, 75, 162, 0.4);
}
这个按钮的重点不是'颜色多好看',而是它在 hover 时会有一点流动感。把渐变顺序反过来,视觉上会像被翻了一层光,效果比单纯放大一点更细。
径向渐变:更适合做光晕和聚焦
径向渐变是从中心向外扩散,适合高光、球体、发光边缘这些场景。它比线性渐变更'有中心感'。
.simple-radial {
background: radial-gradient(red, blue);
}
.perfect-circle {
background: radial-gradient(circle, #ff6b6b, #4ecdc4);
}
.off-center {
background: radial-gradient(circle at 20% 30%, #f093fb, #f5576c);
}
.sized {
background: radial-gradient(circle closest-side at center, #fff, #000);
}
几个常用参数记住就够了:circle 表示正圆,默认是椭圆;at x y 控制圆心位置;closest-side、farthest-corner 这类关键字控制渐变范围。实际项目里我用得最多的还是 circle at center 和 circle at xx% yy%,够直接,也更容易控制视觉重心。
发光效果通常这样写
.glow {
background: radial-gradient(circle at center, rgba(255, 255, 255, 0.9) 0%, rgba(255, 255, 255, 0.4) 40%, rgba(255, 255, 255, 0) 70%);
}
.3d-sphere {
width: 100px;
height: 100px;
border-radius: 50%;
background: radial-gradient(circle at 30% 30%, #ffffff 0%, #e0e0e0 20%, #808080 50%, #404040 80%, #202020 100%);
box-shadow: 5px 5px 15px rgba(0,0,0,0.3);
}
球体这个例子挺典型。高光放左上角,暗部往右下压,再补一个阴影,圆润感就出来了。它不是真正的 3D,但在图标、按钮、装饰块里已经够用了。
输入框外层发光,最好放到伪元素上
.input-wrapper {
position: relative;
display: inline-block;
}
.glow-input {
padding: 12px 20px;
border: 2px solid #e0e0e0;
border-radius: 8px;
outline: none;
transition: all 0.3s;
background: white;
}
.input-wrapper::before {
content: '';
position: absolute;
top: -2px;
left: -2px;
right: -2px;
bottom: -2px;
border-radius: 10px;
background: radial-gradient(circle at center, rgba(102, 126, 234, 0.6) 0%, rgba(102, 126, 234, 0) 70%);
opacity: 0;
transition: opacity 0.3s;
z-index: -1;
filter: blur(8px);
}
.input-wrapper:focus-within::before {
opacity: 1;
}
.glow-input:focus {
border-color: #667eea;
}
我更喜欢把光晕交给伪元素处理,这样不会影响输入框本身的尺寸和点击区域。focus-within 也很实用,外层容器能跟着子元素状态变化,做聚焦效果比单独盯着输入框本身顺手。
渐变语法不用死记,拆开看就行
linear-gradient([方向], [颜色停点 1], [颜色停点 2], ...);
radial-gradient([形状] [大小] at [位置], [颜色停点 1], ...);
线性渐变主要看方向和停点;径向渐变主要看形状、范围和圆心位置。你只要能把这几个参数拆开,剩下的就是调视觉。
颜色停点的几种常用写法
simple {
background: linear-gradient(red, blue);
}
precise {
background: linear-gradient(red 20%, blue 80%);
}
fixed {
background: linear-gradient(red 50px, blue 100px);
}
百分比更适合响应式布局,像素更适合固定长度的条带效果。两种能混用,但别为了'写得复杂'去混,通常清晰比花哨更重要。
玻璃拟态也离不开渐变
.glass-card {
background: linear-gradient(135deg, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0.05) 100%);
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.2);
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
}
这类效果的核心不是'玻璃感'这个词本身,而是半透明加模糊后的层次。渐变负责把表面做出一点明暗变化,backdrop-filter 才是让背景真的糊起来。两者配一起才像样。
多层背景叠加,实际项目里很常见
background 可以写多个层,前面的盖在后面上面。这个特性比很多人想的更常用,尤其是做纹理、遮罩、复杂按钮时。
.layered {
background: linear-gradient(rgba(0,0,0,0.5),rgba(0,0,0,0.5)), linear-gradient(45deg, #ff6b6b, #4ecdc4);
}
.complex {
background: repeating-linear-gradient(45deg, transparent, transparent 10px, rgba(255,255,255,0.1) 10px, rgba(255,255,255,0.1) 20px), linear-gradient(to bottom, #667eea, #764ba2), #1a1a1a;
}
第一层负责纹理或遮罩,第二层负责主色,最后再补一个纯色兜底。这样写虽然看起来长一点,但比去找一张纹理图更省事,也更容易改。
兼容性:现在不用太担心前缀,但别把保底丢了
旧时代写渐变经常要带一堆前缀,现在基本没必要了。
.old-school {
background: -webkit-linear-gradient(left, red, blue);
background: -moz-linear-gradient(left, red, blue);
background: -o-linear-gradient(left, red, blue);
background: linear-gradient(to right, red, blue);
}
如果项目里已经不需要照顾很老的浏览器,直接标准语法就行。真正值得保留的是纯色兜底。
.safe-button {
background: #667eea;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
@supports (background: linear-gradient(90deg, red, blue)) {
.modern-button {
background: linear-gradient(135deg, #667eea, #764ba2);
}
}
这种写法不花哨,但很稳。先给纯色,再覆盖渐变,浏览器支持与否都不至于翻车。
项目里最常见的几个用法
登录按钮
.login-btn {
width: 100%;
padding: 14px;
border: none;
border-radius: 8px;
color: white;
font-size: 16px;
font-weight: 600;
cursor: pointer;
background: linear-gradient(90deg, #667eea 0%, #764ba2 100%);
box-shadow: inset 0 1px 0 rgba(255,255,255,0.2), 0 4px 6px rgba(118, 75, 162, 0.3);
transition: all 0.3s ease;
}
.login-btn:hover {
background: linear-gradient(90deg, #7b8fe8 0%, #8a5cb8 100%);
transform: translateY(-1px);
box-shadow: inset 0 1px 0 rgba(255,255,255,0.3), 0 6px 12px rgba(118, 75, 162, 0.4);
}
.login-btn:active {
transform: translateY(0);
box-shadow: inset 0 2px 4px rgba(0,0,0,0.1), 0 2px 4px rgba(118, 75, 162, 0.3);
}
inset 内阴影会让按钮更像一个有厚度的面,而不是一块平贴在页面上的色块。这个细节不一定每次都要用,但在主按钮上通常是加分项。
卡片 hover 抬升
.card {
background: white;
border-radius: 12px;
padding: 24px;
transition: all 0.3s ease;
box-shadow: 0 2px 8px rgba(0,0,0,0.08);
}
.card:hover {
transform: translateY(-4px);
box-shadow: 0 12px 24px rgba(0,0,0,0.15);
background: linear-gradient(to bottom, rgba(255,255,255,0.8) 0%, white 20%);
}
这个场景里渐变是辅助,不是主角。卡片本身的抬升靠阴影和位移,顶部那一点点亮度变化只是让它看起来没那么死。
骨架屏和进度条
.skeleton {
background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
background-size: 200% 100%;
animation: shimmer 1.5s infinite;
}
@keyframes shimmer {
0% { background-position: 200% 0; }
100% { background-position: -200% 0; }
}
.progress-bar {
height: 4px;
background: #e0e0e0;
border-radius: 2px;
overflow: hidden;
}
.progress-fill {
height: 100%;
width: 60%;
background: linear-gradient(90deg, #667eea 0%, #764ba2 50%, #667eea 100%);
background-size: 200% 100%;
animation: flow 2s linear infinite;
}
@keyframes flow {
0% { background-position: 100% 0; }
100% { background-position: -100% 0; }
}
这两种写法的思路一样:把渐变当成一张'会动的背景图',再通过 background-position 去扫过去。用户看到的是加载动画,实际上就是背景在平移。
调试时,先确认方向和停点
渐变写错的时候,十有八九不是浏览器 bug,而是方向和停点搞混了。我的习惯是先看这两件事:
- 方向有没有反
- 停点是不是写得太近,导致几乎看不出过渡
如果颜色太接近,可以先换成差异很大的两三个色块,把结构调明白,再换回正式配色。这样比盯着最终色值硬猜要省时间。
锥形渐变很适合做饼图和转盘
conic-gradient() 比前两种更像'绕中心旋转'。它常见于饼图、进度环、转盘样式。
.pie {
background: conic-gradient(#667eea 0% 25%, #764ba2 25% 50%, #f093fb 50% 75%, #f5576c 75% 100%);
}
这个语法不复杂,但兼容性和老浏览器支持没前两种稳定。如果你的项目面向比较新的浏览器环境,它很好用;如果需要很稳的降级方案,最好还是保留一层普通背景兜底。
结尾不用记太多,先把这几条用熟
线性渐变适合方向明确的背景和遮罩,径向渐变适合光晕和聚焦,锥形渐变更偏向环形图形。大部分业务场景其实不需要把语法背全,先把方向、停点、透明度和多层叠加这几项用顺手,已经能解决很多界面上的'平'问题。
渐变最有价值的地方,不是做出多花哨的效果,而是让页面多一点层次感。能少用一张图片,就少一张;能用纯 CSS 解决,就别把简单的东西做重。

