SVG USE元素和:悬停样式

时间:2022-11-20 18:41:15

I'm trying to use CSS :hover pseudoclass to style SVG elements embeded from <defs> by <use> tag, but it doesn't seem to work :-/ Here's my code:

我正在尝试使用CSS:hover伪类来设置由 标签从 嵌入的SVG元素,但它似乎不起作用: - /这是我的代码:

<!DOCTYPE HTML>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
 <meta http-equiv="content-type" content="application/xhtml+xml; charset=utf-8"/>
 <style type="text/css" media="screen">
        .active { fill: #0BE; }
        .active:hover { opacity: 0.8; stroke: #F0F; stroke-width: 4px; }
        .active2 #p2 { fill: #0BE; }
        .active2:hover #p2 { opacity: 0.8; stroke: #F0F; stroke-width: 4px; }
        #p2:hover { opacity: 0.8; stroke: #F0F; stroke-width: 4px; }
    </style>
</head>
<body>


<svg version="1.1" width="640" height="480"
 xmlns="http://www.w3.org/2000/svg"
 xmlns:xlink="http://www.w3.org/1999/xlink">

 <defs>
  <polygon id="p0" points="100,0 50,86.6 -50,86.6 -100,0 -50,-86.6 50,-86.6" class="active"/>
  <g id="gr1">
      <polygon id="p1" points="130,0 50,86.6 -50,86.6 -100,0 -50,-86.6 50,-86.6"/>
      <polygon id="p2" points="100,0 50,86.6 -50,86.6 -100,0 -50,-86.6 50,-86.6" class="active"/>
  </g>
 </defs>

 <g transform="translate(70,100)">
    <use xlink:href="#p0" transform="translate(40,0)"/>
    <use xlink:href="#p0" transform="translate(250,0)"/>
    <use xlink:href="#p0" transform="translate(460,0)" class="active" />
 </g>
 <g transform="translate(100,300)">
    <polygon id="style" points="110,0 50,86.6 -50,86.6 -100,0 -50,-86.6 50,-86.6" class="foo"/>
    <use xlink:href="#gr1" transform="translate( 350,2)" class="active2"/>
 </g>

</svg>

</body>
</html>

I want it to work in a way that when user places the mouse pointer over the embedded element, its inner element with class "active" will change its style. It works when I embed one shape from the <defs> directly and apply the CSS class to the <use> which embeds it. But it doesn't work for any classes or ID's inside the group embedded through <use>.

我希望它的工作方式是当用户将鼠标指针放在嵌入元素上时,其内部元素的类“active”将改变其样式。当我直接从 嵌入一个形状并将CSS类应用于嵌入它的 时,它可以工作。但它不适用于通过 嵌入的组内的任何类或ID。

How to fix it?

怎么解决?

Or maybe there's a better way to do it?

或者可能有更好的方法吗?

I need to change only this particular part inside the embedded object when the user hovers it, not the whole group. It's because different parts of this group would have different styles applied, and they need to change differently when hovered by the mouse.

当用户将鼠标悬停在嵌入对象中时,我只需要更改嵌入对象中的这个特定部分,而不是整个组。这是因为该组的不同部分将应用不同的样式,并且当鼠标悬停时它们需要以不同的方式进行更改。

Edit: What I want to get

编辑:我想要的

What I want to get is a way to embed one "library object" from <defs> into many different places in my SVG document. Some parts of this object need to be styled with custom colors from the CSS, because I need easy customization of those colors without changing the library object's code.

我想要的是一种方法,将 中的一个“库对象”嵌入到我的SVG文档中的许多不同位置。该对象的某些部分需要使用CSS中的自定义颜色进行样式设置,因为我需要轻松自定义这些颜色而无需更改库对象的代码。

And then I need to signal the user when the mouse pointer is above such "active" object by styling its parts differently: some bright outlines here and there to show the shape of the clickable areas when the mouse pointer is over them.

然后,当鼠标指针位于这样的“活动”对象之上时,我需要通过不同的方式设置其部件的信号来向用户发出信号:当鼠标指针悬停在它们上方时,这里和那里显示一些明亮的轮廓以显示可点击区域的形状。

Unfortunately, I cannot apply the style to the <use> element's subelements, because they're not subelements of <use> in the DOM (as others already mentioned). I can apply some styles to the elements inside the <defs> section, because they're in the DOM and they're addressable with CSS selectors, but they cannot be hovered, because they're invisible, so applying :hover pseudoclass to them doesn't work. And it doesn't work either if this class is applied to the <use>, because then I cannot sub-select the proper sub elements (they're not sub-elements of <use>). So I don't have any hook to apply those :hover pseudoclass to.

不幸的是,我无法将样式应用于 元素的子元素,因为它们不是DOM中 的子元素(正如其他已经提到的那样)。我可以将一些样式应用于 部分内的元素,因为它们位于DOM中并且可以使用CSS选择器进行寻址,但是它们不能被悬停,因为它们是不可见的,因此应用:hover pseudoclass到它们不起作用。如果将此类应用于 ,它也不起作用,因为那样我就不能再选择正确的子元素(它们不是 的子元素)。所以我没有任何钩子来应用这些:hover pseudoclass to。

Maybe there's some other solution to my problem?

也许我的问题有其他解决方案?

3 个解决方案

#1


25  

You can not address an element that is referenced via use. The specs say:

您无法处理通过use引用的元素。规格说:

For user agents that support Styling with CSS, the conceptual deep cloning of the referenced element into a non-exposed DOM tree also copies any property values resulting from the CSS cascade ([CSS2], chapter 6) on the referenced element and its contents. CSS2 selectors can be applied to the original (i.e., referenced) elements because they are part of the formal document structure. CSS2 selectors cannot be applied to the (conceptually) cloned DOM tree because its contents are not part of the formal document structure.

对于支持使用CSS进行样式处理的用户代理程序,将引用元素概念性深度克隆到非公开DOM树中,还会复制由引用元素及其内容引起的CSS级联([CSS2],第6章)产生的任何属性值。 CSS2选择器可以应用于原始(即引用)元素,因为它们是正式文档结构的一部分。 CSS2选择器不能应用于(概念上)克隆的DOM树,因为它的内容不是正式文档结构的一部分。

Nevertheless, Firefox supports addressing "virtual" elements the are included via a use wormhole. All other browsers don't.

尽管如此,Firefox还是支持通过使用虫洞来处理“虚拟”元素。所有其他浏览器都没有。

What more browser do support is changing filling or stroking color if you give the referenced element a fill/stroke value of currentColor and then you change the color property of the <use> element on hover. Like so:

如果为引用元素提供currentColor的填充/笔触值,然后在悬停时更改 元素的color属性,那么浏览器支持的更多是更改填充或描边颜色。像这样:

<svg version="1.1" width="640" height="480" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">

  <style type="text/css">
    #p0 {fill:currentColor}
    #use1:hover {color:green}
    #use2:hover {color:red}
    #use3:hover {color:blue}
  </style>

  <defs>
    <polygon id="p0" points="100,0 50,86.6 -50,86.6 -100,0 -50,-86.6 50,-86.6" class="active" />
  </defs>

  <g transform="translate(70,100)">
    <use xlink:href="#p0" transform="translate(40,0)" id="use1" />
    <use xlink:href="#p0" transform="translate(250,0)" id="use2" />
    <use xlink:href="#p0" transform="translate(460,0)" id="use3" />
  </g>
</svg>

This is supported by all major browsers (FF, Chrome, IE, Safari). Only Opera doesn't seem to like it. The disadvantage is of course, with this method you can only change one color.

所有主流浏览器(FF,Chrome,IE,Safari)都支持此功能。只有Opera似乎不喜欢它。当然,缺点是这种方法只能改变一种颜色。

So, a different method would possible be to use filters, if it's only about changing color. For example using <feColorMatrix>, you can transform one color to another using a color matrix, like this:

因此,如果只是改变颜色,可以使用不同的方法来使用滤镜。例如,使用 ,您可以使用颜色矩阵将一种颜色转换为另一种颜色,如下所示:

<svg version="1.1" width="640" height="480" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">

  <style type="text/css">
    #p0 {fill: currentColor}
    #use1:hover {filter: url(#filter1)}
    #use2:hover {filter: url(#filter2)}
    #use3:hover {filter: url(#filter3)}
  </style>

  <defs>
    <g id="p0">
      <polygon points="100,0 50,86.6 -50,86.6 -100,0 -50,-86.6 50,-86.6" fill="red" />
      <rect width="50" height="70" fill="green" />
      <circle cx="-20" cy="-30" r="30" fill="blue" />
    </g>
  </defs>

  <filter id="filter1">
    <feColorMatrix type="matrix" in="SourceGraphic" values="0 1 0 0 0 
                     1 0 0 0 0 
                     0 0 1 0 0 
                     0 0 0 1 0" />
  </filter>
  <filter id="filter2">
    <feColorMatrix type="matrix" in="SourceGraphic" values="0 0 1 0 0 
                     1 0 0 0 0 
                     0 1 0 0 0 
                     0 0 0 1 0" />
  </filter>
  <filter id="filter3">
    <feColorMatrix type="matrix" in="SourceGraphic" values="0 1 0 0 0 
                     0 0 1 0 0 
                     1 0 0 0 0 
                     0 0 0 1 0" />
  </filter>

  <g transform="translate(70,100)">
    <use xlink:href="#p0" transform="translate(40,0)" id="use1" />
    <use xlink:href="#p0" transform="translate(250,0)" id="use2" />
    <use xlink:href="#p0" transform="translate(460,0)" id="use3" />
  </g>
</svg>

Still no luck with Opera, though, and this time I wasn't happy with IE9 and Safari either. But I believe it should be possible with Opera and Safari, only I did something not 100% correctly.

尽管如此,Opera仍然没有运气,而这次我对IE9和Safari也不满意。但我相信它应该可以用Opera和Safari,只有我做了一些不正确的事情。

#2


2  

This appears to be according to spec:

这似乎是根据规范:

For user agents that support Styling with CSS, the conceptual deep cloning of the referenced element into a non-exposed DOM tree also copies any property values resulting from the CSS cascade ([CSS2], chapter 6) on the referenced element and its contents. CSS2 selectors can be applied to the original (i.e., referenced) elements because they are part of the formal document structure. CSS2 selectors cannot be applied to the (conceptually) cloned DOM tree because its contents are not part of the formal document structure.

对于支持使用CSS进行样式处理的用户代理程序,将引用元素概念性深度克隆到非公开DOM树中,还会复制由引用元素及其内容引起的CSS级联([CSS2],第6章)产生的任何属性值。 CSS2选择器可以应用于原始(即引用)元素,因为它们是正式文档结构的一部分。 CSS2选择器不能应用于(概念上)克隆的DOM树,因为它的内容不是正式文档结构的一部分。

I tried a few workarounds with use:hover and/or the [] attribute selector syntax and had little luck but there may be a solution there.

我尝试了一些使用的解决方法:悬停和/或[]属性选择器语法,但运气不佳,但可能有一个解决方案。

#3


1  

Maybe this can help: https://codepen.io/AmeliaBR/post/customizable-svg-icons-css-variables

也许这可以帮助:https://codepen.io/AmeliaBR/post/customizable-svg-icons-css-variables

    <svg  xmlns="http://www.w3.org/2000/svg" 
     viewBox="0 0 100 100" preserveAspectRatio="xMidYMid meet"
     class="raw">
  <g id="palette">
  <path d="M5,90
           C5,45 40,-5 75,10 
           C110,25 80,95 60,95
           C50,95 50,75 30,75
           C20,75 17,95 12,95
           C10,95 5,95 5,90 Z"/>
    <g  style="fill:currentColor;">
  <path d="M30,50 
           c-10,0 -20,20 -5,15
           s15,-15 5,-15z
           "/>
  <path  d="M45,30 
           c-10,0 -15,15 -5,15
           s10,-15 5,-15z
           "/>
  <path  d="M70,20 
           c-10,0 -20,15 -5,15
           s10,-15 5,-15z
           "/>
  <path  d="M75,45 
           c-10,0 -20,15 -5,15
           s15,-15 5,-15z
           "/>
  <path  d="M65,65 
           c-10,0 -15,25 -5,20
           s10,-20 5,-20z"/>
    </g>
  </g>
</svg>
<svg class="icon-style-A">
    <use xlink:href="#palette"/>
</svg>

<svg class="icon-style-B">
    <use xlink:href="#palette"/>
</svg>

<svg class="icon-style-C">
    <use xlink:href="#palette"/>
</svg>

    svg {
  display:inline-block;
  height:100px; 
  width:100px;
  margin:10px;
  border:1px solid;
  background:#eee;
}
svg.raw {
/* Default styles for the initial SVG.
 * Because they are defined on the <svg>,
 * not the individual graphics elements, 
 * they will NOT be inherited by the <use> references.
 */
  fill:rgba(255,250,220,0.4);
  stroke: rgba(0,0,0,0.7);
  stroke-width:2;
}
svg.icon-style-A {
/* Set the fill, stroke, and color properties to be 
   inherited by the <use> element:
 */
  fill:burlywood;
  color:blueviolet;
  stroke:#222; 
  stroke-width:0.5px;
}
svg.icon-style-B {
/* Set the color properties:
 */
  fill:blanchedalmond;
  color:lavender;
  stroke:white;
  stroke-width:1px;
/* set some icon styles on the <svg> itself: */
  background:aliceblue;
  border-radius:20%;
  border:none;
  box-shadow:royalblue 0 0 2px;
}
svg.icon-style-C {
/* Set the color properties:
 */
  fill:beige;
  color:green;
  stroke:#aaa; 
  stroke-width:1.5px;
/* icon styles for the <svg> itself: */
  background:#222;
  border-radius:10%;
  border:solid gray;
}

Not very flexible but it worked for my project.

不是很灵活,但它适用于我的项目。

#1


25  

You can not address an element that is referenced via use. The specs say:

您无法处理通过use引用的元素。规格说:

For user agents that support Styling with CSS, the conceptual deep cloning of the referenced element into a non-exposed DOM tree also copies any property values resulting from the CSS cascade ([CSS2], chapter 6) on the referenced element and its contents. CSS2 selectors can be applied to the original (i.e., referenced) elements because they are part of the formal document structure. CSS2 selectors cannot be applied to the (conceptually) cloned DOM tree because its contents are not part of the formal document structure.

对于支持使用CSS进行样式处理的用户代理程序,将引用元素概念性深度克隆到非公开DOM树中,还会复制由引用元素及其内容引起的CSS级联([CSS2],第6章)产生的任何属性值。 CSS2选择器可以应用于原始(即引用)元素,因为它们是正式文档结构的一部分。 CSS2选择器不能应用于(概念上)克隆的DOM树,因为它的内容不是正式文档结构的一部分。

Nevertheless, Firefox supports addressing "virtual" elements the are included via a use wormhole. All other browsers don't.

尽管如此,Firefox还是支持通过使用虫洞来处理“虚拟”元素。所有其他浏览器都没有。

What more browser do support is changing filling or stroking color if you give the referenced element a fill/stroke value of currentColor and then you change the color property of the <use> element on hover. Like so:

如果为引用元素提供currentColor的填充/笔触值,然后在悬停时更改 元素的color属性,那么浏览器支持的更多是更改填充或描边颜色。像这样:

<svg version="1.1" width="640" height="480" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">

  <style type="text/css">
    #p0 {fill:currentColor}
    #use1:hover {color:green}
    #use2:hover {color:red}
    #use3:hover {color:blue}
  </style>

  <defs>
    <polygon id="p0" points="100,0 50,86.6 -50,86.6 -100,0 -50,-86.6 50,-86.6" class="active" />
  </defs>

  <g transform="translate(70,100)">
    <use xlink:href="#p0" transform="translate(40,0)" id="use1" />
    <use xlink:href="#p0" transform="translate(250,0)" id="use2" />
    <use xlink:href="#p0" transform="translate(460,0)" id="use3" />
  </g>
</svg>

This is supported by all major browsers (FF, Chrome, IE, Safari). Only Opera doesn't seem to like it. The disadvantage is of course, with this method you can only change one color.

所有主流浏览器(FF,Chrome,IE,Safari)都支持此功能。只有Opera似乎不喜欢它。当然,缺点是这种方法只能改变一种颜色。

So, a different method would possible be to use filters, if it's only about changing color. For example using <feColorMatrix>, you can transform one color to another using a color matrix, like this:

因此,如果只是改变颜色,可以使用不同的方法来使用滤镜。例如,使用 ,您可以使用颜色矩阵将一种颜色转换为另一种颜色,如下所示:

<svg version="1.1" width="640" height="480" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">

  <style type="text/css">
    #p0 {fill: currentColor}
    #use1:hover {filter: url(#filter1)}
    #use2:hover {filter: url(#filter2)}
    #use3:hover {filter: url(#filter3)}
  </style>

  <defs>
    <g id="p0">
      <polygon points="100,0 50,86.6 -50,86.6 -100,0 -50,-86.6 50,-86.6" fill="red" />
      <rect width="50" height="70" fill="green" />
      <circle cx="-20" cy="-30" r="30" fill="blue" />
    </g>
  </defs>

  <filter id="filter1">
    <feColorMatrix type="matrix" in="SourceGraphic" values="0 1 0 0 0 
                     1 0 0 0 0 
                     0 0 1 0 0 
                     0 0 0 1 0" />
  </filter>
  <filter id="filter2">
    <feColorMatrix type="matrix" in="SourceGraphic" values="0 0 1 0 0 
                     1 0 0 0 0 
                     0 1 0 0 0 
                     0 0 0 1 0" />
  </filter>
  <filter id="filter3">
    <feColorMatrix type="matrix" in="SourceGraphic" values="0 1 0 0 0 
                     0 0 1 0 0 
                     1 0 0 0 0 
                     0 0 0 1 0" />
  </filter>

  <g transform="translate(70,100)">
    <use xlink:href="#p0" transform="translate(40,0)" id="use1" />
    <use xlink:href="#p0" transform="translate(250,0)" id="use2" />
    <use xlink:href="#p0" transform="translate(460,0)" id="use3" />
  </g>
</svg>

Still no luck with Opera, though, and this time I wasn't happy with IE9 and Safari either. But I believe it should be possible with Opera and Safari, only I did something not 100% correctly.

尽管如此,Opera仍然没有运气,而这次我对IE9和Safari也不满意。但我相信它应该可以用Opera和Safari,只有我做了一些不正确的事情。

#2


2  

This appears to be according to spec:

这似乎是根据规范:

For user agents that support Styling with CSS, the conceptual deep cloning of the referenced element into a non-exposed DOM tree also copies any property values resulting from the CSS cascade ([CSS2], chapter 6) on the referenced element and its contents. CSS2 selectors can be applied to the original (i.e., referenced) elements because they are part of the formal document structure. CSS2 selectors cannot be applied to the (conceptually) cloned DOM tree because its contents are not part of the formal document structure.

对于支持使用CSS进行样式处理的用户代理程序,将引用元素概念性深度克隆到非公开DOM树中,还会复制由引用元素及其内容引起的CSS级联([CSS2],第6章)产生的任何属性值。 CSS2选择器可以应用于原始(即引用)元素,因为它们是正式文档结构的一部分。 CSS2选择器不能应用于(概念上)克隆的DOM树,因为它的内容不是正式文档结构的一部分。

I tried a few workarounds with use:hover and/or the [] attribute selector syntax and had little luck but there may be a solution there.

我尝试了一些使用的解决方法:悬停和/或[]属性选择器语法,但运气不佳,但可能有一个解决方案。

#3


1  

Maybe this can help: https://codepen.io/AmeliaBR/post/customizable-svg-icons-css-variables

也许这可以帮助:https://codepen.io/AmeliaBR/post/customizable-svg-icons-css-variables

    <svg  xmlns="http://www.w3.org/2000/svg" 
     viewBox="0 0 100 100" preserveAspectRatio="xMidYMid meet"
     class="raw">
  <g id="palette">
  <path d="M5,90
           C5,45 40,-5 75,10 
           C110,25 80,95 60,95
           C50,95 50,75 30,75
           C20,75 17,95 12,95
           C10,95 5,95 5,90 Z"/>
    <g  style="fill:currentColor;">
  <path d="M30,50 
           c-10,0 -20,20 -5,15
           s15,-15 5,-15z
           "/>
  <path  d="M45,30 
           c-10,0 -15,15 -5,15
           s10,-15 5,-15z
           "/>
  <path  d="M70,20 
           c-10,0 -20,15 -5,15
           s10,-15 5,-15z
           "/>
  <path  d="M75,45 
           c-10,0 -20,15 -5,15
           s15,-15 5,-15z
           "/>
  <path  d="M65,65 
           c-10,0 -15,25 -5,20
           s10,-20 5,-20z"/>
    </g>
  </g>
</svg>
<svg class="icon-style-A">
    <use xlink:href="#palette"/>
</svg>

<svg class="icon-style-B">
    <use xlink:href="#palette"/>
</svg>

<svg class="icon-style-C">
    <use xlink:href="#palette"/>
</svg>

    svg {
  display:inline-block;
  height:100px; 
  width:100px;
  margin:10px;
  border:1px solid;
  background:#eee;
}
svg.raw {
/* Default styles for the initial SVG.
 * Because they are defined on the <svg>,
 * not the individual graphics elements, 
 * they will NOT be inherited by the <use> references.
 */
  fill:rgba(255,250,220,0.4);
  stroke: rgba(0,0,0,0.7);
  stroke-width:2;
}
svg.icon-style-A {
/* Set the fill, stroke, and color properties to be 
   inherited by the <use> element:
 */
  fill:burlywood;
  color:blueviolet;
  stroke:#222; 
  stroke-width:0.5px;
}
svg.icon-style-B {
/* Set the color properties:
 */
  fill:blanchedalmond;
  color:lavender;
  stroke:white;
  stroke-width:1px;
/* set some icon styles on the <svg> itself: */
  background:aliceblue;
  border-radius:20%;
  border:none;
  box-shadow:royalblue 0 0 2px;
}
svg.icon-style-C {
/* Set the color properties:
 */
  fill:beige;
  color:green;
  stroke:#aaa; 
  stroke-width:1.5px;
/* icon styles for the <svg> itself: */
  background:#222;
  border-radius:10%;
  border:solid gray;
}

Not very flexible but it worked for my project.

不是很灵活,但它适用于我的项目。