标签:div sas 坐标 分配 dom 使用 code 没有 parent
内嵌的 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 中,一些属性从祖先到孩子都继承了。如果你分配给 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 中命名通常有两种方式:描述性的或者语义性的。描述性意味着什么颜色就叫什么:如果你存储 #ff0000
,那就叫它 --red
。语义性意味着这种颜色是怎么用的就叫什么。比如你用 #ff0000
填充咖啡杯把手,你就叫它 --cup-handle-color
。描述性的名字可能是你下意识的选择。它看起来更清爽,因为 #ff0000
不仅可以用来填充咖啡杯把手,还可以为其他东西上色。当别的图标需要上红色时,一个 --red
的 CSS 变量是可以重用的。毕竟,这就是 CSS 实用至上原则的体现,它也的确是个好体制。问题在于,在我们的案例中我们不能粒度类应用到我们想要的样式。不能用实用至上原则,因为我们有每个图标的引用,我们必须通过类变量来为它们添加样式。使用语义化的名字,比如 --cup-handle-color
在这种情况下这样才比较有意义。当你想要改变某个图标的部分颜色时,你瞬间就能知道它是什么,应该重写成什么。类名和你分配的无论什么颜色都能保持关联。
将你的图标设置成多种颜色作为默认状态是很吸引人的。用这种方式,你可以直接使用它们不需要添加额外的样式,只有在需要改动时,才会添加你自己的类。可以通过两种方式实现::root 以及 var() default.
你可以用 :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() 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; };}
标签:div sas 坐标 分配 dom 使用 code 没有 parent
原文地址:https://www.cnblogs.com/xiewangfei123/p/13128916.html