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 127Windows 10/11Windows 10/11

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

      回复
        1. saber 文章作者
          Google Chrome 127Google Chrome 127Windows 10/11Windows 10/11

          自己制作字体图标吗?那是不是还得引入字体文件,有点头大

          回复
            1. saber 文章作者
              Google Chrome 127Google Chrome 127Windows 10/11Windows 10/11

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

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

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

    回复

评论 zhijiexv 撤销评论