SVG is an image format for vector graphics. It literally means Scalable Vector Graphics. Basically, what you work with in Adobe Illustrator. You can use SVG on the web pretty easily, but there is plenty you should know.
Why use SVG at all?
- Small file sizes that compress well
- Scales to any size without losing clarity (except very tiny)
- Looks great on retina displays
- Design control like interactivity and filters
Getting some SVG to work with
Design something in Adobe Illustrator. Here’s a Kiwi bird standing on an oval.
Notice the artboard is cropped up right against the edges of the design. Canvas matters in SVG just like it would in PNG or JPG.
You can save the file directly from Adobe Illustrator as an SVG file.
As you save it, you’ll get another dialog for SVG Options. I honestly don’t know much about all this. There is a whole spec for SVG Profiles. I find SVG 1.1 works fine.
The interesting part here is that you can either press OK and save the file, or press “SVG Code…” and it will open TextEdit (on a Mac anyway) with the SVG code in it.
Both can be useful.
Using SVG as an <img>
If I save the SVG to a file, I can use it directly in an <img>
tag.
<img src="kiwi.svg" alt="Kiwi standing on oval">
In Illustrator, our artboard was 612px ✕ 502px.
That’s exactly how big the image will on the page, left to itself. You can change the size of it though just by selecting the img
and changing its width
or height
, again like you could a PNG or JPG. Here’s an example of that:
Check out this Pen!
Browser support
Using it this way has its own set of specific browser support. Essentially: it works everywhere except IE 8 and down and Android 2.3 and down.
If you’d like to use SVG, but also need to support these browsers that don’t support using SVG in this way, you have options. I’ve covered different techniques in different workshops I’ve done.
One way is to test for support with Modernizr and swap out the src
of the image:
if (!Modernizr.svg) {
$(".logo img").attr("src", "images/logo.png");
}
David Bushell has a really simple alternative, if you’re OK with JavaScript in the markup:
<img src="image.svg" onerror="this.onerror=null; this.src='image.png'">
SVGeezy can also help. We’ll cover more fallback techniques as this article progresses.
Using SVG as a background-image
Similarly easy to using SVG as an img, you can use it in CSS as a background-image
.
<a href="/" class="logo">
Kiwi Corp
</a>
.logo {
display: block;
text-indent: -9999px;
width: 100px;
height: 82px;
background: url(kiwi.svg);
background-size: 100px 82px;
}
Notice we set the background-size to the size of the logo element. We have to do that otherwise we’ll just see a bit of the upper left of our much larger original SVG image. These numbers are aspect-ratio aware of the original size. But you could use a background-size
keywords like contain
if you want to make sure the image will fit and can’t know the parent image will be of the exact right size.
Browser support
Using SVG as background-image has its own special set of browser support, but it’s essentially the same as using SVG as img. The only problem browsers are IE 8 and down and Android 2.3 and down.
Modernizr can help us here, and in a more efficient way than using img. If we replace the background-image
with a supported format, only one HTTP request will be made instead of two. Modernizr adds a class name of “no-svg” to the html element if it doesn’t support SVG, so we use that:
.main-header {
background: url(logo.svg) no-repeat top left;
background-size: contain;
}
.no-svg .main-header {
background-image: url(logo.png);
}
Another clever progressive enhancement flavored technique for using SVG as background-image is by using it in conjunction with multiple backgrounds. SVG and multiple backgrounds have very similar browser support, so if the browser supports multiple backgrounds, it supports SVG, and the declaration will work (and override any previous declaration).
body {
background: url(fallback.png);
background-image: url(image.svg), none;
}
The problem with both <img> and background-image…
Is that you don’t get to control the innards of the SVG with CSS like you can with the following two ways. Read on!
Using “inline” SVG
Remember how you can grab the SVG code right from Illustrator while saving if you want? (You can also just open the SVG file in a text editor and grab that code.) You can drop that code right into an HTML document and the SVG image will show up just the same as if you put it in an img.
<body>
<!-- paste in SVG code, image shows up! -->
</body>
This can be nice because the image comes over right in the document and doesn’t need to make an additional HTTP request. In other words, it has the same advantages as using a Data URI. It has the same disadvantages too. A potentially “bloated” document, a big chunk of crap right in the document you’re trying to author, and inability to cache.
If you’re using a back end language that can go fetch the file and insert it, at least you can clean up the authoring experience. Like:
<?php echo file_get_contents("kiwi.svg"); ?>
A little PHP-specific thing here… it was demonstrated to me that file_get_contents()
is the correct function here, not include()
or include_once()
as I have used before. Specifically because SVG sometimes is exported with <?xml version="1.0" encoding="UTF-8"?>
that as the opening line, which will cause the PHP parser to choke on it.
Optimize it first
Likely not a huge shocker, but the SVG that Adobe Illustrator gives you isn’t particularly optimized. It has a DOCTYPE and generator notes and all that junk. SVG is already pretty small, but why not do all we can? Peter Collingridge has an online SVG Optimiser tool. Upload the old, download the new. In Kyle Foster’s video, he even takes it the extra mile and removes line breaks after this optimization.
If you’re even more hardcore, here is a Node JS tool for doing it yourself.
Now you can control with CSS!
See how the SVG looks a lot like HTML? That’s because they are both essentially XML (named tags with angle brackets with stuff inside). In our design, we have two elements that make up the design, an <ellipse>
and an <path>
. We can jump into the code and give them class names, just like any other HTML element can have.
<svg ...>
<ellipse class="ground" .../>
<path class="kiwi" .../>
</svg>
Now in any CSS on this page we can control those individual elements with special SVG CSS. This doesn’t have to be CSS embedded in the SVG itself, it can be anywhere, even in our global stylesheet <link>
ed up. Note that SVG elements have a special set of CSS properties that work on them. For instance, it’s not background-color
, it’s fill
. You can use normal stuff like :hover though.
.kiwi {
fill: #94d31b;
}
.kiwi:hover {
fill: #ace63c;
}
Even cooler, SVG has all these fancy filters. For instance blurring. Chuck a filter in your <svg>
:
<svg ...>
...
<filter id="pictureFilter" >
<feGaussianBlur stdDeviation="5" />
</filter>
</svg>
Then you can apply that in your CSS as needed:
.ground:hover {
filter: url(#pictureFilter);
}
Here’s an example of all that:
Check out this Pen!
- More on applying filters to SVG
- The best list I could find on SVG-specific CSS properties (specific to Opera)
- SVG filter effects playground (from Microsoft)
Browser support
Inline SVG has it’s own set of browser support, but again, it’s essentially only an issue in IE 8 and down and Android 2.3 and down1.
One way to handle fallbacks for this type of SVG is:
<svg> ... </svg>
<div class="fallback"></div>
Then use Modernizr again:
.fallback {
display: none;
/* Make sure it's the same size as the SVG takes up */
}
.no-svg .fallback {
background-image: url(logo.png);
}
Using SVG as an <object>
If “inline” SVG just isn’t your jam (remember it does have some legit drawbacks like being hard to cache), you can link to an SVG file and retain the ability to affect its parts with CSS by using <object>
.
<object type="image/svg+xml" data="kiwi.svg" class="logo">
Kiwi Logo <!-- fallback image in CSS -->
</object>
For the fallback, Modernizr detection will work fine here:
.no-svg .logo {
width: 200px;
height: 164px;
background-image: url(kiwi.png);
}
This will work great with caching and actually has deeper support than using it any other way. But, if you want the CSS stuff to work, you can’t use an external stylesheet or <style>
on the document, you need to use a <style>
element inside the SVG file itself.
<svg ...>
<style>
/* SVG specific fancy CSS styling here */
</style>
...
</svg>
External stylesheets for <object> SVG
SVG has a way to declare an external stylesheet, which can be nice for authoring and caching and whatnot. This only works with <object>
embedding of SVG files as far as I’ve tested. You’ll need to put this in the SVG file above the opening <svg>
tag.
<?xml-stylesheet type="text/css" href="svg.css" ?>
If you put that in your HTML, the page will barf and not even try to render. If you link up an SVG file that has that in it as an <img>
or background-image
, it won’t barf, but it won’t work (the SVG will still render though).
Data URL’s for SVG
Another way to use SVG’s is to convert them into Data URL’s. Data URL’s might not save you actual file size, but can be more efficient because the data is right there. It doesn’t require an additional network request.
Mobilefish.com has an online conversion tool for that base64ing them, but I generally don’t think that’s a good idea for SVG. Simply paste in the contents of your SVG file and fill out the form and it will display the results in a textarea for you to copy. Remember to remove line breaks in the data it gives you back. It looks like pure gibberish:
You can use that anywhere we’ve talked about so far (except inline <svg>
because that just doesn’t make sense) Just put the gibberish where it says [data] in these examples.
This converter is my fav, as it leaves the SVG as mostly readable text:
As <img>
<img src="data:image/svg+xml;base64,[data]">
As CSS
.logo {
background: url("data:image/svg+xml;base64,[data]");
}
Relevant note here: regular CSS doesn’t care if you put quotes around the data URI, but Sass does, so I’ve quoted it above (Thx Oziel Perez).
As <object>
<object type="image/svg+xml" data="data:image/svg+xml;base64,[data]">
fallback
</object>
And yep, if you have an embedded <style>
in your SVG before you base64 it, it will work if you use it as an <object>
still!
Format for Data URI
All the examples above have base64 as the encoding, but data URI’s do not have to be base64. In fact in the case of SVG, it’s probably better NOT to use base64. Primarily because the native format of SVG is much more repetitive than base64 ends up, it gzips better.
<!-- base64 -->
data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL...
<!-- UTF-8, not encoded -->
data:image/svg+xml;charset=UTF-8,<svg ...> ... </svg>
<!-- UTF-8, optimized encoding for compatibility -->
data:image/svg+xml;charset=UTF-8,%3Csvg xmlns='http://...'
<!-- Fully URL encoded ASCII -->
data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A//...
Command line thingy for base64ing SVG:
@chriscoyier @hkfoster maybe you could take a shortcut with >>> echo -n `cat logo.svg` | base64 | pbcopy
— Benny Schudel (@bennyschudel) March 2, 2013
Or alternatively Mathias Bynens has some techniques:
Use
openssl base64 < path/to/file.png | tr -d '\n' | pbcopy
orcat path/to/file.png | openssl base64 | tr -d '\n' | pbcopy
to skip writing to a file and just copy the base64-encoded output to the clipboard without the line breaks.
And a drag-and-drop tool.
Automation Tools
- grunticon:
From a CSS perspective, it’s easy to use, as it generates a class referencing each icon, and doesn’t use CSS sprites.
grunticon takes a folder of SVG/PNG files (typically, icons that you’ve drawn in an application like Adobe Illustrator), and outputs them to CSS in 3 formats: svg data urls, png data urls, and a third fallback CSS file with references to regular png images, which are also automatically generated and placed in a folder.
- iconizr:
A PHP command line tool for converting SVG images to a set of CSS icons (SVG & PNG, single icons and / or CSS sprites) with support for image optimization and Sass output.
Related Stuff
- David Bushell: A Primer to Front-end SVG Hacking
- David Bushell: Resolution Independence With SVG
- MDN on SVG
- Browser support for a variety of different SVG related things.
- Peter Gasston: Better SVG Sprites With Fragment Identifiers
- simuari: SVG Stacks
- SVG.js – “A lightweight library for manipulating and animating SVG.”
- Emmet has an awesome way to get a data URI from an SVG right from your code editor.
- Compass has a helper for data URIs too.
- Adobe: Styling SVG
- Andrew J. Baker: Taming the SVG Beast
- Illustrator alternatives: Inkscape, Sketch
- Krister Kari: Dealing with SVG images in mobile browsers
Kyle Foster’s An Optimized SVG Workflow, which is worth an embed:
1 And speaking of Android 2.3 browser, this. But if you absolutely have to support the native browser, this.
Seriously comprehensive article Chris, opus indeed. Is going straight to the TOP resources folder in the bookmarks.
Already been busy with SVG, the way I handled the fallbacks back then was swapping out the extension .svg for .png if Modernizr showed browser didn’t cut the mustard..
+1
Thank you for the post Chris, I needed an SVG low-down. Just to say that Inkscape is a magnificent cross-platform, open source SVG vector editing program, way better than Illustrator ;) plus SVG is its native format.
+1. Inkscape is great on Windows/Linux.
Not so great on Mac though. Sketch is a much nicer experience on a Mac.
I did a test with Inkscape, a simple text image saved as svg but there is nothing on the browser. I tried other images from internet and works fine. Is there some special setting that I have to use in Inkscape?
@Christos Inskape saves as “Inkscape SVG” or as “Plain SVG” – the latter is the format you want for the web. But in most cases, either will work, and I’ve never had one simply “not show up.” Can you view the image on your computer (whatever picture viewer you normally use)? Can you re-open the image in Inkscape?
I work on Inkscape for all my professional graphics, on a mac. It just screws up the shortcuts which you need to edit, and done. Plus, I had to disable a ‘pasteboard’ setting to allow it to copy vectors files as-is from other mac apps. That’s it and it works great!
This is awesome, Thanks Chris. Alright, so If we can treat svgs like imgs, can we use them for fluid text? . . . sounds like a codepen I’m going to have knockout.
Compass users don’t forget you can base64 svgs into CSS just by using ‘inline-image’ instead of ‘image-url’.
Ohh… what does this look like?
Just when I thought I learned it all, there came SVG. Thanks for the inside scoop on this. Look forward to harnessing its power.
Also, if using Inkscape there’s some pointers here for how to optimise: http://benfrain.com/tips-for-using-svgs-in-web-projects/
Another cool feature with svg : you can use media-queries inside the <style> element (inside your svg)
This way the image responds to the parent size (<object> for example) . Then you can reorganize content into your svg depending on parent size : a smaller text, or “blocks” of content position (text is at the right of the “image” in landscape orientation and goes to the top in portrait mode)
I’ve made an ugly demo of this here (go to the bottom of the page and click on “give it a try” link) a “tag” appears at the top right corner of the screen and reads “you can use svg in responsive web design” into wide screens and “use svg in RWD” into smaller ones.
Onto this page you’ll find some ways to embed svg
The snippet I used was (is still?) useful when some browsers show an unwanted padding at the bottom on resize. Since I made this browser support got better, I’m not sure it is still needed (I have to make some new tests…)
The zebra svg color changes with breakpoints
You can also use javascript inside svg and filters are quite well supported in browsers ; ) (sometimes in a better way than illustrator or inkscape)
Inkscape is a free and open source software dedicated to svg, very useful …
Pascal
forgot the link to my demo :( , sorry :
http://soqr.fr/testsvg/embed-svg-liquid-layout-responsive-web-design.php
Hi @eqroeil, your posted comment addresses what I’ve been trying to figure out – how to make SVG work in responsive design. No one is addressing this.
Here’s my codepen: http://cdpn.io/qItAC
On the left is #ALA art – the paint brush. Next is my logo and then a second version of the paint brush. The 2nd version and the logo both have width and height removed, only veiwBox and “preserveAspectRatio=”xMinYMin meet”. These scale with the container but they break the object box. Why why why?
I have been searching for the right solution. Your example works. I will be pulling it apart today to understand why! Any comments would be most appreciated.
I’ve been trying to use SVG images as a background image on responsive div’s:
div class="span4"
but unlike an
img
I cannot usewidth="100%"
which will automatically scale it, and despite mydiv
resizing as the browser window changes size, the background svg dimensions will stay the same. This is not really specific to SVG’s as it happens with PNG’s/JPG’s too but something you need to keep in mind.Not a problem in modern browsers, but your usual suspects (IE 8 and lower and possibly IE9) have trouble with this.
You should have a look with preserveAspectRatio=”xMinYMin meet” added to your svg and only keep viewBox=”0 0 800 960″ (removing width and height, but it should not be necessary…)
into your css try background-size: cover (or contain)
maybe…
as a fallback for ie : conditionnal classes and png fallback ; )
.ie8 .span4{
background: url(thepngone.png);
}
I dont think is what you needed but it might be useful for someone.
Responsive element with SVG as background keeping ratio:
Nice post Chris! Tiny bug in your object fallback though:
.no-svg .logo {
background-image: url(kiwi.svg);
}
Should be
.no-svg .logo {
background-image: url(kiwi.png);
}
Thanks! Burying cause fixed.
Good to get more info on fallbacks for SVG. I’ll have to get to work on them for my websites.
My last two designs have included nothing but SVGs in the main layout with background textures, header images, logos and other elements being nothing but SVG. They look awesome on a Retina display! What I have noticed however is that the graphics do tend to look slightly different across browsers. On Storiva.com for example, It appears that Fireworks is correctly interpreting some of my gradients in the header background as an ellipse gradient, whereas in Chrome and Safari, they appear to be interpreted as radial gradients, resulting in slightly less vivid colors. I thought that was rather interesting, but definitely not a deal breaker.
Anyway, thanks for such a thorough review Chris! Much appreciated.
I had an issue with svg in ie10 (and possibly 9) recently.
I was building a site that had a svg logo in header and footer. In the header (which as position: fixed) I used a div tag with the svg as background, and in the footer I used it as a img tag. The background in the a tag is used in the original size, while the img tag is a little smaller for design purposes.
The issue is that sometimes explorer moves and crops the background in the header when another element with the same svg file as source is set at a different size. This problem is happening in ie10 but I think it happens in ie9 as well.
I’ve made a fiddle in: http://jsfiddle.net/uK2La/
(I have also made a pen at http://codepen.io/anon/pen/zviwF but most of the time the error doesn’t show until you resize the window).
I solved it in this specific case, however I don’t know if this is an ie bug or I missed something. Other browsers seems to work fine.
hi,
http://jsfiddle.net/uK2La/14/
seems IE10 uses the exact same image and somehow fouls up, workaround seems an extra parameter for one image. Will have other issues (like cache I guess) but seems to work. You should file a bug report at Microsoft, generally I have fewer problems with IE10 than e.g. Chrome with stuff.
BTW, the classList API works nicely for your example… supported in anything except IE<=9 it seems.
Great Article! Thank you, I really have been struggling with how to incorporate svg into my projects lately.
The canvas size gets old fast if you’re not used to it. One thing that I’ve found helpful when saving as SVG is to select your art and then go to: object>artboard>fit selected to art. Hope that makes someone else’s life a bit easier.
How do you handle SVGs inside a link? I’ve been trying to figure out the best way to do this.
I’ve been using this method as a fallback for SVGs as background images –
The idea is that the SVG will either override or be ignored depending on support.
It’s a bit simpler than Chris’ method. Seems to work well for me but maybe there is there a flaw in this that I’m not seeing that somebody could point out?
You will be loading both unnecessarily, when only one is going to be displayed. But I think this is pretty neat to get it to work, though.
Never thought about that Vinay, so I decided to check with Chrome and Firefox’s network profiler and only the svg file seems to be downloaded. Can’t be bothered firing up VMware to test IE but I’d assume it’s the same. Still wondering if there is a problem with this method because it feels almost too easy.
I’m pretty sure you’ll be loading both in every example used above. The difference between the one above and the one by James is the simplicity. The only way to be sure not download both is to use a data URI (pre-loaded) or check for browser support before elements start loading and replace/insert different extensions.
You can also try:
:root
has the same level of support as svg for desktop browsers at least. Not sure about mobile ones. Since invalid selectors and properties are ignored, the svg file will only be downloaded in more modern browsers. The downside is that browsers supporting svg will download both :(This was my first idea when I read article. Why not use simple cascading rules to achieve this fallback? I decided to look further at this and I can tell you why this is wrong. I am 100% that in almost every browser (actually on every I tested, and I tested on lot) will load ONLY one image. This was my first WOW. But could this be so simple? Answer is NO. As only one image is loaded there is no fallback. If .svg will not load (becasue is not supported for example) then nothing will load. That situation appear for example in IE8.
Regards.
Dawid.
Also consider, this method for creating a PNG fallback for browsers that throw an error on SVG within an img element. jQuery:
Demo: http://wedelivery.com/lab/svg/
If a browser doesn’t support SVG and you want to provide a fallback for your content, you might as well attempt to replace all of them. Defining a specific pattern and sticking to it will help. For example, maybe all of your fallback images are named the same as the SVG file except with a .png extension instead of .svn:
Nice!
Just as a note to someone who might use this: remember that you actually have to produce those .png replacements and have them side by side in the same directory, every time.
Thanks for sharing this Chris, great write up.
Chris, please mention this important SVG issue with Firefox:
In Firefox, SVG used as a css background-img is bitmapped at its original designed dimensions, before it is scaled up or down. This results in very blurry images when upscaling a small SVG. Some suggest to simple use a gigantic SVG so you never upscale, only downscale. But I have seen horrible performance when you use a huge SVG and downscale (though that when the element was 3d transformed and animated).
Kinda funny that this implementation of SVG isn’t S or V…
Check this page in FF, it shows the bug well
http://dbushell.com/demos/svg/scaling-09-03-12/
(bugzilla is under maintenance, but this might be the bug, I can’t check now)
https://bugzilla.mozilla.org/show_bug.cgi?id=600207
Workaround is the above mentioned other options, like inline SVG.
Firefox for many many versions has not fixed that bug. As a result, I don’t think SVG as a CSS background is a good option at the moment. Which is sad because background-cover and centering makes it such an attractive option.
Thank you! I was about to post something similar. I’ve had some serious frustrations trying to use SVG background, only to see it look terrible in FF. Inline definitely helps, but there are some real advantages to backround images and it’s interesting that Firefox still has this bug.
Check out this side by side close up of apple.com’s menu, which uses a SVG sprite. Chrome is on the left, FF on the right.
I actually ran into the opposite when setting up svg’s for mobile. Firefox for mobile displayed them perfectly where as chrome for mobile pixelated them so badly that I ended up scrapping the svgs and using double sized pngs scaled down using background-size.
I’ve tried all of the workarounds for FF, and they all seem to be less than 100% effective. Go David Bushell’s home page, and you’ll see that his .svg logo gets blurry and less blurry as you zoom in and out with FF.
Using an img tag didn’t solve the problem for me.
Stripping out height and width from the .svg code appears harmless and helps somewhat.
I’m considering just using a FF conditional to serve .png…
@Peter Foti – agreed,
'img[src$=".svg"]'
much better!Humbled and proud to be a part of this article. Thank you, kind sir.
I had a messy experience here with inline svg and animation.
I didn’t have time to optimise. It’s quite cute on FF; There’s so much to do with svg inline and css. Thanks for the good advices. (I use inkscape on linux)
Very nice post, I have also created a post not long ago about SVGs and animation of them. You can find it here: animating-properties-of-injected-svg-elements
I think SVGs are terrific for multiple purposes but they are not getting the attention they deserve, especially in this new multi-screen era that we are experiencing, their scalability is life-saving.
What kind of magic base64 encoder do you use to make it shrink?
Base64 is larger than raw formats, including plain text.
Thanks for tutorial. I use SVGO GUI for optimizing SVG vector graphics files.
I prefer the invisible gradient technique as fallback for SVG
Fantastic information.
For what it’s worth, here’s a a demo of a draggable and zoomable SVG:
http://www.cyberz.org/projects/SVGPan/tiger.svg
source: http://www.cyberz.org/blog/
Wa, Nice post, I’v got something from here
Excellent article.
Just one remark. You say :
It’s not true. You definitely can style them with CSS.
You only have to use <style> element inside your svg
(because not every browser support <?xml-stylesheet type=”text/css” href=”svg-stylesheet.css” ?> )
A very good article, although not comprehensive – it lacks information about using links inside an SVG as well as the possibilities for animation (although that would require an article all by itself).
I have been meaning for a long time to use SVG in a website but for the moment I only use it to create procedural graphics, like Guilloche patterns, such as this example-
Guilloche experiment #1
Really wish this post existed 6 months ago. Google used to return so many horrible adobe links from 2001 when you googled anything about SVG.
SVG will only get bigger with all the high DPI devices coming out.
Below is the sass/scss mixin I’ve used on lots of builds.
Hi there!
I just want to point out that SVG actually can be considered an application engine with vector graphics presentation built in, as you can script the document and css it very much like you do with HTML. SVG could be used instead of HTML if you want more low-level graphics primitives available in your main layout rather than the high level “document” semantics available in HTML (browsers probably need the SVG viewport be wrapped by the HTML tag though at the moment).
Wow, great article Chris. I just skimmed it, but will definitely dive into it soon.
Just one quick note: If you have a SVG file, you don’t have to explicetly save it as “code”, an SVG file is per already “written in code”.
One minor correction: base64 encoded svg for data-uri will always be more bytes than an un-encoded svg. I’m thinking the optimisation you’re thinking of is the http request you avoid by embedding?
In theory you can get use un-encoded svg in data uri’s, but browser support is a bit flaky:
http://rod.vagg.org/2012/05/data-uri-svg/
Fantastic article. It for this sort of stuff that I subscribe! Thanks :)
Check out this tip by Ben Schwarz:
“All browsers that support SVG background images also supports multiple background images.”
Apparently Android 2.3 rains on that parade. I personally haven’t tested this.
Good catch! Thanks for pointing that out.
All browsers that support SVG background images also support background-size unprefixed. IE8 doesn’t support SVG or background-size, Android 2.3 doesn’t support SVG but requires a prefix for background-size.
Great image choice – a Kiwi isn’t just a fruit!
when using the optimize tool, always check for distortion in your svg output and also check if something is off..
in my case it didn’t leave the id in for my linear gradient, which resulted in a pure color instead of a gradient :P
SVG should be used more. Wikipedia is the only website that comes to mind that uses SVG on a regular basis
MSN on our IE10/Windows8 pages use an inline SVG for the header logo, and use CSS to change the color for the different channels rather than have a bunch of differently-colored PNGs.
Great Article! Actually have started using SVG just few days back so I am new at it. But the biggest advantage is that I can simply create vector graphics in software like Illustrator and use them as SVG in my designs. They are helping me reduce the size of my designs to a great extent.
Thanks for sharing such a valuable information, really helping me a lot to better understand SVG
Please note that as I tweeted you, SVG as background-image doesn’t play well in Opera: http://stackoverflow.com/questions/15220910/svg-as-css-background-problems-with-zoom-level-in-opera
Also, as mentioned by caniuse.com, SVG-as-image is fuzzy/pixelated when zoomed or printed in all browsers but Chrome 23+ and IE9+ because the browsers first renders SVG into a bitmap then zooms that bitmap in instead of re-rendering when the zoom level changes
This is amazing resource. I read a lot about SVG, but never used it on my projects. Will do in future for sure!
Hot Link Flat UI is not working.
Sorry – didnt know where else to post this as there is no comment section on those links
Do I stand correct that you can’t style the svg when it’s base64 encoded within the css? Like in http://codepen.io/anon/pen/oFhzA
Codepen doesn’t seem to like the inline-image property, but you get the point.
How can you talk about SVG on the web and not mention RaphaelJS? Granted, it’s more about dynamically rendering SVG and interacting with it, but to quote their site:
I’m pretty sure it has touch support (dragging) baked in. Check out the demos on their site.
And some good plugins:
export “instructions” as json
export “instructions” as actual SVG
convert to PNG/JPG in browser with canvg — this is super awesome for exporting; you can basically make your own image editor in the browser
Example of a drawing app — Raphael SketchPad
And if you find some polygon formulas, it makes it really easy to make complicated shapes (I’ve built something for hearts, stars, and triangles)
+1
I’m using the Raphael library to handle SVG graphics on one of our sites. I understand it uses VML on IE platforms that don’t support SVG.
I use it for custom charts, which were previously drawn using a graphics library on the server and streamed as images to the browser. Doing it with SVG has allowed me to interact with the charts in Javascript, for example I can highlight a plot on the chart when the user hovers over a name in the legend.
The Raphael commands are embedded in the HTML, which makes the page size a bit larger than before, but it hasn’t affected page performance noticeably and the pages are now served with a single HTTP request instead of several.
Nice article Chris.
Recently I used SVG for a logo (as an
<img>
tag), and with essentially no users of that site on Android 2.3 I only had to worry about oldIE, which meant I was able to use conditional comments and avoid JavaScript altogether.I wrote it up here.
This is awesome, Chris! Thanks a lot for putting all this together. Especially the combination of SVG and CSS opens so many opportunities. I’ll have to try some of this stuff myself! Thanks again
Great article. One other useful bit of knowledge. If you embed an SVG into LESS and probably also SASS you can set the fill colours using variables. This is very handy for me as I can use standard icons on several websites but each site sets it’s own colours.
This is easier more understandable base64 code (for the Terminal):
openssl base64 -in kiwi.svg -out kiwi_64.txt
I added a couple of things to the inline SVG example to make it accessible:
http://codepen.io/bensmithett/pen/oyqhc
Super helpful article :)
Although the SVG being sensational, I regret the fact that he was too slow to use it in games with JavaScript. I think we could do more with the SVG compared to the Canvas, but by its slowness, we have to resort to the canvas.
I opened this article thinking it would be a little explanation and some code snippets. However, my mind was officially blown from start to finish. Insanely good article, this one is totally getting a bookmark. Thank you Mr. Coyier for filling my brain with some more goodness.
That’s a pretty comprehensive article on SVG, I loved it. Saving it for later. I am also really confused between all the SVG vs Canvas stuff in the context of web gaming.
This is the first time I have heard about this. More people should know about this. I am definitely tweeting this one! I will have to bookmark this and create SVG’s when I have the time.
Amazing, Thanks a lot.
Wow! Definitely the best article i’ve come across regarding SVG’s.
I am going to use this format for a website logo. For semantics, would it better to do it in the HTML as an IMG tag and suffer the additional HTTP request, as opposed to doing it via CSS?
If you consider it part of the content, then it deserves an img tag. If you think it is presentation only, then make it a background image via CSS.
Well I am pretty certain the main logo of a website is content, and not presentation. So using an IMG tag would be best practice. My question in this instance was semantics vs performance.
I am now thinking about the last technique Chris talks about, using base64 in the IMG tag, along with an ‘alt’ tag
Wow I did not realize you could get the straight SVG from illustrator. great feature!
Hello!
in our app for android made with html5 +backbone + phonegap we decided to use svg for some illustration. This decision is giving me now some really hard times. The svg i’m trying to embed are not basic svg.
I managed to add the dropshadow as a filter directly into the svg. The cool thing is that it renders well into any of the browser I used in the android device. But when you open the app created from the same html5 with phonegap and run into the same device the dropshadow filter is not rendered. I’m using for testing a HTC one X with the latest android distribution.
Does anyone has an idea why phonegap seems to strip filters from the svg? I’ve tried to look on the web for this issue but got no clue…yet
thanks
Mike
Thanks for the overview Chris! A lot of things in here that I did not realize were possible!
You can also use php to generate data-urls on the fly. For example:
The call it with this:
Okay, I am still not clear about what format of SVG to use. For example, for animating with CSS3, which method is the best? Also, for making responsive graphics (like logos) which one is the best? I have seen many people suggesting different things but there should be at least one that works well for styling and manipulating with CSS…
Just discovered one caveat when styling the
fill
property with CSS – you need to remove any hardcodedfill
attribute that Illustrator exports.Eg
<svg class="foo"><g fill="#FFF700"><path... /></g></svg>
won’t have its
fill
attribute overridden by.foo {
fill: #bada55;
}
If you target the svg element that has the fill property it overrides hard coded attributes. i.e. change to
.foo path { would also work.
In order to use SVGs you’ll need to make sure that your server has the correct MIME type set to serve that file type: “image/svg+xml”.
Thanks for this great writeup on good practices for using SVG on your website.
Incase you are struggling to get the SVG to display on your page, an easy fix is to modify the AddType in your HTACCESS file.
Add this towards the top of your HTACCESS:
Thank you! This was driving me nuts. I mistakenly assumed that my host had this by default.
Chris you are awesome !
Awesome always :)
I currently wrote about SVG Stacking as a replacement for CSS Sprites. Therefore each icon is stored in the same SVG file but within its own layer:
» http://hofmannsven.com/2013/laboratory/svg-stacking/
Such a shame you have to embed the SVG XML in a page to style it, it would have been so powerful to have multiple instances in a page and style them differently based on their context.
I’ve started playing with the Raphaël JavaScript Library. It’s pretty and seems powerful. From the site:
It’s well documented on the site but is sparse on tutorials on the web.<br/>
Does anyone have experience w/ it?
Yes — as I mentioned and this guy replied. Some of the included examples in their documentation are hard to follow, but most everything you need is there. Drop a line with questions.
Keen to know if anyone else has come across the same issue I am having with a site I’m building.
I am testing the site in Chrome (latest version). Modernizer returns support for svg and I can directly access the svg file in the browser (displays fine) but it just won’t show up on the page. In all instances the svg’s are set as background images in the CSS.
I have used this for js detection of svg support.
/* simple SVG image support detection */
if (document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#Image", "1.1")) {
document.documentElement.className = "svg";
}
with this in css
#content {background-image: url(images/logo4.gif);}
html.svg #content {background-image: url(images/logo4.svg);}
thanks to this site for the info on svg use.
http://www.voormedia.nl/blog/2012/10/displaying-and-detecting-support-for-svg-images
made a bash script to simplify the base64 option Mathias Bynens authored.
“inability to cache”? Inline SVG is just part of the HTML document, isn’t it? So if the document is being cached, the inline SVG is being cached too? I don’t get it.
Right but you probably don’t cache the HTML very hard, if at all. For instance, the cached HTML of this very page is being invalidated right now because I’m adding this comment.
Downloading free or stock vector art from the web, I often couldn’t get it to display. It seems some browsers don’t like the “inkscape:” and “sodipodi:” prefixes in the code that appear in many SVG images. For me, it seemed that if opened the file in a text editor and deleted those phrases, it worked fine.
Good tip on the blur in Firefox. Most of my images look fine in Firefox, so I stopped looking carefully at each one in FF, but there are a few that scaled up images that look bad.
Reading this has brought back bad memories of php… Such an annoying language, the verbose requirements of semi-colons…. even in templates.
Working with Django is so much easier.
@Chris Coyler if your page cache is being invalidated by simple changes like comments, then you need to look at using a better templating system.
Django has the concept of Application Level Cache, Whole Page Cache and Block Level Cache: https://docs.djangoproject.com/en/dev/topics/cache/
In the scenario you describe, I’d be wrapping the SVG include inside a block level cache that is only invalidated if the svg were updated (assuming it’s pulled from a ORM query).
Surely the php goblins have something similar?
Uh… he’s talking about client-side page caching — literally, if the HTML has changed it’s a “new” page. Nothing to do with your language of choice.
Possible workaround would be ajaxing in truly dynamic content like the comments, but then you have to jump through crawler hoops to index it.
Hi, I just used (based on a video of teamtreehouse with a correction in conditional comments by Ian Lunn) a svg as a logo with conditional comments as a fallback to a png… here is the code:
It works just great! and to add a link you can follow this easy example found on fiddle (no js)
http://jsfiddle.net/WEbGd/
Sorry, in the closing object there is a mistake… it’s object and no objetct. :D
Raphael is a very necessary library when working with SVG! Cool article though, thanks
For IE7 – 8 and crossbrowers there is
http://www.pep-site.fr/logo_html5.php
Strange I’m not able to resize my svg’s with css in IE9. The SVG’s have viewports, widths and heights, they just don’t seem to be responding to css rules. There are (or should be, in IE9) svgs in the top right corner of each of the 6 white panels here
Replace:
svg width=”640″ height=”480″ version=”1.1″ baseProfile=”full” xmlns=”http://www.w3.org/2000/svg” xmlns:xlink=”http://www.w3.org/1999/xlink” xmlns:ev=”http://www.w3.org/2001/xml-events”
With:
svg xmlns=”http://www.w3.org/2000/svg” xmlns:xlink=”http://www.w3.org/1999/xlink” x=”0px” y=”0px”
viewBox=”0 0 640 480″ enable-background=”new 0 0 640 480″ xml:space=”preserve”
And it should work just fine. I’ve experienced scaling problems with using width and height attributes in svg, and never seem to have problems just eliminating them.
You rock! My viewport was missing!! No more coding at 3am. Thanks so much for catching that, I could have sworn I had one in there. So, for IE9 there seems to be good reason to include a height and width, check out this blog post.
I can’t seem to replicate the problems that seowarp.com experienced by omitting the height and width attributes. I’ve used .svg images very extensively on several sites (Responsively resizing with rem) and they all have the proper aspect ratio in cross-browser testing. Whenever I’ve noticed an image with a bad aspect ratio, it always has a height and width in the .svg code I forgot to delete. I always define height and width with CSS and omit them from the .svg itself; I noticed that you’ve only defined width on your site.
I’m certainly not an expert… …curious what the actual right way to do this is.
What do the other tricksters think?
After some further unintentional science, I seem to experience occasional problems using .svg as a background image with height and width, which are fixed by deleting height and width within the .svg and only using css to scale the image. Confusingly, I can experience problems by omitting the height and width within the .svg if I use an .img tag to embed the image.
Hi, I’ve found you can also use @import within the svg document to load an external CSS file.
Thank you for your detailed coverage of SVG images, Chris. It was very helpful for me, since we plan to use it in some Apps (Webkit only). Therefore we also don’t need to worry about fallbacks or incompatibility.
Firstly Chris, a massive thank you for the write up. I gained a huge amount of knowledge.<br/><br/>I did come across one ‘issue’ that maybe worth mentioning as I couldn’t find anything mentioning it. Using the <object> tag and a Data URI (To get around Chrome’s CORS issue, as I wanted access to elements inside the SVG), Chrome seems to lose the ability to render any gradients.<br/><br/>Example here: http://jsfiddle.net/mikedidthis/rXJXq/1/<br/><br/>I don’t think I missed anything. :(
Hi, great article indeed, I’m just having only one problem:
I have my SVG base64 encoded using Mobilefish.com service, but sometimes I have an error on Chrome that says: ERROR 414 – URI too long.
I think it depends from my webserver, but I have to push my stuff on prod and I have to be sure that I won’t have that error
Do you have any idea/suggestion on how can I “fix” this problem?
Thanks in advance.
Any one has been facing the same problem with base64 svg data URI?
One extra trick for the list, purely for completeness if nothing else. Similar to the
<object/>
method with the addition that it also supports CSS (I think … maybe).Seemingly no IE support at all however.
Chris, Pretend a whole bag of peanut m&ms was modern day currency for $100. Then pretend I knew your address. I would send you a bag of peanut m&ms in a heartbeat my friend! How you write—articulating in easy-to-understand language—is balm to my soul. I’ve been scouring the internet trying to learn to use svgs for the first time. I almost got scared away. Gosh. Talk about confusing. Then I found this gem, hours later… Man, remember that bag of m&ms? Yeah. I meant it! Thank you so much man!!!
Nice one Chris, already started using it for a client. Very good writeup, maybe better than MDN as far as practicality goes. Thanks again!
I’ve been searching for some information on printing SVGs for a while. Some seem to render, but are cropped, some don’t show up at all and I don’t know the distinctions.
For instance, this simple resolution test doesn’t print them at all.
But your codepen example renders them, but they’re cropped.
Any hints?
Hi all, I’m using the “Data URI’s for SVG” option and all is well apart from the background position in IE.
It seems like IE will only display the svg centred. Cannot seem to override this. I initially had the aligment included in a background shorthand, but also tried separating the css background declarations to no avail.
Anyone else confirm this as I may be wasting my time trying to fix this!!
Hi, thank you for this useful guide. Based on this guide I have made world flags rendered only by CSS: http://www.phoca.cz/cssflags/ . Of course it has pros and cons. And the CSS can be improved (it is just experimental).
One thing, I have discovered, not sure if this is valid for all file sizes, but the base64 encoding is much larger then pure SVG code.
Unfortunately, Internet Explorer does not support raw SVG code in background attribute, so this is the only one reason why to encode SVG code, I think (maybe I am wrong). The same with uri encoding, the output is smaller than base64 but for Firefox you need to change this character: “#” and of course in Internet Explorer it does not work either.
Anyway thank you again for this guide.
Jan
@Jan nice work. Sorry to post this here rather than your support forum, but I noticed the top-right and bottom-left stripes in the AU flag are off…
@Jeremy
Hi,
thank you for the info, seems like there were some problems while cleaning the SVG.
I have cleaned it manually and it seems, it is OK now:
http://www.phoca.cz/cssflags/#australia (make F5 – refresh the site as the wrong SVG can be cached)
Thank you, Jan
Great (inspiring) article. I’ve now been using svgs on my and clients’ sites for several years. I even converted my logo to an svg — the language seems straightforward enough. One last puzzle for me is the danged css. I have a gradient background, currently set in “html” along with “min-height:100%”. Why? This seems to ensure the gradient proceeds on down the viewport even on pages whose content is very brief. (Like one-liners.) However, the gradient gets stretched to the full length of the content instead of the viewport for longer pages. How consistently (device-agnostic) to fill the viewport?
Thank you for the article – I am new to svg (and Illustrator) and this helped me enormously.
I have made a glass button in Illustrator as per these simple instructions and saved it as an svg file using your recommended settings above. It looks great in Illustrator but looks terrible in a browser: the transparent gradient doesn’t work at all. I have googled this for a solution until my fingers are bleeding but cannot find one anywhere – is there one?
Thank you again for your great article.
Hey Chris / anyone else reading this,
I’ve got an image inside a unicode character,▼, giving me a nice effect without having to create a transparent png, it actually looks pretty neat.
Was wondering if it’s possible to animate the image inside this ? Tried to animate opacity but it’s not looking very good (never reaches full opacity for some reason, guessing a bug in webkit?) http://jsfiddle.net/n7Wy6/
Just wondering what else is possible?
I’ve done so much research online and I genuinely cannot figure out how to make an svg logo in illustrator and have it appear on a website with a transparent background…
I want to use an svg file for a very small icon in a menu (combating the zooming problems) however it is appearing with a white background.. Is there a way around this??
Great article/tutorial, helped loads … Extra thanks to Ben for his tweaks to make it accessible (march 7th post).
J
How do you do a fill change on :hover when your svg icon is like a ‘hollow’ box? Once I’m inside the box, and not technically on the thin svg, I lose the hover. I tried doing a display:block on a parent div and putting the over on that. It seems I can’t override anything in the xml loaded stylesheet via an external one.
I hope that makes sense. I’m trying to work with an envelope icon made up of very thin lines. The inside of the envelope is transparent. Unless I’m on the thin lines, I loose the hover.
I solved the problem above by using a hover on a group, defining an opacity 0 rectangle inside, then having my path. This way if you have a thin icon, you’re using the invisible square to define the ‘hotspot’.
Note: I didn’t post the html here, but I used the object method Chris described above.
svg.css:
/* Icons */
SVG:
Hi Technie Geeks,
Can any kind soul tell me in simple english how one can place an.svg Image file into a HTML5 webpage?
I’m old-fashioned in normally using the standard HTML format but would like to know how and where to place the embedded svg code?
What a fantastic post and discussion. Thank you!
I’m curious, has anyone experimented with creating their own font as an alternative means to achieve vector quality/scalable graphics with CSS control? Doesn’t fontface have better support in older versions of IE than SVG?
http://caniuse.com/fontface
http://caniuse.com/svg
I’d like to use SVG in my projects, but the inability to cache seems like a huge dealbreaker. If you use it on your logo, which is on every page, wouldn’t that make the entire site in-cacheable? What if it’s for a large complex site where caching is crucial for performance?
Thanks for the article! About the usable properties for styling, I found the following:
http://www.w3.org/TR/SVG11/styling.html#SVGStylingProperties
Don’t know if it’s up-to-date/relevant/implemented though.
The issue with Firefox making scaled SVGs blurry, mentioned above, has been fixed from version 24 and up. The most recent version at the time of writing this is 28. (24-04-2014)
Perhaps I’m confused, but since IE8 doesn’t really support javascript I don’t see how this is gong to work.
if (!Modernizr.svg) {
$(‘img[src$=”.svg”]’).each(function() {
var $this = $(this); // this = img
$this.attr(‘src’, $this.attr(‘src’).replace(/svg$/, ‘png’));
});
}
I’ve tried adding it (in a script tag pair in the header) and it fails on IE8 tests as does the solution proposed here http://wedelivery.com/lab/svg/ (posted by someone above)
Am I missing something? Can anyone point me to a site that shows a clean swap from svg to png in IE8 using that global script?
The version that uses onerror works because the overlap between jscript (M$’s script version and javascript is sufficient to make it work but the global one does not seem to. I would love a global solution for that as now we just degrade the whole site and suggest they might want to think about a newer browser.
Based on your article, I made a command line SVG optimizer and base64 encoder. It is very easy to use “svgoptimizer -h” will show how it is used. https://gist.github.com/mrinterweb/11303706
I have a Q? I used the object route for the .svg – it worked great in some ways… the fall back .png worked.. my .svg tho viewed online as a box in the correct size but it had the .txt file code in it?? I did make my .svg in ILL cs3 and used DW cs3 to html and upload… I tried it every way even your other opts and still – I think it works but my .svg shows as text code in image area with scrolls… I even tried all the different opts when saving .svg found on various sites… hmmm can u help? Has anyone had this [what I am sure is a minor…] happen before… Do I need to use the cloud or cs5 or higher… My site is HTML 5 and reponsive… I am baffled.. It was my first attempt as I want all my vectors to be .svg so they scale and look awesome!
Thank you for this article, it’s very well written and informative, but I have a question. When I save my svg from Illustrator, my code isn’t picking up the size of my artboard (the height and width don’t show in the markup) and my image is not responsive. From the article, it seems that this should be the default behavior. I’m using Adobe CC, so it should be the most up-to-date. Is there a setting I need to make in order for the svg to pick up the size of the artboard? Currently, when I open it in the browser, it renders the full height and width, not the settings I gave it. Is there a fix for that?
Great article. I have recently started using SVG’s and found this really useful. I am however wondering if any one can assist me with an issue I am tackling. I have a single SVG logo which uses DEFS and USE for various colours. I am then including the logo using the method. As the logo is used in two separate areas of the page template I wanted to use CSS to style the SVG fill colour dependent on the objects unique ID. Is this possible to do with CSS? I can do this with script or adding the SVG code directly onto the template, but ideally wanted to use CSS. Thanks!
Thanks a lot for the information, you answered all my questions in one fell swoop.
Great stuff Chris! Thanks for the detailed explanation.
just spotting an opensource SVG background pattern library on github: http://buseca.github.io/patternbolt/