当我"display: none"一个 SVG 时,另一个(独立的)SVG 会以不同的方式呈现



我已经伤透脑筋好几个小时了。这没有任何意义。

我将我遇到的问题简化为这个代码笔:https://codepen.io/Octopous/pen/OJORpJQ

HTML:

*the two inline SVG's* (too many characters), see the CodePen

CSS:

svg.one {
display: none;
}
svg.two {
display: block;
}

一个页面上有两个内联SVG元素。它们完全相同。当第一SVG被设置为"0"时;display:none";,第二SVG被加扰/以不同的方式显示。在这种情况下,过去由剪裁路径剪裁的所有元素现在都会忽略剪裁路径。当第一SVG未被设置为"0"时;display:none";,第二个SVG与第一个一样显示正确。

由于CSS声明尽可能简单,再具体不过了,所以我无法理解为什么第二个SVG会受到这些影响。在我作为一名网络开发人员和SVG工作的这些年里,我从未遇到过这样的问题。

我尝试过的东西:

  • 重命名第二个SVG中的所有ID(尽管这没有意义(
  • 导出具有不同维度等的附加SVG,以便第二个SVG具有不同的属性,而不会使其在视觉上有所不同

非常感谢您的帮助。对于这个项目来说,最重要的是两个SVG实际上是相同的SVG。只要这个问题存在,我就无法继续这个项目。

编辑:Safari似乎做得很好,行为如预期。Firefox和Chrome都搞砸了。

问题-纠缠SVG(CodePen中的演示(

正如其他人在评论中指出的那样,问题是如果同一个SVG的元素具有[id]属性,则不应该在一个页面上包含两次相同的SVG。

充其量,您的标记是无效的,因为ID在整个文档中必须是唯一的

最糟糕的情况是,正如我们在这里看到的那样,拥有多个ID会给浏览器带来困惑,让浏览器在被其他元素引用时无法确定要使用哪个ID。默认情况下,浏览器通常会使用文档流中的第一个id。如果第一个恰好通过display none隐藏,则不会自动重新路由到下一个适用用途。

解决方案

选项A-创建唯一ID

根据您将SVG注入页面的方式,您可以换掉旧的ID并替换为随机guid。这样,每个SVG都可以完全独立地工作和操作,不会干扰任何其他SVG。

然而,这需要稍微更多的处理和稍微更多的布线空间。

选项B-使用外部SVG

如果不是内联<svg>元素,而是引用外部引用文件(如<img src="/circle.svg" />(,则每个文件都有自己的文档范围,并且可以独立操作。

但是,需要一个额外的(但希望是缓存的(网络请求。外部加载的SVG还有一些其他限制,比如不能继承颜色。

选项C-隐藏,不要隐藏

不要使用display:none,而是尝试使用width:0px;height:0px; position;absolute;right:-100px;。这允许样式仍然被使用,但将元素移出屏幕。

然而,如果隐藏的东西在DOM中的更高位置,并且恰好包含SVG ,那么这可能会很有挑战性

选项D-使用CSS而不是defs

根据您引用的属性,可以修改SVG以使用CSS,而不是通过ID引用SVG元素。

然而,在CSS中找到SVG的替代表达方式可能有挑战性,也可能是不可能的。

选项E-从使用中拆分Defs

创建两个SVG-Icon_Base.svgIcon_Image.svg。将任何常见的<defs>添加到基中,并将其包含在DOM的顶部,然后将实际图像包含在SVG中的任何位置,并包含在页面内的任何位置。由于底座保证是可见的,您可以根据自己的喜好更新各个图像,而无需担心干扰。

但是,创建了一个相当统一的DX,即*_Base变体需要包含在页面的其他位置,并且如果在其他位置使用图标,则需要包含

选项F-内联B64 SVG

您可以将整个SVG序列化为base64字符串,然后引用的ID,该URL类似于fill="url(data:image/svg+xml;base64,<encoded full svg>#mygradient)

但是,仅适用于FF

进一步阅读

  • 隐藏SVG会影响同一页面中的其他SVG样式
  • 使用SVG符号隐藏的梯度
  • SVG LinearGradient隐藏如果SVG隐藏在单独的类中
  • SVG隐藏或外部时,SVG过滤器会失去颜色

在React中,您可以将您的svg放入组件中,并为每个svg生成一个随机id

export const PlayCircleIcon: FC<SvgIconProps> = () => {
const id = useRef(Math.floor(Math.random() * 10e4)).current;
return (
<svg>
<path
// ...
fill={`url(#paint0_linear_6316_${id})`}
/>
<defs>
<linearGradient
id={`paint0_linear_6316_${id}`}
// ...
>
<stop stopColor="#6345ED" />
<stop offset="1" stopColor="#E039FD" />
</linearGradient>
</defs>
</svg>
);
};

最新更新