CSS 渐变生成器:从线性到圆锥,彻底搞懂 gradient 的实现原理

0 阅读5分钟

三种渐变类型,本质都是"颜色插值"

在这里插入图片描述

CSS 支持三种渐变:linear-gradient(线性)、radial-gradient(径向)、conic-gradient(圆锥)。它们的核心机制是一样的——在起点和终点之间进行颜色插值。

线性渐变:最简单也最常用

/* 最简形式 */
background: linear-gradient(#667eea, #764ba2);

/* 指定方向 */
background: linear-gradient(135deg, #667eea, #764ba2);

/* 多个颜色节点 */
background: linear-gradient(90deg, #ff6b6b, #feca57, #ff9ff3);

线性渐变的关键参数是角度。0deg 是从下往上,90deg 是从左往右,135deg 是左下到右上。这个角度定义的是渐变线的方向,颜色沿着这条线分布。

角度计算有个容易踩的坑:CSS 的角度是顺时针的,但数学上的角度是逆时针的。所以 linear-gradient(45deg) 和 SVG 的 transform="rotate(45)" 方向是一致的,但和 Canvas 的 rotate() 相反。

径向渐变:从中心向外扩散

/* 圆形径向渐变 */
background: radial-gradient(circle, #48dbfb, #006ba6);

/* 椭圆形 */
background: radial-gradient(ellipse, #1dd1a1, #10ac84);

/* 指定圆心位置 */
background: radial-gradient(circle at 30% 70%, #5f27cd, #341f97);

径向渐变的形状由 circleellipse 决定。at 关键字指定圆心位置,可以是百分比、像素值或关键字(centertop left 等)。

实现径向渐变时,我发现一个有趣的边界情况:当容器是正方形时,circleellipse 看起来一样;但当容器是长方形时,ellipse 会自动拉伸以填满容器,而 circle 保持正圆。

圆锥渐变:围绕中心点旋转

/* 基础圆锥渐变 */
background: conic-gradient(#ff6348, #ff4757, #ffa502, #ff6348);

/* 指定起始角度 */
background: conic-gradient(from 45deg, #00d2d3, #5f27cd, #ff9ff3, #00d2d3);

/* 指定中心点 */
background: conic-gradient(from 0deg at 50% 50%, #2f3542, #57606f, #747d8c, #2f3542);

圆锥渐变是 CSS Images Module Level 4 新增的,用于创建类似雷达图或饼图的效果。颜色围绕中心点旋转分布,from 指定起始角度。

注意圆锥渐变的最后一个颜色必须和第一个颜色相同,否则会有明显的接缝。这是因为渐变是 360 度闭环的。

颜色节点的高级用法

指定位置

颜色节点可以指定具体位置,精确控制渐变过渡:

/* 颜色在 30% 和 70% 处过渡 */
background: linear-gradient(90deg, 
  #667eea 0%, 
  #764ba2 30%, 
  #ff9ff3 70%, 
  #feca57 100%
);

硬边缘

如果两个颜色节点位置相同,就没有过渡,形成硬边缘:

/* 条纹效果 */
background: linear-gradient(90deg,
  #667eea 0%, #667eea 25%,
  #764ba2 25%, #764ba2 50%,
  #ff9ff3 50%, #ff9ff3 75%,
  #feca57 75%, #feca57 100%
);

这个技巧常用于创建条纹背景、格子图案。

透明度渐变

渐变支持 rgba()#rrggbbaa 格式,实现透明度过渡:

/* 从透明到不透明 */
background: linear-gradient(180deg, 
  rgba(102, 126, 234, 0), 
  rgba(118, 75, 162, 1)
);

这在做遮罩层、图片上方的文字背景时特别有用。

实现在线生成器的技术细节

实时预览

核心是监听颜色、角度、类型的变化,实时计算 CSS 字符串:

const generateGradient = useCallback(() => {
  const colorStops = colors.join(', ')
  
  switch (gradientType) {
    case 'linear':
      return `linear-gradient(${angle}deg, ${colorStops})`
    case 'radial':
      return `radial-gradient(circle, ${colorStops})`
    case 'conic':
      return `conic-gradient(from ${angle}deg, ${colorStops})`
  }
}, [colors, gradientType, angle])

随机渐变

生成随机颜色时,我用了一个简单但有效的方法:

const randomColor = () => {
  return '#' + Math.floor(Math.random() * 16777215)
    .toString(16)
    .padStart(6, '0')
}

167772150xFFFFFF,即 24 位颜色的最大值。padStart(6, '0') 确保不足 6 位时前面补零。

但纯随机生成的颜色往往不好看。更好的方法是使用 HSL 色彩空间,限制饱和度和亮度范围:

const randomColorHSL = () => {
  const h = Math.floor(Math.random() * 360)
  const s = 60 + Math.floor(Math.random() * 30) // 60-90%
  const l = 50 + Math.floor(Math.random() * 20) // 50-70%
  return `hsl(${h}, ${s}%, ${l}%)`
}

这样生成的颜色更鲜艳、更协调。

预设渐变

我收集了一些常用的渐变组合:

const PRESET_GRADIENTS = [
  { name: '日落', colors: ['#ff6b6b', '#feca57', '#ff9ff3'] },
  { name: '海洋', colors: ['#48dbfb', '#0abde3', '#006ba6'] },
  { name: '森林', colors: ['#1dd1a1', '#10ac84', '#00d2d3'] },
  { name: '紫霞', colors: ['#5f27cd', '#341f97', '#9980fa'] },
]

这些预设来自 UI Gradients 等网站,都是设计师精选的配色。

浏览器兼容性

现代浏览器对三种渐变的支持都很好:

  • linear-gradient: IE10+,所有现代浏览器
  • radial-gradient: IE10+,所有现代浏览器
  • conic-gradient: Chrome 69+, Firefox 83+, Safari 12.1+

如果需要支持旧浏览器,可以用 linear-gradient 作为 fallback:

background: #667eea;
background: conic-gradient(from 45deg, #667eea, #764ba2);

性能优化

渐变本身是 GPU 加速的,性能开销很小。但有几个注意点:

  1. 避免过多颜色节点:每个节点都会增加计算量,一般不超过 5 个
  2. 避免频繁更新:如果渐变需要动画,用 CSS @property 而不是 JS
  3. 大容器慎用径向渐变:径向渐变需要计算每个像素到圆心的距离,大容器可能卡顿

最终工具

基于以上研究,我做了一个 CSS 渐变生成器

  • 支持线性、径向、圆锥三种类型
  • 实时预览 + CSS 代码生成
  • 8 个精选预设渐变
  • 随机生成功能

核心代码不到 200 行,但把 CSS gradient 的各种用法都覆盖了。希望这篇文章能帮你理解渐变的原理,下次遇到复杂渐变需求时不再迷茫。


相关工具:CSS 变量生成器 | Flexbox 生成器