如何使用<use>标签渲染外部SVG文件?

huangapple go评论65阅读模式
英文:

How to render an external SVG file with the <use> tag?

问题

我正在尝试做一件我认为是一个非常简单的任务,但我就是无法让它工作。我已经完全复制了我在线找到的其他8个示例,就像这个一样,但都没有成功。

我实际上正在开发一个React项目,但为了让示例更简单,让我们将情况简化为以下内容:

我有一个名为svg的文件夹,其中包含svg.htmlicon.svg

svg.html 包含:

<html>
<head></head>
<body>
<svg>  
<use href="icon.svg" />
</svg>
</body>
</html>

icon.svg 包含:

<svg width="19" height="18" viewBox="0 0 19 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M16.5 0H2.5C1.4 0 0.5 0.9 0.5 2V16C0.5 17.1 1.4 18 2.5 18H16.5C17.6 18 18.5 17.1 18.5 16V2C18.5 0.9 17.6 0 16.5 0ZM2.5 16V2H8.5V16H2.5ZM16.5 16H10.5V9H16.5V16ZM16.5 7H10.5V2H16.5V7Z" fill="#9F9E99"/>
</svg>

当我运行这个html时,简单地什么都没有显示出来。我希望发生的是,icon.svg 在html中显示出来。我做错了什么?

英文:

I am trying to do something which I thought was a very simple task, but I just can't make it work. I have exactly copied about 8 other examples I found online, like this one, but to no avail.

I am actually working on a React project, but to make the example easier, let's reduce the situation to just this:

I have a folder called svg containing svg.html and icon.svg.

svg.html contains:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-html -->

&lt;html&gt;
&lt;head&gt;&lt;/head&gt;

&lt;body&gt;

&lt;svg&gt;  
&lt;use href=&quot;icon.svg&quot; /&gt;
&lt;/svg&gt;
&lt;/body&gt;
&lt;/html&gt;

<!-- end snippet -->

icon.svg contains:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-html -->

&lt;svg width=&quot;19&quot; height=&quot;18&quot; viewBox=&quot;0 0 19 18&quot; fill=&quot;none&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;
&lt;path d=&quot;M16.5 0H2.5C1.4 0 0.5 0.9 0.5 2V16C0.5 17.1 1.4 18 2.5 18H16.5C17.6 18 18.5 17.1 18.5 16V2C18.5 0.9 17.6 0 16.5 0ZM2.5 16V2H8.5V16H2.5ZM16.5 16H10.5V9H16.5V16ZM16.5 7H10.5V2H16.5V7Z&quot; fill=&quot;#9F9E99&quot;/&gt;
&lt;/svg&gt;

<!-- end snippet -->

When I run the html, simply nothing at all is displayed. What I want to happen, is for the icon.svg to be displayed in the html.
What am I doing wrong?

答案1

得分: 1

以下是翻译好的内容:

  • 你可以将多个图标资源存储在外部的svg文件中。
  • 使用<symbol>元素创建一个图标资源文件是一种常见的做法。
  • 至关重要的是为所有的图标/符号赋予一个独特的ID。
  • 现在你可以像这样引用每个图标:
    <svg>
      <use href="icon.svg#symbolID" />
    </svg>
    
  • 覆盖图标样式时,应尽量保持图标样式属性的中性,即删除fillstyle属性,否则样式覆盖(例如从文本继承颜色或在悬停时更改填充)会变得更加复杂。

