Issue
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:
<html>
<head></head>
<body>
<svg>
<use href="icon.svg" />
</svg>
</body>
</html>
icon.svg contains:
<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>
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?
Solution
You can store multiple icon assets in an external svg file.
Create an icon asset file using <symbol>
elements
A common practice is to wrap your icons in a <symbol>
elements.
It is crucial to give all your icons/symbols a unique ID.
Now you can reference each icon like so:
<svg>
<use href="icon.svg#symbolID" />
</svg>
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.
body{
font-size: 2em;
font-family: sans-serif
}
.icn-svg{
height:1em;
width:auto;
fill:currentColor;
}
.icn-svg-square{
height:1em;
width:1em;
}
<p style="color:red">
<svg class="icn-svg" viewBox="0 0 19 18">
<use href="#customIcon" />
</svg>
Custom icom
</p>
<p style="color:green">
<svg class="icn-svg" viewBox="0 0 320 512">
<use href="#icon-chess-pawn" />
</svg>
fontAwesome icon proportional
</p>
<p style="color:purple">
<svg class="icn-svg icn-svg-square" >
<use href="#icon-calendar" />
</svg>
fontAwesome icon (square)
</p>
<!-- external icion.svg -->
<svg xmlns="http://www.w3.org/2000/svg" style="width:0;height:0;">
<symbol id="customIcon" viewBox="0 0 19 18" 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" />
</symbol>
<symbol class="icon icon-chess-pawn" id="icon-chess-pawn" viewBox="0 0 320 512">
<path d="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"></path>
</symbol>
<symbol class="icon icon-calendar" id="icon-calendar" viewBox="0 0 448 512">
<path d="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" />
</symbol>
</svg>
We can't use external svgs in SO snippets. Just replace the inline references to something like icons.svg#customIcon
when running on local server.
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 <symbol>
element and copy these values for the parent <svg>
elemnts containing your <use>
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.
Answered By - herrstrietzel
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.