码迷,mamicode.com
首页 > Web开发 > 详细

SVG 符号和 CSS 变量做出彩色图标

时间:2020-06-15 10:33:43      阅读:71      评论:0      收藏:0      [点我收藏+]

标签:div   sas   坐标   分配   dom   使用   code   没有   parent   

设置 SVG 符号图标

内嵌的 SVG 的问题在于它们的冗余。你肯定不想在每次使用同一个图标时复制粘贴所有的坐标。这显得笨拙,可读性差,难以维护。使用 SVG 符号图标,你只要复制整个 SVG 元素一次,然后你就可以用一个引用在任何地方实例化它们。从内嵌 SVG 开始,隐藏它,并用一个 <symbol> 包裹,然后加上 id 属性:

<svgxmlns="http://www.w3.org/2000/svg"style="display: none"><symbolid="my-first-icon"viewBox="0 0 20 20"><title>my-first-icon</title><pathd="..."/></symbol></svg>

 

一次包含完整的 SVG 标记并隐藏在 HTML 里。然后,只要用 <use> 元素来实例化这个图标就行了:

<svg>  <usexlink: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 的内容。??那我们该怎么做?我们怎样才能影响不在 DOM 中的子元素?

CSS 变量来帮忙

在 CSS 中,一些属性从祖先到孩子都继承了。如果你分配给 body 分配一个文本颜色,所有页面中的文本都会继承这个颜色,除非颜色被重写。祖先不知道孩子,但可继承的样式被传递下来。我们开始的示例中,继承了 fill 属性。再看一次,你会看到我们声明的 fill颜色被添加到实例中,而不是定义的 SVG。这就是我们能够为每个实例添加不同颜色的原因。现在问题来了:我们想要将不同的颜色传递给原始 SVG 的不同的路径,但我们只能继承一个 fill 属性。看看 CSS 变量。CSS 变量可以像其他属性那样声明在规则集里。你可以为它取任意的名字,并分配任意的有效的 CSS 值。然后你可以为它声明一些值或者任意的孩子属性,它能够被继承。

.parent {  --custom-property: red;  color:var(--custom-property);}

 

所有 .parent 的孩子都会有红色的文本。

.parent {  --custom-property: red;}.child {  color:var(--custom-property);}

 

所有嵌套在 .parent 的 .child 元素也会有红色的文本。现在将这个概念应用到我们的 SVG 符号。我们将在 SVG 定义的每个路径里用 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 变量。

我的 CSS 变量名应该叫什么?

在 CSS 中命名通常有两种方式:描述性的或者语义性的。描述性意味着什么颜色就叫什么:如果你存储 #ff0000,那就叫它 --red。语义性意味着这种颜色是怎么用的就叫什么。比如你用 #ff0000 填充咖啡杯把手,你就叫它 --cup-handle-color。描述性的名字可能是你下意识的选择。它看起来更清爽,因为 #ff0000 不仅可以用来填充咖啡杯把手,还可以为其他东西上色。当别的图标需要上红色时,一个 --red 的 CSS 变量是可以重用的。毕竟,这就是 CSS 实用至上原则的体现,它也的确是个好体制。问题在于,在我们的案例中我们不能粒度类应用到我们想要的样式。不能用实用至上原则,因为我们有每个图标的引用,我们必须通过类变量来为它们添加样式。使用语义化的名字,比如 --cup-handle-color 在这种情况下这样才比较有意义。当你想要改变某个图标的部分颜色时,你瞬间就能知道它是什么,应该重写成什么。类名和你分配的无论什么颜色都能保持关联。

默认或不默认

将你的图标设置成多种颜色作为默认状态是很吸引人的。用这种方式,你可以直接使用它们不需要添加额外的样式,只有在需要改动时,才会添加你自己的类。可以通过两种方式实现::root 以及 var() default.

:root

你可以用 :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-colorvar() default用来将 CSS 变量分配给某个属性的 var() 函数可以将第二个参数作为默认值。

<svgxmlns="http://www.w3.org/2000/svg"style="display: none">  <symbolid="my-first-icon"viewBox="0 0 20 20">    <title>my-first-icon</title>    <pathfill="var(--color-1, red)"d="..."/>    <pathfill="var(--color-2, blue)"d="..."/>    <pathfill="var(--color-3, green)"d="..."/>  </symbol></svg>

 

除非你定义 --color-1,--color-2 和 --color-3, 否则图标会使用默认的值为每个 <path> 填充颜色。这解决了之前使用 :root 时全局范围的问题,但是要注意:你现在使用了默认值,并且它正在生效。结果是,你不能够使用单个 fill 声明来定义单色的图标了。你必须为每个 CSS 变量分配颜色,一个一个地。设置默认值很有用,但它是种权衡。我建议你不要将这种做法成为一种习惯,只有当它在特定的项目有意义时才使用。

浏览器兼容

CSS 变量对于绝大多数现代浏览器都是兼容的,但正如你所想的那样,IE 浏览器完全不支持。甚至 IE 11 也不支持,自从 Edge 的开发被搁置后,它再也没机会赶上了。现在,仅仅因为一个浏览器不支持这个功能,这并不意味着你要推翻一切来迎合它。这种情形有更加优雅的做法:为现代浏览器提供多彩图标,为其他的老版本浏览器提供回滚的填充颜色。你想要做的是当 CSS 变量不支持时设置一个会起作用的声明,这可以通过为 fill 属性设置回滚颜色来实现:当支持 CSS 变量时,它不会生效,如果不支持,你的 fill 声明才会生效。如果你使用 Sass,可以抽象到@mixin 里:

@mixinicon-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 符号和 CSS 变量做出彩色图标

标签:div   sas   坐标   分配   dom   使用   code   没有   parent   

原文地址:https://www.cnblogs.com/xiewangfei123/p/13128916.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!