在上面的代码片段中,移除了所有的fill属性,这样我们可以轻松地通过CSS规则fill: currentColor来继承文本颜色。

  • 带有单独viewBox设置的符号

    • 只在处理不同图标纵横比时需要,如果所有图标都相对于一个正方形(类似)的viewBox绘制,你可以直接设置图标的宽度和高度。
    • 对于“比例”图标布局,为每个图标的<symbol>元素定义一个合适的viewBox,并将这些值复制到包含<use>引用元素的父级<svg>元素中。
  • 外部图标svg应该托管在相同的域上

    • 主要浏览器非常严格 - 即使你的图标svg托管在允许跨域访问的CDN上,除非你首先获取和内联文件,否则它不会工作。
    • 正如Danny '365CSI' Engelman所评论的,你可以使用他的load-file本地Web组件
    • 你还可以使用keyamoon的"svgxuse"助手脚本
    • 重要提示:只有在允许跨域访问的服务器上托管的外部svg图标才能获取/注入!(例如,像svgshare这样的图像分享平台不会发送适当的CORS标头)。
  • 替代方法:使用现有的图标库

    • 创建自定义图标很棒,但也需要一些研究和大量的测试/调试。
    • 因此,如果你对svg不是特别兴奋,最好选择一个现有的图标库,如fontAwesome、material icons等等。测试icomoon、fontello包括的库/导出功能(后者还可以导出svg文件)……列表还在不断扩展。
    • 关键是:创建自己的自定义图标库通常并不是非常简单的事情 - 特别是混合来自不同来源的图标相当棘手。

Plnkr示例

在上述代码片段中,所有的fill属性都被移除了。这样,我们可以通过CSS规则fill: currentColor轻松继承文本颜色。

英文:

You can store multiple icon assets in an external svg file.

Create an icon asset file using &lt;symbol&gt; elements

A common practice is to wrap your icons in a &lt;symbol&gt; elements.

It is crucial to give all your icons/symbols a unique ID.

Now you can reference each icon like so:

&lt;svg&gt;  
  &lt;use href=&quot;icon.svg#symbolID&quot; /&gt;
&lt;/svg&gt;

Overriding icon styles

Besides, you should keep your icon styles/style attributes as neutral as possible – so remove fill or style attributes – otherwise style overriding (e.g. inheriting colors from text or changing fills on hover) gets more complicated.

<!-- begin snippet: js hide: true console: true babel: false -->

<!-- language: lang-css -->

body{
  font-size: 2em;
  font-family: sans-serif
}

.icn-svg{
  height:1em;
  width:auto;
  fill:currentColor;
}

.icn-svg-square{
  height:1em;
  width:1em;
}

<!-- language: lang-html -->

&lt;p style=&quot;color:red&quot;&gt;
  &lt;svg class=&quot;icn-svg&quot; viewBox=&quot;0 0 19 18&quot;&gt;
    &lt;use href=&quot;#customIcon&quot; /&gt; 
  &lt;/svg&gt;
  Custom icom
&lt;/p&gt;

&lt;p style=&quot;color:green&quot;&gt;
  &lt;svg class=&quot;icn-svg&quot; viewBox=&quot;0 0 320 512&quot;&gt;
    &lt;use href=&quot;#icon-chess-pawn&quot; /&gt; 
  &lt;/svg&gt;
  fontAwesome icon proportional
&lt;/p&gt;

&lt;p style=&quot;color:purple&quot;&gt;
  &lt;svg class=&quot;icn-svg icn-svg-square&quot; &gt;
    &lt;use href=&quot;#icon-calendar&quot; /&gt; 
  &lt;/svg&gt;
  fontAwesome icon (square)
&lt;/p&gt;


