我已经伤透脑筋好几个小时了。这没有任何意义。
我将我遇到的问题简化为这个代码笔: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.svg
和Icon_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>
);
};