Link svg paths from external file to be displayed in HTML - html

I have a bunch of svg paths (for icons) which work fine if they are placed directly in the html. But with so many, I want to put them into an external file instead. I cant use object or img as I am using css to style them. any ideas?
<!-- svg paths -->
<symbol viewBox="0 0 100 100" preserveAspectRatio="xMidYMid meet" id="icon1">
<path d="..."></path>
</symbol>
<symbol viewBox="0 0 100 100" preserveAspectRatio="xMidYMid meet" id="icon2">
<path d="..."></path>
</symbol>
<symbol viewBox="0 0 100 100" preserveAspectRatio="xMidYMid meet" id="icon3">
<path d="..."></path>
</symbol>
<!-- html -->
<svg>
<use xlink:href="#icon1"></use>
</svg>
<svg>
<use xlink:href="#icon2"></use>
</svg>
<svg>
<use xlink:href="#icon3"></use>
</svg>

You can use the filename in front of the id reference. Like here I'm referring to the symbol s2 in the file symbols.svg:
<!DOCTYPE html>
<html>
<head>
<title>SVG symbol</title>
</head>
<body>
<h1>Test</h1>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200">
<use href="symbols.svg#s2" />
</svg>
</body>
</html>

Related

Is it legal to put <svg> resources after </body>?

Can I put svg resources used in the website behind the end of body, in order to keep
them outside of what will be rendered?
In short: Is it legal to do the following?
<!DOCTYPE html>
<html>
<head>...</head>
<body>
<svg xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 315.424 315.424" >
<use href="#arrow" fill="rgb(0,44,89)" />
</svg>
</body>
<svg>
<g id="arrow">
<path d="M311.929,222.266l-96.119-67.342c-1.413-0.99-2.783-1.513-4.307-1.513c-3.307,0-6.471,2.512-6.471,7.313v41.05H19.886
c-4.962,0-8.854,4.132-8.854,9.094v35.563c0,4.962,3.892,9.343,8.854,9.343h185.146v40.81c0,4.801,3.167,7.19,6.474,7.19
c0.001,0-0.089,0-0.089,0c1.524,0,3.032-0.461,4.445-1.451l96.09-67.306c2.214-1.55,3.473-3.864,3.473-6.375
S314.142,223.815,311.929,222.266z" />
</g>
</svg>
</html>
As mentioned before in the comments:
It's not valid and many browser won't display your elements.
So inserting your svg assets at the top or bottom of your <body> is the preferrable method.
Caution: Hiding your asset svg via display:none will break some referenced definitions like:
filters
gradients
masks and clip-paths
It works flawlessly for shape elements (like icons)
Example
function displayNone() {
document.querySelector('#svgAssets').style.display = 'none';
}
svg {
border: 1px dotted #ccc;
height: 10em;
display: inline-block;
}
<p><button onclick="displayNone()">Set display:none</button></p>
<svg viewBox="0 0 315.424 315.424">
<use href="#arrow" fill="red" />
</svg>
<svg viewBox="0 0 100 100">
<use href="#circle" fill="green" />
</svg>
<svg viewBox="0 0 200 100">
<use href="#ellipse" fill="url(#gradient)" />
</svg>
<svg id="svgAssets" style="visibility:visible; width:0; height:0" aria-hidden="true">
<defs>
<linearGradient id="gradient">
<stop stop-color="red" offset="0%"/>
<stop stop-color="orange" offset="100%"/>
</linearGradient>
</defs>
<symbol id="arrow" viewBox="0 0 315.424 315.424">
<path d="M311.929,222.266l-96.119-67.342c-1.413-0.99-2.783-1.513-4.307-1.513c-3.307,0-6.471,2.512-6.471,7.313v41.05H19.886 c-4.962,0-8.854,4.132-8.854,9.094v35.563c0,4.962,3.892,9.343,8.854,9.343h185.146v40.81c0,4.801,3.167,7.19,6.474,7.19 c0.001,0-0.089,0-0.089,0c1.524,0,3.032-0.461,4.445-1.451l96.09-67.306c2.214-1.55,3.473-3.864,3.473-6.375 S314.142,223.815,311.929,222.266z" />
</symbol>
<symbol id="circle" viewBox="0 0 100 100">
<circle cx="50%" cy="50%" r=50% />
</symbol>
<symbol id="ellipse" viewBox="0 0 200 100">
<ellipse cx="100" cy="50" rx="100" ry="50" />
</symbol>
</svg>
In the above example I'm using <symbol> elements which could be used as an alternative to <defs>. They also support different viewBox properties for each icon.
If you just need to place icons via <use> you could also use external file references like so:
<svg viewBox="0 0 315.424 315.424">
<use href="svgIcons.svg#arrow" fill="red" />
</svg>
However, your svg files need to be same domain (or send with appropriate CORS headers)
If the purpose is not to have the original #arrow rendered in the document, you might include it inside the svg in the body, wrapped around defs.
Demo in the snipped below.
<svg xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 315.424 315.424">
<defs>
<g id="arrow">
<path d="M311.929,222.266l-96.119-67.342c-1.413-0.99-2.783-1.513-4.307-1.513c-3.307,0-6.471,2.512-6.471,7.313v41.05H19.886
c-4.962,0-8.854,4.132-8.854,9.094v35.563c0,4.962,3.892,9.343,8.854,9.343h185.146v40.81c0,4.801,3.167,7.19,6.474,7.19
c0.001,0-0.089,0-0.089,0c1.524,0,3.032-0.461,4.445-1.451l96.09-67.306c2.214-1.55,3.473-3.864,3.473-6.375
S314.142,223.815,311.929,222.266z" />
</g>
</defs>
<use href="#arrow" fill="rgb(0,44,89)" />
</svg>