&lt;!-- external icion.svg --&gt;
&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; style=&quot;width:0;height:0;&quot;&gt;
  &lt;symbol id=&quot;customIcon&quot; viewBox=&quot;0 0 19 18&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;
    &lt;path d=&quot;M16.5 0H2.5C1.4 0 0.5 0.9 0.5 2V16C0.5 17.1 1.4 18 2.5 18H16.5C17.6 18 18.5 17.1 18.5 16V2C18.5 0.9 17.6 0 16.5 0ZM2.5 16V2H8.5V16H2.5ZM16.5 16H10.5V9H16.5V16ZM16.5 7H10.5V2H16.5V7Z&quot; /&gt;
  &lt;/symbol&gt;
  
  &lt;symbol class=&quot;icon icon-chess-pawn&quot; id=&quot;icon-chess-pawn&quot; viewBox=&quot;0 0 320 512&quot;&gt;
    &lt;path d=&quot;M296 463.1H23.1c-13.25 0-23.1 10.75-23.1 24s10.75 24 23.1 24h272c13.25 0 23.1-10.75 23.1-23.1S309.3 463.1 296 463.1zM55.1 287.1L80 287.1v29.5c0 40.25-3.5 81.25-23.38 114.5h53.5C125.1 394.1 128 354.6 128 317.5v-29.5h64v29.5c0 37.13 2.875 77.5 17.88 114.5h53.5C243.5 398.7 240 357.7 240 317.5V287.1l24-.0001C277.3 287.1 288 277.3 288 263.1c0-13.25-10.75-24-23.1-24H241c23.75-21.88 38.1-53.12 38.1-87.1c0-9.393-1.106-19.05-3.451-28.86C272.3 105.4 244.9 32 159.1 32C93.75 32 40 85.75 40 151.1c0 34.88 15.12 66.12 39 88H55.1C42.75 239.1 32 250.7 32 263.1C32 277.3 42.75 287.1 55.1 287.1zM160 79.1c39.75 0 72 32.25 72 72S199.8 223.1 160 223.1S88 191.7 88 151.1S120.2 79.1 160 79.1z&quot;&gt;&lt;/path&gt;
  &lt;/symbol&gt;

  &lt;symbol class=&quot;icon icon-calendar&quot; id=&quot;icon-calendar&quot; viewBox=&quot;0 0 448 512&quot;&gt;
    &lt;path d=&quot;M152 64H296V24C296 10.75 306.7 0 320 0C333.3 0 344 10.75 344 24V64H384C419.3 64 448 92.65 448 128V448C448 483.3 419.3 512 384 512H64C28.65 512 0 483.3 0 448V128C0 92.65 28.65 64 64 64H104V24C104 10.75 114.7 0 128 0C141.3 0 152 10.75 152 24V64zM48 448C48 456.8 55.16 464 64 464H384C392.8 464 400 456.8 400 448V192H48V448z&quot; /&gt;
  &lt;/symbol&gt;

&lt;/svg&gt;

<!-- end snippet -->

We can't use external svgs in SO snippets. just replace the inline references to somethinng like icons.svg#customIcon when running on local server.

Plnkr example

In the above snippet, all fill attributes are removed.
This way we can easily inherit text colors via fill: currentColor in a css rule like this:

.icn-svg{
  height:1em;
  width:auto;
  fill:currentColor;
}

Symbols with individual viewBox settings

Only needed, if you're dealing with different icon aspect ratios – if all icons are drawn relative to a square (like) viewBox – you can set the icons with and height directly.

For a "proportional" icon layout – define an appropriate viewBox for each icon &lt;symbol&gt; element and copy these values for the parent &lt;svg&gt; elemnts containing your &lt;use&gt; reference element.

External icon svgs should be hosted on same domain

Major browsers are very strict – even if your icon svg is hosted on a cdn allowing cross origin access, it won't work, unless you're fetching and inlining the file first.

As commented by Danny '365CSI' Engelman you could use his load-file native web component.

You might also use keyamoon's "svgxuse" helper script.

Important: you can only fetch/inject external svg icons if they are hosted on servers allowing cross origin access! (e.g image sharing platforms like svgshare don't send a suitable CORS header).

Alternative: use a existing icon library

Seriously, creating custom icons is great but also requires some research and quite a lot of testing/debugging.

So if you're not overly excited about svg, you should better opt for an existing icon library like fontAwesome, material icons ... test icomoon, fontello included libraries/export functions (the latter ones can also export svg files) ... the list goes on and on.

The point is: creating your own custom icon library is usually not very trivial – especially mixing icons from different sources is quite tricky.

huangapple
  • 本文由 发表于 2023年5月15日 00:56:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/76248681.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定