
用 background-image 实现渐变背景:线性渐变与多层背景的写法
CSS 渐变不是一张需要下载的图片,而是浏览器根据颜色和位置即时绘制的图像。把渐变写在 background-image 中,可以用较少的代码实现纯色过渡、按钮高光、卡片装饰和多层背景,也不必为每种尺寸额外准备图片资源。
本文以线性渐变为主,讲解 linear-gradient() 的方向与色标、多层背景的绘制顺序,以及它与 background-size、background-position 等属性的配合方式。渐变能做什么、不适合做什么,以及常见的透明度、层级和可访问性问题,也会逐一说明。
一、先理解 background-image 与渐变
background-image 接受一个或多个图像值。图像值可以是图片地址,也可以是由 CSS 绘制的渐变函数,例如 linear-gradient()、radial-gradient()。它们属于背景图像,不会取代元素本身的背景色、内容或布局。
最简单的线性渐变是从一种颜色过渡到另一种颜色:
.banner {
background-image: linear-gradient(#2463eb, #8b5cf6);
}
如果不指定方向,线性渐变默认从上到下。渐变是在元素的背景绘制区域中计算的;元素有多大,背景图像也会按相应的背景定位区域来铺放。若元素没有高度,或高度由内容决定,渐变仍然存在,但它的实际显示效果会受该元素尺寸影响。
渐变本身不设定元素的宽度、高度、内边距或圆角。它也不会自动提供内容对比度、响应式布局或交互效果。通常需要把背景规则与普通盒模型、文字颜色及布局样式一起编写。
二、linear-gradient() 的基本语法
linear-gradient() 的常见写法如下:
linear-gradient(方向, 色标1, 色标2, ...)
方向和颜色列表之间用逗号分隔。方向可以省略,也可以写角度,或使用 to 加方向关键字。颜色色标至少要有两个;一个色标描述一个颜色,也可以附带该颜色在渐变线上的位置。
1. 方向关键字
关键字描述渐变的终点方向。比如 to right 表示渐变朝右侧结束,颜色从左侧开始变化。可以组合水平和垂直方向:
.directions {
background-image:
linear-gradient(to right, #0f766e, #38bdf8);
}
.diagonal {
background-image:
linear-gradient(to bottom right, #f97316, #db2777);
}
.upward {
background-image:
linear-gradient(to top, #111827, #475569);
}
方向关键字中,to 后面不能写两个相反的方向,例如 to left right。可以写一个水平与一个垂直方向,例如 to top right。方向描述的是渐变的终点一侧,不是“颜色从哪个方向流过”的口语指令,理解这一点能避免把颜色顺序写反。
2. 角度
角度以 deg 等 CSS 角度单位书写。在线性渐变中,0deg 指向上方,角度增加时顺时针旋转;因此 90deg 指向右侧,180deg 指向下方。角度也可以使用 turn、grad 或 rad 等角度单位。
.angles {
background-image:
linear-gradient(90deg, #06b6d4, #2563eb);
}
.full-turn {
background-image:
linear-gradient(0.25turn, #06b6d4, #2563eb);
}
对同一尺寸的水平渐变,90deg 与 to right 表达相同方向。角度渐变的几何方向相对渐变绘制区域计算;元素形状改变时,视觉上的过渡长度和斜率也可能随之变化。若需求是“从左上角走到右下角”,可用 to bottom right 表意;若需求是固定角度,则使用角度值更直接。
3. 色标与位置
不写位置时,浏览器会根据色标数量分配位置。例如两个色标默认分别在渐变线的起点和终点,三个色标默认分布在起点、中间和终点。可以用百分比或长度显式指定位置:
.stops {
background-image:
linear-gradient(
to right,
#ef4444 0%,
#f59e0b 35%,
#fde047 70%,
#16a34a 100%
);
}
百分比通常更适合随容器尺寸缩放的背景。长度单位适合描述固定尺寸的过渡,但要注意:色标位置是沿渐变线定义的,不是元素左边距或上边距。位置也可以超出 0% 到 100% 的范围;这表示颜色变化范围延伸到渐变线的对应边界以外,并不等价于把元素尺寸设成负值。
色标位置可以相同,形成明显的颜色分界;也可以相隔较近,形成很窄的过渡区。位置顺序若出现递减,浏览器会按照 CSS 渐变的色标规则处理,而不是把它当作无效的普通坐标。因此,想要可读、易维护的设计时,通常应按从小到大的顺序排列位置。
.hard-edge {
background-image:
linear-gradient(
to right,
#111827 0%,
#111827 50%,
#f9fafb 50%,
#f9fafb 100%
);
}
上例在中点形成清晰分界。利用多个相邻色标还可以制作条纹,但若要规则重复的条纹,通常更适合使用 repeating-linear-gradient()。
三、用多层背景叠加装饰
background-image 可以接收逗号分隔的多个图像层。每一层既可以是渐变,也可以是图片;各层按书写顺序排列,第一层在最上方,后面的层依次位于下方。所有层都绘制在元素背景色之前,因此背景色不会盖住这些图像层。
下面叠加两条线性渐变:第一层绘制左上角的淡色光斑,第二层提供由深蓝到紫色的底色。
.hero {
min-height: 16rem;
padding: 2rem;
color: white;
background-color: #312e81;
background-image:
linear-gradient(
135deg,
rgb(255 255 255 / 28%),
transparent 48%
),
linear-gradient(
to right,
#1d4ed8,
#6d28d9
);
}
第一层出现在上方,所以半透明白色会叠加在下方的蓝紫渐变上。若把两层顺序调换,视觉结果会不同。多层背景适合在不增加额外元素的情况下,把底色、柔和高光、装饰色块和重复纹理组合起来。
1. 为每一层单独指定位置与尺寸
background-position、background-size、background-repeat 等背景属性也可以接收逗号分隔的列表。列表中的第一项对应最上层图像,第二项对应下一层,以此类推。属性值数量少于背景图像层数时,浏览器会循环使用该列表中的值。
例如,下面让第一层渐变占据一个较小区域,第二层渐变铺满背景:
.spotlight {
min-height: 18rem;
background-color: #111827;
background-image:
linear-gradient(
135deg,
rgb(96 165 250 / 75%),
transparent 70%
),
linear-gradient(
to bottom,
#1f2937,
#111827
);
background-size: 18rem 18rem, auto;
background-position: left top, center;
background-repeat: no-repeat, no-repeat;
}
这里 18rem 18rem 是第一层的背景尺寸;第二层的 auto 依照该层的默认背景尺寸处理。对渐变而言,背景图像没有固有尺寸,尺寸和定位更依赖背景绘制区域以及显式设置的 background-size。要获得稳定的局部光斑,显式写出尺寸通常比依赖默认值更清晰。
当背景层很多时,给每一层的尺寸、位置和重复方式都列出对应值,有助于减少维护错误。也可以将每层属性写成完整的 background 简写,但简写容易因为遗漏字段重置而产生意外,后文会说明。
2. 渐变叠加图片
渐变还可以覆盖在背景图片上。由于第一层在最上方,先写渐变、后写图片,可以给图片加一层颜色蒙版:
.photo-card {
min-height: 22rem;
color: white;
background-image:
linear-gradient(
to top,
rgb(0 0 0 / 78%),
transparent 65%
),
url("images/landscape.jpg");
background-position: center, center;
background-size: cover, cover;
background-repeat: no-repeat, no-repeat;
}
这种写法适合在背景图片底部增强文字可读性。不过它只能改变背景图像的显示效果,不能保证任意图片、任意裁剪情况下都达到足够的文字对比度。重要文本仍应通过真实文字颜色、背景或其他设计手段保证可读,并进行实际检查。
四、重复渐变与常见视觉效果
repeating-linear-gradient() 与 linear-gradient() 的参数思路相同,但会重复绘制色标定义的图案。它适合制作细条纹、网格线或刻度纹理。若色标间距没有形成完整的重复周期,结果可能不符合预期,因此要明确一个完整周期的起止位置。
.stripes {
min-height: 10rem;
background-image:
repeating-linear-gradient(
45deg,
#e2e8f0 0,
#e2e8f0 8px,
#cbd5e1 8px,
#cbd5e1 16px
);
}
上例每 16 像素重复一次,其中两种颜色各占 8 像素。想让条纹更细,可以缩短位置间隔;想改变倾斜方向,可以调整角度。大量高对比细纹可能造成视觉干扰,也可能影响文字阅读,不宜不加判断地铺在长段正文后面。
五、透明色标:避免不自然的过渡
关键字 transparent 表示完全透明的颜色,其颜色通道相当于透明黑色。在渐变中,如果从某个有色颜色过渡到 transparent,中间颜色可能经过带黑色通道的半透明颜色,出现发暗或发灰的边缘。
需要透明过渡且希望保留原颜色色相时,可以明确写出同色的透明版本。例如从半透明蓝色过渡到完全透明蓝色:
.blue-fade {
background-image:
linear-gradient(
to right,
rgb(37 99 235 / 90%),
rgb(37 99 235 / 0%)
);
}
也可以使用颜色函数的现代语法表达透明度,例如 rgb(37 99 235 / 0%)。为照顾需要支持较旧浏览器的项目,应结合项目目标环境确认语法支持情况。不要仅因为看到 transparent 简短,就假定它在所有场景都等同于“当前颜色的透明版本”。
六、background 简写的重置陷阱
background 是包含多个背景相关属性的简写。给它赋值时,未在本次简写中指定的背景子属性会回到相应初始值。比如先设置了多个背景层及其定位,之后又用一个简单的 background 覆盖,前面的背景图像、位置、重复方式等设置都可能被重置。
.panel {
background-image:
linear-gradient(to right, #0f766e, #0ea5e9);
background-position: center;
}
/* 这条简写会重设未明确写出的背景子属性 */
.panel--alternate {
background: #f8fafc;
}
如果只想改变底色,直接使用 background-color 通常更明确。如果确实要用简写,则应把需要保留的背景层和对应设置完整写入。尤其在组件样式分散于多个文件、多个选择器时,检查简写规则的覆盖顺序,能避免渐变突然消失或定位异常。
七、线性渐变不只有颜色,也要考虑尺寸与绘制区域
渐变背景会受到元素尺寸和背景绘制区域影响。背景默认绘制在边框内侧的区域,具体范围还可能受 background-origin、background-clip、边框与内边距影响。若元素带有圆角,背景的裁剪范围也会受到相应背景裁剪规则影响。
例如,想让渐变覆盖包括内边距在内的内容区域,默认设置通常就能满足;若需要它延伸到边框区域,可以调整 background-origin 或 background-clip。这两个属性含义不同:前者影响背景定位区域,后者影响背景绘制与裁剪区域。调试时不要把它们当作同一个“背景范围”开关。
.bordered {
padding: 1.5rem;
border: 6px solid transparent;
border-radius: 1rem;
background-image:
linear-gradient(#fff, #fff),
linear-gradient(135deg, #06b6d4, #7c3aed);
background-origin: padding-box, border-box;
background-clip: padding-box, border-box;
}
上例使用两层背景配合透明边框:第一层覆盖内边距区域,第二层覆盖边框盒,形成渐变边框效果。它展示的是 CSS 背景裁剪与层叠机制,不是渐变本身产生了真实边框。若边框宽度、圆角或背景层顺序变化,效果也会随之变化。
为避免渐变看起来“没出现”,先检查元素是否有可见尺寸、是否被后续规则覆盖、背景层顺序是否正确,以及渐变颜色是否与底色过于接近。必要时临时给元素加上明显的高度和纯色背景,分步骤定位问题。
八、常见错误与排查方法
错误一:把方向关键字写反
to right 指向右侧终点,因此第一种颜色出现在渐变线的另一端。若视觉方向与预期相反,先交换色标顺序或调整方向,不要同时随意修改角度与色标位置。
错误二:误以为百分比是元素坐标
色标位置百分比沿渐变线计算,不是元素宽度或高度的普通坐标。若目标是一个固定尺寸的小区域,应设置对应背景层的 background-size,并用 background-position 移动它。
错误三:把 background-size 当成渐变色标间距
background-size 控制背景图像层的尺寸,色标位置控制该渐变内部的颜色分布。两者影响不同。想让光斑更小,通常调整该层背景尺寸;想让颜色更快过渡,调整色标位置。
错误四:用多个背景时漏掉逗号
每个背景图像层之间需要逗号分隔。漏写逗号会让值不符合语法,整个声明可能被浏览器丢弃。可以把每一层单独换行,便于看清层数以及对应的大小和位置。
错误五:不理解图层顺序
逗号列表第一层在最上方。若用不透明的渐变覆盖图片,图片自然不可见;要让下层图片透出来,覆盖层需要有透明度。检查颜色的 alpha 通道,以及每层的书写顺序。
错误六:色标过多、过渡难以维护
堆叠大量色标未必能改善效果,反而难以解释和调整。先用少量关键颜色确定整体方向,再按需要添加中间色标。重复纹理优先考虑重复渐变,不要用几十个手工色标模拟周期图案。
错误七:将渐变当作内容信息的唯一载体
用渐变区分状态、表达警告或标注数据时,不能只依赖颜色。应同时使用文字、图标或其他可感知线索。装饰背景不需要替代内容语义;重要信息应由正常文档内容呈现。
九、适用场景与不适用场景
线性渐变适用于纯色之间的平滑过渡、按钮和横幅的装饰底色、卡片高光、图片文字蒙层,以及简单重复的条纹纹理。它特别适合颜色变化规则、无需精细纹理的图形,因为无需维护图片文件,也能随元素尺寸灵活调整。
如果背景需要复杂插画、真实材质、精确品牌图案或摄影细节,渐变并不适合取代专业图像资源。CSS 渐变只能描述规则的颜色变化,不会自动生成高质量纹理、阴影细节或复杂路径。对于动画,如果在色标或背景尺寸上频繁变化,也要评估渲染成本和设备表现;不要仅凭“它是 CSS”就认定动画一定便宜。
渐变背景不提供语义信息,也不具备图片的替代文本机制。若某幅图像承载必须理解的内容,不能把它仅仅做成 CSS 背景,然后假设辅助技术会把内容读出来。内容性图像应采用适合的 HTML 图像与替代文本;纯装饰背景则可用 CSS 渐变。
十、边界与兼容性说明
线性渐变属于 CSS 图像功能,现代浏览器普遍支持常用的 linear-gradient()、多层背景和基本色标写法。更细致的颜色语法、颜色插值方式或新语法特性,支持范围可能因浏览器版本而异。面向特定老旧设备时,应以项目要求的浏览器矩阵进行验证,而不是默认所有 CSS 新语法都可用。
渐变函数需要符合 CSS 语法:颜色值应合法,方向写法应有效,逗号和括号必须配对。无效声明通常会被浏览器忽略;这不一定会触发明显错误提示。开发时可在浏览器开发者工具的样式面板检查声明是否生效,并用目标浏览器实际测试。
渐变没有固有的宽度、高度或比例,不像位图那样携带天然尺寸信息。其呈现依赖背景尺寸和元素布局;设置 background-size: cover 或 contain 时,行为也应按背景图像的尺寸算法理解,不要把渐变当成一张永远固定比例的图片。对于简单铺满元素的渐变,通常不必额外设置 background-size;对于局部装饰层,则可以显式设置尺寸。
十一、安全使用注意事项
纯粹由颜色、方向和色标组成的渐变不会因为绘制本身而请求外部图片资源。它与 url() 不同;多层背景中若加入 url(),浏览器可能需要请求指定资源。不要把所有 background-image 值都笼统地认为没有网络请求。
CSS 渐变不是安全边界,也不能用来清理或验证不可信输入。如果应用把用户提供的字符串拼进样式、内联 style 属性或动态生成的样式表,必须按相应上下文进行严格验证与编码,不能假设“最终看起来只是颜色”就没有风险。更稳妥的做法是从固定的设计令牌或允许列表中选颜色和方向,而不是直接拼接任意 CSS 片段。
在支持受限或存在兼容性要求的系统中,应结合内容安全策略、样式注入防护和资源来源策略设计整体方案。渐变没有外部资源请求,不代表同一段动态 CSS 中的其他值安全,也不代表可以忽略输入处理。
十二、完整示例:渐变横幅与装饰光斑
下面的示例包含 HTML 与 CSS,可保存为本地文件直接打开。它使用两层背景绘制底色和局部装饰,并为容器设置最小高度、内边距和文字颜色。示例中的渐变是装饰性的,标题和说明仍以普通 HTML 文本提供。
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>线性渐变背景示例</title>
<style>
* {
box-sizing: border-box;
}
body {
margin: 0;
min-height: 100vh;
padding: 2rem;
font-family: system-ui, sans-serif;
background: #f1f5f9;
}
.hero {
max-width: 56rem;
min-height: 20rem;
margin: 0 auto;
padding: clamp(2rem, 6vw, 4rem);
display: flex;
flex-direction: column;
justify-content: flex-end;
color: #fff;
border-radius: 1.25rem;
background-color: #312e81;
background-image:
linear-gradient(
135deg,
rgb(255 255 255 / 24%),
transparent 42%
),
linear-gradient(
to right,
#1d4ed8,
#6d28d9
);
box-shadow: 0 1rem 2.5rem rgb(15 23 42 / 18%);
}
.hero h1 {
max-width: 14ch;
margin: 0 0 1rem;
font-size: clamp(2rem, 5vw, 3.5rem);
line-height: 1.1;
}
.hero p {
max-width: 42rem;
margin: 0;
line-height: 1.7;
color: rgb(255 255 255 / 92%);
}
</style>
</head>
<body>
<main class="hero">
<h1>用渐变表达界面层次</h1>
<p>底层负责颜色过渡,上层提供柔和高光。背景只是装饰,文字仍然是页面中可读取、可选择的真实内容。</p>
</main>
</body>
</html>
如果将它用于真实页面,可以先确定底层主渐变,再添加一层低对比度装饰;随后检查标题在不同屏幕尺寸、背景裁剪和颜色变化下是否清晰。尽量通过少量色标和清楚的图层顺序表达设计意图,而不是不断追加背景层掩盖问题。
结语
使用 background-image 编写线性渐变,核心是明确三个问题:渐变朝哪个方向延伸、颜色在什么位置变化、每一层位于其他背景的哪一侧。掌握方向与色标后,再用多层背景组合底色、透明高光和简单纹理;需要局部效果时,再配置相应层的尺寸、位置和重复方式。
写渐变时也要留意透明颜色的混合、背景简写的重置行为、元素实际尺寸、浏览器目标范围和文字对比度。渐变适合规则的颜色装饰,不是复杂图像、语义内容或安全校验的替代品。先用最少的背景层实现需求,再根据实际显示结果增补样式,通常会比一次写出很长的渐变表达式更容易维护。







