Saber 酱的抱枕

Fly me to the moon

08/9
2024
软件

CSS 使用 SVG 图像作为背景图片的一些经验

no_lazy

本站右上角的几个图标以前是 PNG 格式的背景图片,最近我在优化网站的配色,需要这里的图标能根据需要变色,所以就需要把它们换成 SVG 格式。下面是一些蛋疼的经验。

设置为背景图片

这个很简单,只要把 svg 文件设置为按钮的 background 就可以了,比如下面的按钮:

{ background: url(/f/tg.svg); }

提示:本文里出现的按钮是真实的 button 元素,可以在上面右键然后选择“检查”,在开发者工具查看其样式。

设置图标的颜色

上面的按钮我没有设置默认的填充颜色,你可能看到它是黑色的,这是浏览器的默认行为。如果想让它显示为红色该怎么做呢?

由于上面的 SVG 是作为 CSS 的背景图片显示的(而非 HTML 页面上的 SVG 标签),因此在 CSS 里设置 fill: red; 是无效的。

我们需要在 SVG 里添加类似 fill = "red" 的代码,例如添加到 path 标签里:

<svg
  t="1722876190552"
  class="icon"
  viewBox="0 0 1024 1024"
  version="1.1"
  xmlns="http://www.w3.org/2000/svg"
  width="32"
  height="32"
>
  <path
    fill = "red"
    d="M417.28 795.733333l11.946667-180.48 327.68-295.253333c14.506667-13.226667-2.986667-19.626667-22.186667-8.106667L330.24 567.466667 155.306667 512c-37.546667-10.666667-37.973333-36.693333 8.533333-55.466667l681.386667-262.826666c31.146667-14.08 61.013333 7.68 49.066666 55.466666l-116.053333 546.56c-8.106667 38.826667-31.573333 48.213333-64 30.293334L537.6 695.466667l-84.906667 82.346666c-9.813333 9.813333-17.92 17.92-35.413333 17.92z"
  ></path>
</svg>

注意:下面开始蛋疼起来了,属于拓展知识。

使用遮罩来控制图标的颜色

上面我们使用了 fill 来设置图标的颜色,但这存在一个问题:颜色值被硬编码到 SVG 图标里了,修改起来不方便。

假设我有 5 个 SVG 图标,都设置为红色 fill = "red" ,但现在需要改为绿色,那就需要打开这 5 个 SVG 文件进行修改。

有没有办法不修改 SVG 文件,而是通过 CSS 来控制它的颜色呢?有办法,使用遮罩可以做到。

比如下面的红色图标:

它的红色是怎么来的呢?不是它 fill 的,而是 button 的背景颜色。

{
  --svg: url('/f/tg.svg') no-repeat;
  /* background-image: var(--svg); */
  background-color: red;
  -webkit-mask: var(--svg);
  mask: var(--svg);
}

原理也很简单,只有 2 部分:

  1. 给按钮设置背景颜色
  2. 把 SVG 图像用作按钮的 mask(而非背景图片)

这样,SVG 的路径会作为 button 的遮罩,只显示路径内的内容。这样你看到的颜色实际上是 button 的背景颜色,而形状是 SVG 的路径。

修改图标显示的颜色

当你需要改变图标的颜色时,只需要修改 button 的背景颜色即可。这样我们就控制了 SVG 图标(看上去)的颜色。

使用这个方法,我们不仅可以方便的修改 SVG 图标的颜色,还可以有更多动态效果,只要给 button 添加颜色变化的效果即可。

如果你愿意的话,完全可以给 button 做个 CSS 动画,不过通常我们只需要设置按钮的 hover、active 状态即可。比如我让这个按钮在鼠标放上去时变成绿色,点击时变成蓝色:

#t3 {
  background-color: red;
}
#t3:hover {
  background-color: green;
}
#t3:active {
  background-color: blue;
}

控制图标作为背景图片的表现