How to display SVG with <use>

I am trying to use <use> tag to display an SVG. I am using Wordpress and have the file under the upload folder (as any other media). For some reason the <use> doesn't show, on the browser it show width and height as 0, even though I have inlined them in it.
My code:
<svg viewBox='0 0 153 91'>
<use href='https://example.com/wp-content/uploads/2021/04/arrow.svg' width='30' height='18'>
</svg>
In the Browser:
<svg viewBox="0 0 153 91">
<use href="https://example.com/wp-content/uploads/2021/04/arrow.svg" width="30" height="18">
</use>
</svg>
The svg file:
<svg fill="none" stroke="#fff" stroke-linecap="round" stroke-width="9.17" viewBox="0 0 153 91"><path d="m18.898 45.191h115.04"/><path d="m108.181 18.898 25.757 26.293-25.757 26.293"/></svg>
BONUS: Could the SVG be inlined somewhere in the <body> instead of the file uploaded?
This was missing on the SVG
xmlns="http://www.w3.org/2000/svg" xmlns:xlink= "http://www.w3.org/1999/xlink"
Final SVG should be:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink= "http://www.w3.org/1999/xlink"
>
<symbol id="arrow" viewBox="0 0 153 91" fill="none" stroke="#fff" stroke-linecap="round" stroke-width="9.17">
<path d="m18.898 45.191h115.04"/><path d="m108.181 18.898 25.757 26.293-25.757 26.293"/>
</symbol>
</svg>
src: SVG image tag not working

How can I see the icons inside the SVG file?

I want to see all the icons inside the SVG file. I have tried to insert it into the HTML file with an img tag but I see a blank page.
<svg aria-hidden="true" style="position: absolute; width: 0; height: 0; overflow: hidden;" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<symbol id="icon-triangle-left" viewBox="0 0 20 20">
<title>triangle-left</title>
<path d="M14 5v10l-9-5 9-5z"></path>
</symbol>
<symbol id="icon-triangle-right" viewBox="0 0 20 20">
<title>triangle-right</title>
<path d="M15 10l-9 5v-10l9 5z"></path>
</symbol>
<symbol id="icon-check" viewBox="0 0 20 20">
<title>check</title>
<path d="M8.294 16.998c-0.435 0-0.847-0.203-1.111-0.553l-3.573-4.721c-0.465-0.613-0.344-1.486 0.27-1.951 0.615-0.467 1.488-0.344 1.953 0.27l2.351 3.104 5.911-9.492c0.407-0.652 1.267-0.852 1.921-0.445s0.854 1.266 0.446 1.92l-6.984 11.21c-0.242 0.391-0.661 0.635-1.12 0.656-0.022 0.002-0.042 0.002-0.064 0.002z"></path>
</symbol>
</defs>
</svg>
The code you provided contains only <symbols>. This is used to house SVG definitions that can be reused in different parts of the document. You would use them like this:
<svg>
<use xlink:href="#icon-triangle-left" />
</svg>
Live test: https://codepen.io/guilhermemuller/pen/NWqddGp

