用 background-image 实现渐变背景:线性渐变与多层背景的写法

百科问答13小时前发布 jdkjadmin
0 00
用 background-image 实现渐变背景:线性渐变与多层背景的写法

用 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 编写线性渐变,核心是明确三个问题:渐变朝哪个方向延伸、颜色在什么位置变化、每一层位于其他背景的哪一侧。掌握方向与色标后,再用多层背景组合底色、透明高光和简单纹理;需要局部效果时,再配置相应层的尺寸、位置和重复方式。

写渐变时也要留意透明颜色的混合、背景简写的重置行为、元素实际尺寸、浏览器目标范围和文字对比度。渐变适合规则的颜色装饰,不是复杂图像、语义内容或安全校验的替代品。先用最少的背景层实现需求,再根据实际显示结果增补样式,通常会比一次写出很长的渐变表达式更容易维护。

© 版权声明

相关文章