'Dynamically added svg viewbox values not working? [duplicate]
I'm trying to add an svg dynamically to a menu, but I'm having a problem setting the viewbox.
When I inline the svgs (svg and svg-2), the viewbox has to be correct for the respective icon (0 0 512 512 and 0 0 24 24), as expected. Changing the viewbox removes the icon from view.
But for my dynamically added icons (dynamic-svg and dynamic-svg-2), changing the viewbox values (0 0 24 24 and 0 0 512 512) does nothing. In fact I can't get dynamic-svg-2 to show at all. dynamic-svg continues to display even if I change the viewbox to random values.
I must be doing something wrong, or have a bug somewhere, but I really can't see it. Would appreciate if someone could take a look. Thanks
const container = document.querySelector('.container');
const svgWrapper = document.createElement('div');
svgWrapper.className = 'dynamic-svg-wrapper'
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg")
const path1 = document.createElementNS("http://www.w3.org/2000/svg", 'path')
svg.setAttribute("aria-hidden","true");
svg.setAttribute('viewbox', '0 0 24 24');
svg.setAttribute('class', 'dynamic-svg');
path1.setAttribute('d', `M9 8h-3v4h3v12h5v-12h3.642l.358-4h-4v-1.667c0-.955.192-1.333 1.115-1.333h2.885v-5h-3.808c-3.596 0-5.192 1.583-5.192 4.615v3.385z`);
path1.setAttribute('fill', '#000000');
svg.append(path1);
svgWrapper.append(svg);
container.append(svgWrapper);
const svgWrapper2 = document.createElement('div');
svgWrapper2.className = 'dynamic-svg-wrapper-2'
const svg2 = document.createElementNS("http://www.w3.org/2000/svg", "svg")
const path2 = document.createElementNS("http://www.w3.org/2000/svg", 'path')
svg2.setAttribute("aria-hidden","true");
svg2.setAttribute('viewbox', '0 0 512 512');
svg2.setAttribute('class', 'dynamic-svg-2');
path2.setAttribute('d', `M461.6,109.6l-54.9-43.3c-1.7-1.4-3.8-2.4-6.2-2.4c-2.4,0-4.6,1-6.3,2.5L194.5,323c0,0-78.5-75.5-80.7-77.7
c-2.2-2.2-5.1-5.9-9.5-5.9c-4.4,0-6.4,3.1-8.7,5.4c-1.7,1.8-29.7,31.2-43.5,45.8c-0.8,0.9-1.3,1.4-2,2.1c-1.2,1.7-2,3.6-2,5.7
c0,2.2,0.8,4,2,5.7l2.8,2.6c0,0,139.3,133.8,141.6,136.1c2.3,2.3,5.1,5.2,9.2,5.2c4,0,7.3-4.3,9.2-6.2L462,121.8
c1.2-1.7,2-3.6,2-5.8C464,113.5,463,111.4,461.6,109.6z`);
path2.setAttribute('fill', '#000000');
svg2.append(path2);
svgWrapper2.append(svg2);
container.append(svgWrapper2);
* {
margin: 0;
}
.container {
display: flex;
justify-content: center;
width: 100%;
height: 100vh;
background-color: lightgrey;
}
.svg-wrapper {
display: flex;
width: 24px;
height: 24px;
border: 1px solid black;
margin: 10px;
}
.svg {
display: flex;
width: 24px;
height: 24px;
}
.svg-wrapper-2 {
display: flex;
width: 24px;
height: 24px;
border: 1px solid black;
margin: 10px;
}
.dynamic-svg-wrapper {
display: flex;
width: 24px;
height: 24px;
border: 1px solid black;
margin: 10px;
}
.dynamic-svg {
display: flex;
width: 24px;
height: 24px;
}
.dynamic-svg-wrapper-2 {
display: flex;
width: 24px;
height: 24px;
border: 1px solid black;
margin: 10px;
}
.dynamic-svg-2 {
display: flex;
width: 24px;
height: 24px;
}
<div class="container">
<div class="svg-wrapper">
<svg class="svg" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 512 512">
<path d="M461.6,109.6l-54.9-43.3c-1.7-1.4-3.8-2.4-6.2-2.4c-2.4,0-4.6,1-6.3,2.5L194.5,323c0,0-78.5-75.5-80.7-77.7
c-2.2-2.2-5.1-5.9-9.5-5.9c-4.4,0-6.4,3.1-8.7,5.4c-1.7,1.8-29.7,31.2-43.5,45.8c-0.8,0.9-1.3,1.4-2,2.1c-1.2,1.7-2,3.6-2,5.7
c0,2.2,0.8,4,2,5.7l2.8,2.6c0,0,139.3,133.8,141.6,136.1c2.3,2.3,5.1,5.2,9.2,5.2c4,0,7.3-4.3,9.2-6.2L462,121.8
c1.2-1.7,2-3.6,2-5.8C464,113.5,463,111.4,461.6,109.6z"/>
</svg>
</div>
<div class="svg-wrapper-2">
<svg class='svg-2' xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9 8h-3v4h3v12h5v-12h3.642l.358-4h-4v-1.667c0-.955.192-1.333 1.115-1.333h2.885v-5h-3.808c-3.596 0-5.192 1.583-5.192 4.615v3.385z"/></svg>
</div>
</div>
]1
Solution 1:[1]
You can save yourself a lot of headaches using modern technologies,
A <svg-icon> Web Component, supported in all modern browsers.
I processed some of your <path> with https://yqnn.github.io/svg-path-editor/, to make them smaller.
You don't need 0.nnn precision when you stuff a 512x512 viewBox in 40x40 pixels
It does not matter where or when you execute customElements.define;
all existing or new <svg-icon> will automagically upgrade.
<style>
div {
display: flex; justify-content: center;
width:100%; background:pink;
}
</style>
<div>
<svg-icon>
<path fill="green" d="m461.6 109.6-54.9-43.3c-1.7-1.4-3.8-2.4-6.2-2.4-2.4 0-4.6 1-6.3 2.5l-199.7 256.6c0 0-78.5-75.5-80.7-77.7-2.2-2.2-5.1-5.9-9.5-5.9-4.4 0-6.4 3.1-8.7 5.4-1.7 1.8-29.7 31.2-43.5 45.8-.8.9-1.3 1.4-2 2.1-1.2 1.7-2 3.6-2 5.7 0 2.2.8 4 2 5.7l2.8 2.6c0 0 139.3 133.8 141.6 136.1 2.3 2.3 5.1 5.2 9.2 5.2 4 0 7.3-4.3 9.2-6.2l249.1-320c1.2-1.7 2-3.6 2-5.8 0-2.5-1-4.6-2.4-6.4z" />
</svg-icon>
<svg-icon vb="5120">
<path fill="red" d="m4616 1096-549-433c-17-14-38-24-62-24-24 0-46 10-63 25l-1997 2566c0 0-785-755-807-777-22-22-51-59-95-59-44 0-64 31-87 54-17 18-297 312-435 458-8 9-13 14-20 21-12 17-20 36-20 57 0 22 8 40 20 57l28 26c0 0 1393 1338 1416 1361 23 23 51 52 92 52 40 0 73-43 92-62l2491-3200c12-17 20-36 20-58 0-25-10-46-24-64z" />
</svg-icon>
<svg-icon vb="24">
<path fill="blue" d="M9 8h-3v4h3v12h5v-12h3.642l.358-4h-4v-1.667c0-.955.192-1.333 1.115-1.333h2.885v-5h-3.808c-3.596 0-5.192 1.583-5.192 4.615v3.385z" />
</svg-icon>
<svg-icon vb="24">
<path fill="rebeccapurple" d="M9 8h-3v4h3v12h5v-12h3.642l.358-4h-4v-1.667c0-.955.192-1.333 1.115-1.333h2.885v-5h-3.808c-3.596 0-5.192 1.583-5.192 4.615v3.385z" />
</svg-icon>
</div>
<script>
customElements.define("svg-icon", class extends HTMLElement {
connectedCallback() {
let vb = this.getAttribute("vb") || 512;
setTimeout(() => { // wait till path innerHTML is parsed
let svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
svg.setAttribute("viewBox",`0 0 ${vb} ${vb}`);
svg.innerHTML = this.innerHTML;
this.replaceWith(svg); // Web Component did its job, no need to keep it
});
}
});
</script>
Take this idea some steps further and you get https://iconmeister.github.io
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
