头图
欢迎关注公众:前端侦探

分享一些渐变的实际案例。

最近在工作中碰到一个这样的进度条,如下

image-20250510120005611

和一般进度条不同的是,上面多了很多小圆点,每个小圆点代表一个进度。

由于是完全自适应的,圆点可以自定义数量,宽度也能自动分配,就像这样

image-20250510120337327

所以不能直接切图实现。

这时,很多同学可能会想到用很多标签来实现这些小圆点

<div class="progress">
  <i></i>
  <i></i>
  <i></i>
  <i></i>
  ...
</div>

然后用flex布局就能实现均等分布了。

确实也能实现,不过总觉得用一个标签来实现这样一个装饰性的小圆点有点过于冗余了,不够优雅。

那还有其他方式吗?那当然要试一试强大的CSS渐变了,仅需一次平铺就能实现上述效果,一起看看吧

一、渐变平铺最小单元

要使用背景平铺,最关键要搞清楚最小平铺单元。

拿上面这个例子,你觉得最小平铺单元是哪个呢?

image-20250510131644462

答案是C

其实这里有个技巧,只需要收尾相连,能够覆盖整个容器,就可以当做最小平铺单元

image-20250510133143094

所以现在的问题就变成了,如何绘制这样一个圆孔?(注意,这里的尺寸是动态的)

image-20250510133605654

二、径向渐变

这是一个从白色到透明的径向渐变

.progress {
  background: radial-gradient(circle at 8px 50%, #fff 2px, transparent 2px) #ccc
}

示意如下

image-20250511131643955

渐变中心点上下是居中的,距离左边是 8px,所以是circle at 8px 50%,然后就是关键点了,当两个分界点重合时,就能形成边界分明的圆形

image-20250510140236109

效果如下

image-20250510140801906

现在只有一个圆点,这是因为默认背景尺寸是100%,撑满了整个容器,所以需要手动改变背景尺寸,比如我们设置

.progress {
  /**/
  background-size: 50px 100%
}

效果如下

image-20250510142344997

当然这里不能写死,能够自由控制圆点数量,用一个变量来表示--total: 10,那么平铺单元的尺寸就是

.progress {
  /**/
  --total: 10;
  --step: calc( (100% - 16px) / (var(--total) - 1); /*注意临界值*/
  background-size: var(--step) 100%
}

这样就能随意控制数量了,效果如下

image-20250510142840310

三、自适应SVG

虽然径向渐变实现代码很少,但很多同学表示渐变太难以上手,有没有更容易得方式呢?还可以试试自适应的SVG

我们在设计软件里绘制这样一个图形,注意整体轮廓,比如 Figma

image-20250510143243345

然后直接拷贝这段SVG,如下

<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="8" cy="8" r="2" fill="white"/>
</svg>

我们需要对这段SVG做一点小小的改动,将宽高改为100%,去除viewBox属性

关于这个SVG小技巧,可以参考之前这篇文章:不一样的SVG!SVG在CSS背景平铺中的应用
<svg width="100%" height="100%" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="8" cy="8" r="2" fill="white"/>
</svg>

接着将这段SVG转为内联形式,直接用到背景中

.progress {
  /**/
  --total: 10;
  --step: calc( (100% - 16px) / (var(--total) - 1); 
  background: url("data:image/svg+xml,%3Csvg fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Ccircle cx='8' cy='8' r='2' fill='%23fff'/%3E%3C/svg%3E") #ccc;
  background-size: var(--step) 100%
}

也能达到相同的效果

image-20250510142840310

相比前面的方式,这种方式可以不用考虑繁杂的径向渐变语法

四、当前进度

除了背景图案,还需要当前进度,我们可以再设置一个变量--progress: 3,表示位于第几个圆点处

我们可以再叠加一层线性渐变来实现当前进度。这里的进度尺寸其实就是最小单元尺寸 * 当前进度,具体实现如下

.progress{
  background:
    radial-gradient(circle at 8px 8px, #fff 2px, transparent 2px) 0 0 / var(--step) 100%,
    linear-gradient(#FF5E1A, #FF5E1A) 0 0 / calc((var(--progress) - 1) * var(--step) + 8px) 100% no-repeat #ccc;
}

效果如下

image-20250510145631986

然后是一个当前进度的点,可以直接用伪元素实现

.progress::after {
  content: '';
  position: absolute;
  box-sizing: border-box;
  width: 16px;
  height: 16px;
  border: 1px solid #fff;
  background-color: #FF5E1A;
  transition: 0.3s;
  left: calc((var(--progress) - 1) * var(--step));
}

效果如下

image-20250510150809099

我们可以随意改变这两个变量来自适应各种场景

Kapture 2025-05-10 at 15.21.27

你也可以访问在线demo真实体验:https://codepen.io/xboxyan/pen/MYYPyMZ

五、还可以应用到slider上

使用渐变的好处是可以用在各种场景上,没有html结构限制,比如input type="range",实现一个自定义样式的滑动选择器

<input type="range">

不同的是需要自定义::-webkit-slider-runnable-track::-webkit-slider-thumb,具体实现如下

[type="range"] {
  --total: 20;
  --progress: 3;
  --step: calc((100% - 16px) / (var(--total) - 1));
  -webkit-appearance: none;
  appearance: none;
  margin: 0;
  outline: 0;
  background-color: transparent;
  width: 300px;
  overflow: hidden;
  height: 16px;

}
[type="range"]::-webkit-slider-runnable-track {
  height: 100%;
  position: relative;
  border-radius: 16px;
  background:
    radial-gradient(circle at 8px 8px, #fff 2px, transparent 2px) 0 0 / var(--step) 100%,
    linear-gradient(#FF5E1A, #FF5E1A) 0 0 /
      calc((var(--progress) - 1) * var(--step) + 8px) 100% no-repeat,
    #ccc;
}
[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
appearance: none;
  box-sizing: border-box;
  width: 16px;
  height: 16px;
  border: 1px solid #fff;
  background-color: #FF5E1A;
  border-radius: 16px;
  background-size: 10px;
  background-position: center center;
  background-repeat: no-repeat;
}

效果如下

Kapture 2025-05-10 at 18.20.08

现在当前进度还没跟上,需要通过JS更新一下

<input type="range" oninput="this.style.setProperty('--progress', this.value);">

这样就实现了一个自定义滑到选择器了

Kapture 2025-05-10 at 18.23.12

你也可以访问在线demo真实体验:https://codepen.io/xboxyan/pen/bNNmwZp

六、总结一下

以上就本文的全部内容了,一些关于渐变的实际应用,你学到了吗?下面总结一下

  1. html标签来实现一个个装饰性的小圆点有点过于冗余了,不够优雅
  2. CSS 渐变天然支持内容平铺,可以避免大量无意义的标签
  3. 小圆点本质上是一个从白色到透明的径向渐变
  4. 可以使用CSS变量自动计算需要平铺的背景尺寸
  5. 除了使用径向渐变,还可以使用自适应SVG来实现,可以不用考虑繁杂的径向渐变语法
  6. 当前进度可以再叠加一层线性渐变实现
  7. 使用渐变的好处是可以用在各种场景上,没有html结构限制,可以实现一个自定义样式的滑动选择器

总之,渐变几乎是万能的,如果你想进阶学习CSS,一定少不了渐变。最后,如果觉得还不错,对你有帮助的话,欢迎点赞、收藏、转发 ❤❤❤


XboxYan
18.3k 声望14.1k 粉丝