Changing fill to svg with <use>

I'm trying to load in my HTML, the colors that are set in the .svg file with <use> but for some reason it doesn't load.
HTML
<svg>
<use xlink:href="img/beer-05.svg#beer"></use>
</svg>
beer-05.svg
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<style type="text/css">
#beer1 {fill:#ffc32e;}
#beer2 {fill:#f2a33a;}
#beer3 {fill:#fffade;}
#beer4 {fill:#ffffff;}
#beer1:hover {fill:green;}
</style>
<symbol id="beer" viewBox="0 0 32 32">
<path id="beer1" d="M19.8,17.5v2.4v2.4v1.4v1v3.8V44h8.5c3,0,5.4-2.4,5.4-5.4V28.5v-3.8v-1v-1.4v-2.4v-2.4H19.8z"/>
<path id="beer2" d="M5.9,15.2v4.8v3.8v1v3.8v10.2c0,3,2.4,5.4,5.4,5.4h8.5V28.5v-3.8v-1v-3.8v-4.8H5.9z" />
<rect x="19.8" y="14.2" fill="none" width="13.9" height="4.8"/>
<path id="beer3" fill="#FFFADE" d="M9.4,38.5L9.4,38.5c-0.6,0-1-0.5-1-1V24c0-0.6,0.5-1,1-1h0c0.6,0,1,0.5,1,1v13.5
C10.4,38.1,9.9,38.5,9.4,38.5z"/>
<path id="beer4" fill="#FFFFFF" d="M35.3,18.5c-0.2,0-0.4,0-0.6,0v-0.2c0-0.4,0-0.8-0.1-1.2c2.1-1.7,3.1-4.2,2.3-6.3c-0.4-1.1-1.2-2-2.3-2.6
c-0.9-2.1-3.2-3.9-6.2-4.6c-1.6-0.4-3.2-0.4-4.5-0.1c-1.3-1-3.2-1.5-5.2-1.4c-2.6,0.2-4.7,1.4-5.7,3c-0.6,0-1.3,0-2,0.1
c-5.2,0.6-9.1,4.3-8.6,8.3c0.2,1.7,1.2,3.2,2.6,4.3c0,0.2,0,0.4,0,0.6v20.3c0,3.5,2.9,6.4,6.4,6.4h17c3.5,0,6.3-2.8,6.4-6.3
c0.2,0,0.4,0,0.6,0c4.5,0,8.2-4.5,8.2-10.1S39.8,18.5,35.3,18.5z M32.7,38.1v0.5c0,2.4-2,4.4-4.4,4.4h-17c-2.4,0-4.4-2-4.4-4.4
V18.8c1.7,0.7,3.6,1,5.7,0.7c1.6-0.2,3.1-0.7,4.4-1.4c1.9,2.2,5.1,3.5,8.8,3.3c2.8-0.2,5.2-1.2,6.9-2.8v0.5V38.1z M35.3,35.2
c-0.2,0-0.4,0-0.6-0.1v-13c0.2,0,0.4-0.1,0.6-0.1c2.5,0,4.7,3,4.7,6.6S37.8,35.2,35.3,35.2z"/>
</symbol>
could someone help me with this?
As defined in the specs, you can't address <use> elements via CSS.
CSS2 selectors cannot be applied to the (conceptually) cloned DOM tree because its contents are not part of the formal document structure.
Check this answer.
In your case, I would embed the external svg with <object> , after altering the external svg file to look like:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="280" viewBox="0 0 32 32" preserveAspectRatio="xMinYMin meet">
<defs>
<style type="text/css">
#beer1 {fill:#ffc32e;}
#beer2 {fill:#f2a33a;}
#beer3 {fill:#fffade;}
#beer4 {fill:#ffffff;}
#beer1:hover {fill:green;}
</style>
</defs>
<path id="beer1" d="M19.8,17.5v2.4v2.4v1.4v1v3.8V44h8.5c3,0,5.4-2.4,5.4-5.4V28.5v-3.8v-1v-1.4v-2.4v-2.4H19.8z"/>
<path id="beer2" fill="#f2a33a" d="M5.9,15.2v4.8v3.8v1v3.8v10.2c0,3,2.4,5.4,5.4,5.4h8.5V28.5v-3.8v-1v-3.8v-4.8H5.9z" />
<rect x="19.8" y="14.2" fill="none" width="13.9" height="4.8"/>
<path id="beer3" fill="#FFFADE" d="M9.4,38.5L9.4,38.5c-0.6,0-1-0.5-1-1V24c0-0.6,0.5-1,1-1h0c0.6,0,1,0.5,1,1v13.5
C10.4,38.1,9.9,38.5,9.4,38.5z"/>
<path id="beer4" fill="#FFFFFF" d="M35.3,18.5c-0.2,0-0.4,0-0.6,0v-0.2c0-0.4,0-0.8-0.1-1.2c2.1-1.7,3.1-4.2,2.3-6.3c-0.4-1.1-1.2-2-2.3-2.6
c-0.9-2.1-3.2-3.9-6.2-4.6c-1.6-0.4-3.2-0.4-4.5-0.1c-1.3-1-3.2-1.5-5.2-1.4c-2.6,0.2-4.7,1.4-5.7,3c-0.6,0-1.3,0-2,0.1
c-5.2,0.6-9.1,4.3-8.6,8.3c0.2,1.7,1.2,3.2,2.6,4.3c0,0.2,0,0.4,0,0.6v20.3c0,3.5,2.9,6.4,6.4,6.4h17c3.5,0,6.3-2.8,6.4-6.3
c0.2,0,0.4,0,0.6,0c4.5,0,8.2-4.5,8.2-10.1S39.8,18.5,35.3,18.5z M32.7,38.1v0.5c0,2.4-2,4.4-4.4,4.4h-17c-2.4,0-4.4-2-4.4-4.4
V18.8c1.7,0.7,3.6,1,5.7,0.7c1.6-0.2,3.1-0.7,4.4-1.4c1.9,2.2,5.1,3.5,8.8,3.3c2.8-0.2,5.2-1.2,6.9-2.8v0.5V38.1z M35.3,35.2
c-0.2,0-0.4,0-0.6-0.1v-13c0.2,0,0.4-0.1,0.6-0.1c2.5,0,4.7,3,4.7,6.6S37.8,35.2,35.3,35.2z"/>
</svg>
Edit from the comments below :
You can access each item separately, the same way <use xlink:href> does :
<object type="image/svg+xml" data="http://epoje.es/beers.svg#cervey"></object>

svg: change fill color using css

I have this svg file which I want to use with different colors
I have tried the following
<object type="image/svg+xml" width="100" height="100" data="todo.svg">
<span/>
</object>
(Not sure if OBJECT is the correct element for this)
Here is the content of todo.svg
<svg version="1.1" id="Layer_1" xmlns="..." x="0px" y="0px"
width="156px" height="141.6px" viewBox="0 0 156 141.6" enable-background="new 0 0 156 141.6" xml:space="preserve">
<g>
....
<g id="bar">
<path fill-rule="evenodd" clip-rule="evenodd" fill="#000" d="..."/>
</g>
</g>
....
So in the css I tried to style this as follows
#bar path { fill: #444; }
Doesn't work :( Any suggestions how I can change this svg property using css ?