SVGs are often used as icons in web applications. As vector graphics, SVGs are small in size and high in quality even when scaled. Another benefit is the ability to style them using CSS. It comes in handy when designing light/dark themes and modifying styles on hover etc.
There are three ways of including SVG in HTML, each with its pros and cons for styling and bundling.
1- Inline SVG
Include SVG in the HTML itself.
<html>
<head>
<style>
svg {
fill: red;
}
</style>
</head>
<body>
<svg viewBox="0 0 30 10" xmlns="http://www.w3.org/2000/svg">
<circle id="myCircle" cx="5" cy="5" r="4"/>
</svg>
</body>
</html>

Styling | ⭐️⭐️⭐️ | Can be fully styled using CSS |
Bundling | ⭐️⭐️ | Bundling with icons within HTML can increase the size of the initial HTML sent down the wire. |
Maintainability | ⭐️⭐️ | As the SVG is included inside the HTML, we lose the ability to independently modify the SVG files. Particularly, this could be an issue for library authors. |
2- SVG as image
Include as an image using img
tag or background-image
property.
<html>
<head>
<style>
svg {
fill: red;
}
</style>
</head>
<body>
<img src="circle.svg" alt="circle" >
</body>
</html>
Styling | ⭐️ | As the SVG is added as an image, it is not part of the DOM and cannot be styled using CSS. There are a number workarounds though: 1- design different versions of each SVG icon and swap image files on the relevant event, like hover, using CSS. This involves maintaining and downloading duplicates with slight variations (see an example here) 2- Use CSS filters to change the colour of the icons. It can be tricky to get it right and doesn’t work for all icons (see an example here) 3- Use SVG as a mask instead of background-image. Here, the colour comes from the background instead of the SVG itself. Again, it may not work for specific files. (see an example here) 4- Inject the CSS using client-side JavaScript. This will have an overhead (see an example here). |
Bundling | ⭐️⭐️⭐️ | This provides flexibility as we can have – images in separate files – or merge them into a single file and refer to each using SVG fragment <use> – or bundle them together using data URL |
Maintainability | ⭐️⭐️ | The workaround required for styling makes it a bit less maintainable. |
3- SVG Use Element
In a sense, this approach is a comprise between the above two. The <use>
element takes nodes from within the SVG document and duplicates them elsewhere.
<html>
<head>
<style>
/* works - the variable should be used in the svg file */
:root {
--my-color: magenta;
}
/* work */
svg {
fill: red;
}
/* doesn't work */
.blue {
fill: green;
stroke: purple;
}
</style>
</head>
<body>
<svg viewBox="0 0 30 10">
<use href="my-svg.svg#myCircle" fill="green" stroke="red" />
<use href="my-svg.svg#myCircle" x="10" />
</svg>
</body>
</html>
<svg display="none" viewBox="0 0 30 10" xmlns="http://www.w3.org/2000/svg">
<circle id="myCircle" cx="5" cy="5" r="4" fill="var(--my-color)" class="blue"/>
<!-- <use href="#myCircle" x="10" fill="blue" />
<use href="#myCircle" x="20" fill="white" /> -->
</svg>
Styling | ⭐️⭐️ | – As svg and use elements are part of the HTML, they can be styled, and their styles can cascade down.– Elements inside svg like rect or circle cannot be styled.– Any CSS variable used in the SVG file can be controlled using CSS. This is a bonus as compared to using the img tag.– Classes don’t work |
Bundling | ⭐️⭐️ | This provides flexibility as we can have – images in separate files – or merge them into a single file and refer to each using SVG fragment <use> But SVG has to be in a separate file(s). |
Maintainability | ⭐️⭐️ | SVG segments are referred using the id . This requires a cross-reference between the SVG file and the HTML use tag to be maintained. |