More from this category
Resource Links / Other Articles
https://vecta.io/app/dashboard
converter: https://convertio.co/jpg-svg/
photos: https://teamtreehouse.com/community/svg-basics-why-photographs-arent-saved-as-vector-images
https://bit.dev/
https://svgontheweb.com/
https://medium.com/adalab/svg-best-image-format-for-the-web-781713859752
https://deliciousbrains.com/svg-advantages-developers/
https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Adding_vector_graphics_to_the_Web
https://the.shawneee.com/svg-vs-srcset/
SVG on the web
A Practical Guide
One of the great things with using an SVG is we can change how elements within it are styled using good old CSS. Say we have an orange icon and we want it to be blue on some pages, we can do that without having to make a new blue icon. Ideal.
There are two ways we can change styles — inline in the SVG and externally (i.e. within our stylesheet). To put styles inline, wrap them in a <style>
tag and also within <![CDATA[ ... ]]>
. It’s best to do this as sometimes XML parsers can conflict with certain characters (i.e. >
). Even if you don’t have any funky characters in there now, it is best practice to use CDATA
as some could be added at a later time and break all the things.
Inline styles will mostly work in all implementations. <img>
and background-image
don’t support CSS3 animations even if they are inline (see section on animations for more). background-image
doesn’t support inline media queries (see section on media queries for more).
Inline styles
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 68 65">
<style type="text/css">
<![CDATA[
.firstb { fill: yellow; }
.secondb { fill: red; }
]]>
</style>
<path class="secondb" d="M42 27v-20c0-3.7-3.3-7-7-7s-7 3.3-7 7v21l12 15-7 15.7c14.5 13.9 35 2.8 35-13.7 0-13.3-13.4-21.8-26-18zm6 25c-3.9 0-7-3.1-7-7s3.1-7 7-7 7 3.1 7 7-3.1 7-7 7z"/>
<path class="firstb" d="M14 27v-20c0-3.7-3.3-7-7-7s-7 3.3-7 7v41c0 8.2 9.2 17 20 17s20-9.2 20-20c0-13.3-13.4-21.8-26-18zm6 25c-3.9 0-7-3.1-7-7s3.1-7 7-7 7 3.1 7 7-3.1 7-7 7z"/>
</svg>
If you want to use external styles, which are mostly much easier to work with and maintain, you can’t use <img>
or background-image
. If you are using <object>
you need to reference your stylesheet internally from the SVG file (see code following). Remember: if you do this the SVG will also not be able to know what its parent class is (i.e. the <object>
) so don’t try to use that in its styling. Inline SVGs don’t need this added and therefore can be slightly easier to work with in this sense.
External styles
// Add to very start of SVG file before <svg>
<?xml-stylesheet type="text/css" href="style.css"?>
// In style.css
.firstb { fill: yellow; }
.secondb { fill: red; }
JS Manipulation
My JavaScript knowledge is pretty minimal, so I’m just going to point out some basic tips on how you can use JS to change things in an SVG. If you want to embed your scripts within the SVG file, remember to wrap them in <![CDATA[ ... ]]>
again to prevent parsing errors. Scripts will not run if you use <img>
or background-image
as a security measure (i.e. to prevent potentially malicious code running on your page).
When working with external JS (i.e. not embeded within the SVG file), if you have your SVG inline you can target it as you would any other DOM element. If you use an <object>
you can target it with contentDocument
. You can get much more creative than the following, but here is an example:
External scripts
window.onload=function() {
var object = document.getElementById("logoObject");
var svgDocument = object.contentDocument;
var svgb1 = svgDocument.getElementsByClassName("firstb");
var svgb2 = svgDocument.getElementsByClassName("secondb");
svgb1[0].setAttribute("fill", "yellow");
svgb2[0].setAttribute("fill", "red");
};
Fixed width vs responsive
When using images on the web in responsive designs there are two options you can use to style them, you can keep them at a fixed-size and adjust at breakpoints if needed, or allow them to resize with the page depending on their parent container.
If they are a fixed size the only thing you need to be careful of is if you are using the SVG as a background-image
you need to make sure to include a background-size
because browsers can get a bit confused and either crop it or shrink it, particularly if you are showing it at a different size to the actual size of the image.
When implementing an SVG that can resize there are a couple of things to remember (again mostly with the background-image
implementation) as outlined here:
Object
Works as expected with width: 100%;
Inline
Previously needed a max-height
value to work, of recent works as expected. Note Safari doesn’t redraw these as quickly (if they are complex) on window resize.
Img
Works as expected with width: 100%;
Background-image
Needs padding-bottom: #%;
to keep the proportions of the image else it will not show.
Animating
When it comes to animating SVGs there are a few different options that we can use — SVG animation (based on the SMIL spec), CSS3 animations, or JS animations. SVG animation and CSS3 animations let you do most things you will want to do — with SVG animation being slightly more powerful in that it has control over a few extra things. JavaScript allows you to do some pretty complex animations relatively easily, especially with libraries such as Snap.svg. This is a little beyond my knowledge of JavaScript so I’ll let you check out their demos to see for yourself if that is the right option.
SVG animation is super powerful but I’m not going to go in to too much depth on it as to be honest I’ve not really ever used it. I can imagine it being useful for illustrations that you would like to have some nice animations happening with, but from a practical point of view not every project has the time or budget to spend on this. If you do, it is actually pretty simple to start playing around with and there are some great tutorials online. Basically you can add a child element of <animate>
to any paths and shapes in your SVGs which will control the animations. The best thing about it is, it works in all implementation methods. Internet Explorer does not support SVG animation, however you can use a polyfill such as FakeSmile if you need it to work in IE too.
Here’s a little demo to show you. Note: I’ve lightened the blue to make it easier to see the animation.
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 68 65">
<path fill="#4e86b1" d="M42 27v-20c0-3.7-3.3-7-7-7s-7 3.3-7 7v21l12 15-7 15.7c14.5 13.9 35 2.8 35-13.7 0-13.3-13.4-21.8-26-18zm6 25c-3.9 0-7-3.1-7-7s3.1-7 7-7 7 3.1 7 7-3.1 7-7 7z">
<animate dur="2s" values="#000000; #4e86b1; #000000" keyTimes="0; 0.5; 1" attributeName="fill" repeatCount="indefinite"/>
</path>
<path d="M14 27v-20c0-3.7-3.3-7-7-7s-7 3.3-7 7v41c0 8.2 9.2 17 20 17s20-9.2 20-20c0-13.3-13.4-21.8-26-18zm6 25c-3.9 0-7-3.1-7-7s3.1-7 7-7 7 3.1 7 7-3.1 7-7 7z">
<animate dur="2s" values="#4e86b1; #000000; #4e86b1" keyTimes="0; 0.5; 1" attributeName="fill" repeatCount="indefinite"/>
</path>
</svg>
SVG animation
Object
Inline
Img
Background-image
Often when we want to animate icons or illustrations on the web it will be for an interaction, i.e. on hover etc. This falls under CSS Manipulation and Interactive SVG Animation in the table of support above and thus doesn’t work for either SVG animation or CSS3 animations if you use <img>
or background-image
. To get interactive animations in SVG animation we can add begin="mouseover"
& begin="mouseout"
and with CSS3 animations just as you would anywhere else — add classes to the SVG elements and style them on hover
. One thing to note is, if you want to style the animations from your external stylesheet it will work as expected if you have the SVG inline, but if you use <object>
you will need to reference the external stylesheet from within the SVG too.
Interactive SVG animation
Only works with <object>
or inline.
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 68 65">
<path fill="#4e86b1" d="M42 27v-20c0-3.7-3.3-7-7-7s-7 3.3-7 7v21l12 15-7 15.7c14.5 13.9 35 2.8 35-13.7 0-13.3-13.4-21.8-26-18zm6 25c-3.9 0-7-3.1-7-7s3.1-7 7-7 7 3.1 7 7-3.1 7-7 7z">
<animate fill="freeze" dur="0.1s" to="#000000" from="#4e86b1" attributeName="fill" begin="mouseover"/>
<animate fill="freeze" dur="0.1s" to="#4e86b1" from="#000000" attributeName="fill" begin="mouseout"/>
</path>
<path d="M14 27v-20c0-3.7-3.3-7-7-7s-7 3.3-7 7v41c0 8.2 9.2 17 20 17s20-9.2 20-20c0-13.3-13.4-21.8-26-18zm6 25c-3.9 0-7-3.1-7-7s3.1-7 7-7 7 3.1 7 7-3.1 7-7 7z">
<animate fill="freeze" dur="0.1s" to="#4e86b1" from="#000000" attributeName="fill" begin="mouseover"/>
<animate fill="freeze" dur="0.1s" to="#000000" from="#4e86b1" attributeName="fill" begin="mouseout"/>
</path>
</svg>
CSS3 animation
Only works with <object>
or inline. Also works with external CSS as explained previously.
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 68 65">
<style type="text/css">
<![CDATA[
.firstb { fill: #000; transition: fill 0.1s; }
.firstb:hover { fill: #4e86b1; }
.secondb { fill: #4e86b1; transition: fill 0.1s; }
.secondb:hover { fill: #000; }
]]>
</style>
<path class="secondb" d="M42 27v-20c0-3.7-3.3-7-7-7s-7 3.3-7 7v21l12 15-7 15.7c14.5 13.9 35 2.8 35-13.7 0-13.3-13.4-21.8-26-18zm6 25c-3.9 0-7-3.1-7-7s3.1-7 7-7 7 3.1 7 7-3.1 7-7 7z"/>
<path class="firstb" d="M14 27v-20c0-3.7-3.3-7-7-7s-7 3.3-7 7v41c0 8.2 9.2 17 20 17s20-9.2 20-20c0-13.3-13.4-21.8-26-18zm6 25c-3.9 0-7-3.1-7-7s3.1-7 7-7 7 3.1 7 7-3.1 7-7 7z"/>
</svg>
Spriting
You can create and use SVG sprites just as we typically do with PNGs and background-image
to get the resolution benefits or you can take it a step further using the extra power we have with SVG. I’m not going to go in to too much depth here again as it does get pretty complex and I’ve never found a need to implement them personally. The benefit is getting all the power of SVG with fewer HTTP requests.
There are two approaches you can take — in the first you define all the icons within <symbol>
elements in the SVG but hide them. Then reference each later when needed with a <use>
element referencing the <symbol>
with xlink:href="#id"
. The second uses the SVG viewbox
attribute to crop the artboard (area of the SVG that shows) around a certain area. These are both quite advanced SVG uses so only worry about them if you want to use them.
If you do want to learn how to implement these techniques please take a look at the links in the resources, especially Sara Soueidan’s 24ways article.
If you want to use an SVG sprite just as you would a PNG sprite with CSS it is worth noting that you will need to add the width
and height
attributes back in alongside the viewBox
attribute in the SVG code. During the optimising process these are typically removed because they aren’t usually needed. In this case however IE9 & 10 need them to be able to correctly crop to part of the image sprite. This is because those browsers take the width and height sizes specified in the CSS for the image size, but these are actually the sizes of the part of the image wanted (not the whole image). Confusing I know, but it is something I ran into recently.
Media queries
A really cool thing about SVGs is, if you use media queries in the styles you embed within the file, instead of them working from the viewport size they will work from the SVGs viewport size. Basically that means they have their own working implementation of element queries out of the box. Nice. This allows us to control how the SVG will look at whatever size it is shown.
Imagine you are a big brand and you want people to use your logo correctly no matter what size it’s shown. Well you pretty much can! Just embed some media queries and you can change its formatting based on what size it is displayed at. This works with all implementations apart from background-image
and in all browsers (note: IE9–11 seem to ignore some breakpoints). Have a play with the slider below to see an example of how that could work:
Fallbacks
A word on fallbacks. SVGs are supported in all modern browsers. If you still have to support IE8 then you will need to implement fallbacks, most likely in the form of PNGs. I’m not going to go in to this much because you probably shouldn’t be supporting IE8 anymore ¯_(ツ)_/¯. Anyway, if you do want fallbacks, basically things get pretty complicated pretty quickly as most things do with SVG. I would recommend to read this comprehensive article by Amelia Bellamy-Royds on CSS-Tricks.
Resources
General
Optimising
- Tips For Optimising SVG Delivery For The Web
- Understanding and Manually Improving SVG Optimization
- SVG Optimization Video
- SVGOMG — SVGO GUI in browser
Animating
Spriting
- An Overview of SVG Sprite Creation Techniques
- A guide to SVG <use> elements
- Grunticon
- SVG icon workflow
- Inline SVG icons