Post

SVG Info

Miscellaneous

  • The viewBox of a symbol is less meaningful than it seems, it doesn’t actually control size of the element, it is arbitrary and only used for the coordinate system of points within
    • For example the point 12,2 in viewBox="0 0 24 24" is the same as 24,4 in viewBox="0 0 48 48"
  • Viewboxes with base-12 are preferred as the numbers are more divisible, base-60 might even be preferable
  • The default <svg> rendering size is 300x150, most of the time it is useful to add svg { width: 100%; height: 100% } to your CSS styles so as to have <svg> fill a parent container, or something like svg { width: 48px; height: 48px } if you want to fix their size
  • Each symbol should have its own viewbox, even if it is the same as all other sibling symbols, you cannot inherit viewbox from the <svg> parent

SVG Info

One of the most common ways to work with SVG is to add an “SVG symbol definitions block” or an “SVG spritesheet”. It’s important that it is given style="display:none;", otherwise it will render on the site itself

1
2
3
4
5
<svg style="display:none;">
  <symbol id="symbol-id" viewBox="0 0 24 24">
    <polygon points="12,2 22,12 12,22 2,12" />
  </symbol>
</svg>

Once the <svg> is added you can reference the symbols within it via a new <svg> tag that has a <use> tag within it, as below

1
2
3
<svg>
  <use href="#symbol-id"></use>
</svg>

Styling

There are multiple ways to style SVG, each will influence the contents of the <svg> when accessed via <use href="#symbol-id">

Method 01 You can style the <symbol> tag as below

1
2
3
4
5
<svg style="display:none;">
  <symbol id="symbol-id" viewBox="0 0 24 24" style="fill: red; stroke: blue; stroke-width: 3;">
    <polygon points="12,2 22,12 12,22 2,12" />
  </symbol>
</svg>

Method 02 You can style the individual elements within a symbol as below

1
2
3
4
5
6
<svg style="display:none;">
  <symbol id="symbol-id" viewBox="0 0 24 24">
    <polygon points="12,2 22,12 12,22 2,12" style="fill: red; stroke: blue; stroke-width: 3;" />
    <circle cx="12" cy="12" r="2" style="fill: cyan; stroke: magenta; stroke-width: 2;" />
  </symbol>
</svg>

Method 03 You can style via the <use> tag

1
2
3
<svg>
  <use href="#symbol-id" style="fill:red; stroke:blue; stroke-width:3;"></use>
</svg>

Method 04 You can style via parent <svg> of the <use> tag

1
2
3
<svg style="fill:red; stroke:blue; stroke-width:3;">
  <use href="#symbol-id"></use>
</svg>

Method 05 You can style via the CSS

1
2
3
4
5
svg {
  fill: red;
  stroke: blue;
  stroke-width: 3;
}

Note 01 You cannot style via the spritesheet <svg> tag as it is not inherited by its <symbol> tags

1
2
3
4
5
<svg style="display:none; fill: red; stroke: blue; stroke-width: 3;">
  <symbol id="symbol-id" viewBox="0 0 24 24">
    <polygon points="12,2 22,12 12,22 2,12" />
  </symbol>
</svg>

Note 02 While the methods above focused on colours, there are many other styles you can alter, most commonly you’d want to alter sizing via one of the examples below

1
2
3
<svg width="48px" height="48px">
  <use href="#symbol-id"></use>
</svg>
1
2
3
4
svg {
  width: 48px;
  height: 48px;
}

Adding SVG From File

It seems that for <use> to work you need <svg> with <symbol> children somewhere within the DOM, and if you have not manually added it you may want to add it via a function similar to the one below, preferably loaded before the site itself is rendered

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/** 
 * Load SVG from a file url and append to body
 * @param {string} url The url for the SVG file
 */
async function loadSVGFile(url) {
    const response = await fetch(url);
    if (!response.ok) throw new Error(`Failed to fetch SVG: ${response.status}`);
    const svgText = await response.text();
    const wrapper = document.createElement('div');
    wrapper.innerHTML = svgText;
    const svgElement = wrapper.firstElementChild;
    svgElement.style.display = 'none';
    document.body.appendChild(svgElement);
}

Example usage might look something like below

1
2
3
4
5
6
7
8
9
10
// ? Run callback when all resources have loaded
window.addEventListener('load', async () => {

    // Load the SVG into the DOM
    await loadSVGFile('./assets/svg/icons.svg');

    // Show the page element
    page.style.display = '';

})

[!NOTE]

  • There are other ways to import SVG into the DOM without JavaScript but these do not allow access to the <symbol> ids via the <use> tag
This post is licensed under CC BY 4.0 by the author.