通过 mask 使用 SVG 时需要注意:由于此时 SVG 并没有被设置为背景图片,因为如果你要设置某些 background 的属性如 center no-repeat,需要在 mask 属性里设置,而非在 button 上的 background 里设置 ,因为此时 SVG 并不是背景图片。

示例:

{ mask: url('/f/tg.svg') center no-repeat; }

其语法和 background 一样。

另外,如果你想使用 background-size 属性调整图标的大小(但此时这是无效的),也需要通过 mask 设置,如:

{ mask: url('/f/tg.svg') center center / 80% no-repeat; }
/* mask 的属性也有单独设置的形式,不是一定要使用缩写,如: */
{ mask-size: 80%; }

还有个扭曲的方式来调整这个图标的大小,就是使用变形,如 transform: scale(0.8);,但这会导致整个 button 的尺寸缩小为原本的 80%,可能会影响布局,所以不推荐使用。

让按钮和图标使用不同的颜色

下图里,按钮是具有白色背景的,而图标是紫红色的:

no_lazy

按照上面 mask 的方式,图标看上去的颜色实际上是按钮的背景色,那么图标也应该是白色的才对。图上的效果是怎么实现的?

其实很简单,这就是两个元素:按钮是个普通的白色按钮,而 SVG 图标是在另一个元素上,这样就可以给 SVG 设置不同的颜色了。

至于怎么让 SVG 在另一个元素上呢?最简单的办法就是在 CSS 里使用 button 的 ::after 伪元素。

如下:

#t4 {
 position: relative;
 background-color: #fff;
 border: 1px solid #aaa;
 border-radius: 32px;
}
#t4::after {
 background-color: #de2c67;
 content: '.';
 font-size: 0px;
 position: absolute;
 left: 0;
 top: 0;
 width: 100%;
 height: 100%;
 --svg: url('/f/tg.svg') 0px center/ 90% no-repeat;
 -webkit-mask: var(--svg);
 mask: var(--svg);
}

注意:
有些元素是没有 ::after 伪元素的,主要是“替换元素”,如 img input。所以如果它们本身就具有背景颜色,又需要把 SVG 图标显示为另一种颜色,那么就需要使用一个真正的元素来显示 SVG 图标。

目前我就探索了这么多,结束蛋疼!

使用 CSS 变量设置颜色值

当多个 CSS 选择器使用了同一种颜色,并且具有联动效果时(也就是说要变就一起变),可以把这个颜色值做成 CSS 变量,以后修改这些元素的颜色时只需要修改这一处变量就行了,很方便。

示例:

:root {
  --color-icon: red;
}
button.icon1 {
  background-color: var(--color-icon);
}
h1.title {
  color: var(--color-icon);
}
svg.icon2 {
  fill: var(--color-icon);
}

CSS 使用 SVG 图像作为背景图片的一些经验

    1. saber 文章作者
      Google Chrome 127Google Chrome 127WindowsWindows

      确实是个好办法,我之前没怎么用过,刚才看了下 Font Awesome 里面已经包含了这几个图标,不过 svg 的方式在图标选择上会自由一些。以后可以试试~

      回复
            1. saber 文章作者
              Google Chrome 127Google Chrome 127WindowsWindows

              多了个制作字体的步骤,比直接使用 svg 麻烦。我想起来还有个 iconfont 的方式,它是需要用到 JS 的,实际上也没简单多少。
              文中的方式只需要修改 CSS,对我来说更方便。因为有的按钮是主题的 PHP 代码生成的,修改它们的 class 名是个额外的工作,要么从 PHP 源码修改,要么前台用 JS 修改,不如直接不改省事。

              回复
  1. zhijiexv
    Google Chrome 126Google Chrome 126Android 10Android 10

    最近用的什么梯子,有没有推荐便宜好用的。之前那个农家有风小院好像挂掉了全线路红,我试了试重新挂链接、下了他那个自己的客户端也没用,官网也没公告啥的。最近逛iwara比较多备用梯子的稳定太差不好用诶

    回复