时间:2023-07-05 21:00:01 | 来源:网站运营
时间:2023-07-05 21:00:01 来源:网站运营
手把手教你用 SVG 符号和 CSS 变量做出彩色图标:简评:使用图片和 CSS 样式来制作网页图标的日子已经过去了,随着网页字体的爆发,图标字体成为展示图标的第一解决方案。字体都是向量,所以你不必担心分辨率的问题。它们能作为文本来用 CSS 属性修饰,所以你能够完全掌控它们的大小,颜色以及样式。还可以添加变换,效果以及装饰比如旋转,下划线或阴影。
太长,不读:这篇文章将深入探讨怎么做以及为什么。如果你想理解整个过程,就继续阅读。如果想直接查看代码,可以点击 CodePen.
<svg xmlns="http://www.w3.org/2000/svg" style="display: none"> <symbol id="my-first-icon" viewBox="0 0 20 20"> <title>my-first-icon</title> <path d="..." /> </symbol></svg>
一次包含完整的 SVG 标记并隐藏在 HTML 里。<svg> <use xlink:href="#my-first-icon" /></svg>
这样就可以展示你之前的 SVG 图标了:xlink:href
属性:这是你的实例和原始的 SVG 之间的链接。xlink:href
是一个被弃用的 SVG 属性。即使大多数浏览器仍然支持,你都应该使用 href
来代替它。问题是,有些浏览器比如 Safari 还不支持通过 href
属性引用 SVG 资源,所以你还要提供 xlink:href
属性。color
属性对于 SVG 图标没有任何作用:你必须使用 fill
属性来定义一个颜色。这意味着它们不像图标字体那样继承父类的文本颜色,但你仍然可以用 CSS 来为它们添加样式。// HTML<svg class="icon"> <use xlink:href="#my-first-icon" /></svg>// CSS.icon { width: 100px; height: 100px; fill: red;}
这里,你可以用不同的填充颜色创建另一个同样的图标实例。// HTML<svg class="icon icon-red"> <use xlink:href="#my-first-icon" /></svg><svg class="icon icon-blue"> <use xlink:href="#my-first-icon" /></svg>// CSS.icon { width: 100px; height: 100px;}.icon-red { fill: red;}.icon-blue { fill: blue;}
这会起作用,但不是我们确切想要的。到这里,我们刚才完成的步骤可以得到一个常规的图标字体。我们想要的是对于图标的每个部分可以有不同的颜色。我们想要用不同的颜色填充每个 path 而不用更改其他实例,必要的时候可以重写。// HTML<svg xmlns="http://www.w3.org/2000/svg" style="display: none"> <symbol id="my-first-icon" viewBox="0 0 20 20"> <title>my-first-icon</title> <path class="path1" d="..." /> <path class="path2" d="..." /> <path class="path3" d="..." /> </symbol></svg><svg class="icon icon-colors"> <use xlink:href="#my-first-icon" /></svg>// CSS.icon-colors .path1 { fill: red;}.icon-colors .path2 { fill: green;}.icon-colors .path3 { fill: blue;}
然而这并没什么用。.path1
, .path2
和 .path3
添加样式,就好像它们被 .icon-colors
嵌套一样,但技术上来说并非如此。<use>
不是一个被你定义的 SVG 的占位符。 它是一个引用,复制了指向暗处的 DOM 的内容。?body
分配一个文本颜色,所有页面中的文本都会继承这个颜色,除非颜色被重写。祖先不知道孩子,但可继承的样式被传递下来。fill
属性。再看一次,你会看到我们声明的 fill
颜色被添加到实例中,而不是定义的 SVG。这就是我们能够为每个实例添加不同颜色的原因。fill
属性。.parent { --custom-property: red; color: var(--custom-property);}
所有 .parent
的孩子都会有红色的文本。.parent { --custom-property: red;}.child { color: var(--custom-property);}
所有嵌套在 .parent
的 .child
元素也会有红色的文本。fill
属性,然后把它们的值设置为不同的 CSS 变量。这样一来,我们就能分配不同的颜色了。// HTML<svg xmlns="http://www.w3.org/2000/svg" style="display: none"> <symbol id="my-first-icon" viewBox="0 0 20 20"> <title>my-first-icon</title> <path fill="var(--color-1)" d="..." /> <path fill="var(--color-2)" d="..." /> <path fill="var(--color-3)" d="..." /> </symbol></svg><svg class="icon icon-colors"> <use xlink:href="#my-first-icon" /></svg>// CSS.icon-colors { --color-1: #c13127; --color-2: #ef5b49; --color-3: #cacaea;}
然后……大功告成!?// HTML<svg class="icon icon-colors-alt"> <use xlink:href="#my-first-icon" /></svg>// CSS.icon-colors-alt { --color-1: brown; --color-2: yellow; --color-3: pink;}
如果你只想使用单色的图标,你不用在每个 CSS 变量里重复相同的颜色。你可以使用单个 fill
来代替:因为 CSS 变量没有被定义,所以将会回滚到你的 fill
声明。.icon-monochrome { fill: grey;}
你的 fill
声明会起作用因为 fill
属性的值在原始的 SVG 上是没有定义的 CSS 变量。#ff0000
,那就叫它 --red
。语义性意味着这种颜色是怎么用的就叫什么。比如你用 #ff0000
填充咖啡杯把手,你就叫它 --cup-handle-color
。#ff0000
不仅可以用来填充咖啡杯把手,还可以为其他东西上色。当别的图标需要上红色时,一个 --red
的 CSS 变量是可以重用的。毕竟,这就是 CSS 实用至上原则的体现,它也的确是个好体制。--cup-handle-color
在这种情况下这样才比较有意义。当你想要改变某个图标的部分颜色时,你瞬间就能知道它是什么,应该重写成什么。类名和你分配的无论什么颜色都能保持关联。:root
里定义你所有的 CSS 变量。这样一来可以把所有的变量放在同一个地方,并允许你“共享“类似的颜色。 :root
有最低的优先权,所以很容易可以重写它。:root { --color-1: red; --color-2: green; --color-3: blue; --color-4: var(--color-1);}.icon-colors-alt { --color-1: brown; --color-2: yellow; --color-3: pink; --color-4: orange;}
然而,这种方法有一些主要的缺点。首先,让颜色的定义和它们各自的图标分离会变得混乱。当你想要重写它们时,你必须在 :root
和当前的类之间往返。更重要的是,它不会限制你的 CSS 变量,从而避免你使用相同的名字。--fill-color
。它简单易懂,当你只想用一种颜色填充所有的图标时,这种方式也比较行得通。如果我必须在 :root
中声明所有的变量,我不能有多个 --fill-color
。我必须定义 --fill-color-1
, --fill-color-2
等等,或者使用命名空间比如 --star-fill-color
, --cup-fill-color
。var()
函数可以将第二个参数作为默认值。<svg xmlns="http://www.w3.org/2000/svg" style="display: none"> <symbol id="my-first-icon" viewBox="0 0 20 20"> <title>my-first-icon</title> <path fill="var(--color-1, red)" d="..." /> <path fill="var(--color-2, blue)" d="..." /> <path fill="var(--color-3, green)" d="..." /> </symbol></svg>
除非你定义 --color-1
,--color-2
和 --color-3
, 否则图标会使用默认的值为每个 <path>
填充颜色。这解决了之前使用 :root
时全局范围的问题,但是要注意:你现在使用了默认值,并且它正在生效。结果是,你不能够使用单个 fill
声明来定义单色的图标了。你必须为每个 CSS 变量分配颜色,一个一个地。fill
属性设置回滚颜色来实现:当支持 CSS 变量时,它不会生效,如果不支持,你的 fill
声明才会生效。如果你使用 Sass,可以抽象到@mixin
里:@mixin icon-colors($fallback: black) { fill: $fallback; @content;}
现在我们可以定义我们的颜色方案而不用担心浏览器兼容问题了。.cup { @include icon-colors() { --cup-color: red; --smoke-color: grey; };}.cup-alt { @include icon-colors(green) { --cup-color: green; --smoke-color: grey; };}
如果你想要了解更多 SVG 的内容,我推荐阅读 Sara Soueidan 的博客。原文链接:Let’s make multi-colored icons with SVG symbols and CSS variables
关键词:变量,把手,符号,彩色