January 24, 2016
•Last updated November 5, 2023
Should I use SVG, Icon Fonts, or Images?
Responsive web design has finally caught on across many websites around the world. No longer is it thought of as an extra feature to provide support for mobile devices.
With more people visiting websites from their handheld devices, website owners and makers need a way to make the information and content they have to share reachable with their audience no matter the device.
Since all devices vary, designers need to think in terms of scalability. Many devices today have retina support while others date back years before retina was even a thing. Offering support for many devices means having scalable assets in our arsenal. Which type of assets in use may depend on your project, but it’s worth noting the upsides and downsides to each.
Images
Images are great for supporting any relating content on a web page. What they lack is scalability. If a web design showcases an image for a specific part of the design, chances are you will have to supply multiple resolutions of that image to adhere to most devices.
Years ago images were used for all aspects of a web design. The old-school approach of slicing up a PSD file might give veteran designers a sense of nostalgia, I know it does for me. Some designers still swear by this technique. Even though it’s a little more hands-on and repetitive it still gets the job done.
CSS Image Sprites
CSS Image Sprites were born out of the need to reduce the number of HTTP
requests made on a website (Read more about requests here). Sprites helped with speed, performance, and just generally made displaying reusable images easier to reference via CSS
. Making one image out of multiple might seem counterintuitive, but generally, it’s a wiser approach for a more efficient experience.
How about an example?
Image | File Size | Dimensions |
---|---|---|
alarmclock_64px.png | 1.36KB | 60 x 64 |
bike_64px.png | 1.96KB | 112 x 64 |
camera_64px.png | 1.64KB | 84 x 64 |
Here we have three icons in png
image format. Combined, the file size of these images comes in at 4.96KB altogether. That’s not a lot by any means. We could easily load each separately and still have a fast website, but you probably won’t always just have three icons.
Combining these three images into one results in a small increase in size; from 4.96KB each to 5.30KB. That comes to just 0.34KB larger. This isn’t a big difference, but there needs to be a good reason for the increase in size...luckily there is.
The total image size of a sprite can sometimes rise (sometimes not). The tradeoff is that rather than loading multiple images and making request after request, a sprite only requires one request which takes less time to load even if the image size grows.
Combined with concatenating CSS and JavaScript, sprites provide the most optimal experience to date when using images. Keep in mind that the typical use image sprites are for icons. Many software/web applications depend on a library of icons to give the user a quick way to reference each feature and function within.
Sprites 101
Here’s an example sprite using the images from before:
To make use of this, you set the same background-image
on several CSS
classes and set the background-position
according to the icon you need. The background-position
property shuffles the image around to display the icon you are after. Here’s some example CSS:
.icons-alarm, .icons-bike, .icons-camera {
background-image: url('http://i.imgur.com/O6XvkWW.png');
background-repeat: no-repeat;
height: 64px;
}
.icons-alarm {
width: 60px;
background-position: 0 0;
}
.icons-bike {
width: 112px;
background-position: -72px 0;
}
.icons-camera {
width: 84px;
background-position: -192px 0;
}
To get these to print on the page, you just need to create some elements with the classes as denoted above. Using the dimensions of each individual image we were able to key into each separately all while loading only one image.
<div class="icons-alarm"></div>
<div class="icons-bike"></div>
<div class="icons-camera"></div>
The Verdict About Images
Images are certainly here to stay but images as icons and sprites are a little out of date for today's demands. The market seems to be transitioning to SVG (Scalable Vector Graphics) as well as web-fonts for icons especially.
Images, as I stated before, are not scalable so right away that limits your workflow. Fortunately, there are workarounds that make the use of JavaScript to load the best image depending on the user's needs.
Picturefill is a popular library created by Scott Jehl which ties into newer attributes on a picture
or img
element. The library then tells the browser different assets to load depending on the resolution of the user’s display. It’s quite easy to implement. I would say the only downside is the generation of assets at different resolutions. You’ll start to load up your server fast with assets with the @2x
and @3x
suffixes which are a necessary evil with images on the web today. If you can find a dynamic way to generate these assets then this is solution certainly for you.
Generally, images are used to support content. You won’t see many modern websites using images as buttons or icons anymore for the sake of scalability. Some websites hardly use images at all but rather vector-based graphics to make scaling a breeze. We’ll dive more into this soon.
Icon Fonts
Icon fonts came after the rise of web-based typography foundries starting creating glyph-based fonts for easier use. CSS image sprites were then the method for success when it came to displaying icons on a web page.
Why use Icon Fonts over CSS Image Sprites?
- Changing size is extremely easy via CSS.
- Changing the size doesn’t result in sub-optimal resolutions like images.
- Changing color is a breeze again with CSS
- CSS3 brings us neat properties like
box-shadow
which allows you to add some shadow to your icons if you like - There are quite a lot of icon fonts available for free which is a big perk. You can also create your own.
- Icon fonts take way less time to implement than images which need to be designed first as well.
Icon fonts 101
Adding Icon Fonts to your project has never been easier. You can make use of popular libraries like Font-Awesome, Entypo(recently switched to SVG only), and much more to extend your user interfaces.
If you’d like to combine forces of any of these icon font libraries you can do so with an amazing tool called IcoMoon. With IcoMoon, you can pick and choose whichever icons you like to make use of in your projects. Going this route is wise in the event you only need a handful of icons. Fewer icons mean fewer requests and file sizes.
For a quick example, I’ll make use of Font-Awesome and add it to a project via CSS and through a CDN linked to the font itself.
Our HTML would look simple:
<html>
<head>
<title>Icon Font Example</title>
<!-- Font Awesome CDN -->
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css" rel="stylesheet" />
</head>
<body>
<h1><i class="fa fa-globe"></i> Hello World</h1>
</body>
</html>
Here we added the link to the Font-Awesome stylesheet from a third-party CDN provider. Linking this stylesheet gives us complete access to all icons in the library. To add an icon you have to write an i
tag with the class of fa
followed by fa-<icon name>
.
Opting out of the CDN
Sometimes you just want your icon fonts to exist within your project itself. To do this, you can simply download the icon fonts and associated CSS that goes along with it. Font-Awesome comes with options for Less, Sass, and regular CSS which is wonderful.
Linking up your new icon fonts should be pretty simple. You’ll just need to verify the src
path within your CSS, Less, or Sass files so that your project is pointing to the fonts themselves. Out of the box Font-Awesome comes like this:
@font-face {
font-family: 'FontAwesome';
src: url('../fonts/fontawesome-webfont.eot?v=4.5.0');
src: url('../fonts/fontawesome-webfont.eot?#iefix&v=4.5.0') format('embedded-opentype'), url('../fonts/fontawesome-webfont.woff2?v=4.5.0') format('woff2'), url('../fonts/fontawesome-webfont.woff?v=4.5.0') format('woff'), url('../fonts/fontawesome-webfont.ttf?v=4.5.0') format('truetype'), url('../fonts/fontawesome-webfont.svg?v=4.5.0#fontawesomeregular') format('svg');
font-weight: normal;
font-style: normal;
}
Once this part is set up correctly you would just proceed like we did before by adding an icon anywhere using the i
element with a class of it's
and fa-<icon-name>
.
<i class="fa fa-thumbs-up"></i>
The Verdict About Icon Fonts
There’s a bit of drama going around the web design world in relation to icon fonts. This drama brings forth the argument of accessibility with icon fonts. Some think fonts were never meant to be glyphs but rather typographic elements no matter the language.
A big problem with icon fonts is when they don’t display correctly. Browsers won’t be able to interpret them and end up displaying nothing or empty characters that don’t support the content at all. This, of course, is the same for images as well.
Web fonts are also yet another request that the browser has to make if using a linked version of CSS (CDN) to make them display. This request takes a little time to load so commonly on the first load of a website you witness any fonts doing a sort of flickering effect because these libraries haven’t loaded yet. Unfortunately, there isn’t a great workaround for this so many designers have begin looking for alternative solutions. This alternative for many is SVG.
SVG
SVG is all the hype on the web at the moment. When it comes to scalable assets and animations SVG is the new ring leader. Out of the box, SVGs can be responsive as well as efficient when it comes time to load a new page since they are just code.
SVG stands for Scalable Vector Graphics. If you’ve ever used a vector-based editor, like Adobe Illustrator, for example, you know that the shapes and illustrations you create can scale to any size.
Why Use SVG anyway?
- Very small footprint and easily compressible
- Scalability without loss of clarity
- Easy to control from a design perspective.
At first glance, SVG code can look daunting. It’s a series of random numbers and characters that in some way tie together to display a graphic inside the browser.
Here is some example code for reference
<?xml version="1.0" encoding="utf-8"?>
<!-- Generated by IcoMoon.io -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="28" height="28" viewBox="0 0 28 28">
<path d="M26 10q0.828 0 1.414 0.586t0.586 1.414-0.586 1.414-1.414 0.586v6q0 0.812-0.594 1.406t-1.406 0.594q-6.516-5.422-12.688-5.938-0.906 0.297-1.422 1.031t-0.484 1.57 0.625 1.445q-0.313 0.516-0.359 1.023t0.094 0.906 0.523 0.859 0.75 0.781 0.961 0.789q-0.453 0.906-1.742 1.297t-2.633 0.18-2.063-0.867q-0.109-0.359-0.461-1.367t-0.5-1.477-0.359-1.391-0.234-1.578 0.055-1.539 0.344-1.727h-1.906q-1.031 0-1.766-0.734t-0.734-1.766v-3q0-1.031 0.734-1.766t1.766-0.734h7.5q6.797 0 14-6 0.812 0 1.406 0.594t0.594 1.406v6zM24 19.437v-14.906q-6.156 4.719-12 5.359v4.219q5.891 0.656 12 5.328z"></path>
</svg>
Here I’ve opened the IcoMoon app and selected an icon from the Font-Awesome library. With that icon selected I generated HTML, the SVG code, and some CSS to make it all work nicely. IcoMoon makes this really easy. The result of the SVG code is noted above.
Another approach is to draw whatever vector graphic you need a tool like Adobe Illustrator. From there you can save out the file as an SVG or generate code right within the interface. This code, unfortunately, comes with a few unnecessary components but that's a topic for another time. If you are interested in getting the most out of your SVGs check out svgo.
Working with SVGs
There are several ways to get SVGs on the page. Many you already know how to use and others that are useful in only certain situations.
Using SVG as <img>
The first technique is to use an SVG just like you would a regular img
tag in HTML.
<img src="/path/thumbs-up.svg" alt="Thumb pointing up">
Depending on the size of your graphic your SVG will display according to the same size you setup up in your vector graphics editor. You can adjust dimensions just like a regular image with the width
and height
attributes.
Using SVG as a background-image
Using the background-image
attribute you can load an SVG just like you would a JPG or PNG. To start, you need an element to target inside an HTML document.
<h1 class="logo">
<a href="/">My Company</a>
</h1>
With CSS you can target the element like this:
.logo a {
display: block;
text-indent: -9999px;
width: 120px;
height: 68px;
background: url(logo.svg);
background-size: 120px 68px;
}
The SVG then loads as a background image. One thing to note is the background-size
. We need this to match the appropriate dimensions we want the logo to display as. Since the SVG can scale you can enter any configuration you want but matching the background-size
with those dimensions constrains the SVG properly.
Fallbacks
For a safe fallback, you can make use of Modernizr which kindly adds a class called no-svg
to the element containing SVGs. You can target these classes with fallback images instead of SVGs altogether.
.logo a {
display: block;
text-indent: -9999px;
width: 120px;
height: 68px;
background: url(logo.svg);
background-size: 120px 68px;
}
.no-svg .logo a {
background-image(logo.png);
}
Downsides to the two previous approaches
Using an SVG as a background-image
or <img>
limits any advanced customizations to the SVG code itself. Since SVG is simply code, there are ways to target it with CSS and modify stylistic features. Unfortunately, using both of these approaches make that nearly impossible. Never fear though there is another way!
“Inline” SVG
Adding SVG code to a web page is as simple as copy and pasting. This technique is known as “inline” SVG and is probably the most extendable. If you happened to save an SVG from Adobe Illustrator (or any other vector graphics editor) you can open that file in a code editor to retrieve its contents. Copying that code and pasting into your HTML document instantly displays it as a graphic in your browser (IE8+). Before doing this I recommend using Peter Collingridge’s online tool or svgo as mentioned prior.
After getting the “inline” SVG to display you can target it like you would any other element on an HTML page by adding a class, ID, or just targeting by name with CSS.
<!-- at its minimal form -->
<svg>
<path id="myIcon" d="..."></path>
</svg>
with CSS, we can go further than before and actually apply fill colors, transitions, and even CSS3 animations.
#myIcon {
fill: blue;
}
#myIcon:hover {
fill: red;
}
You can also go another step further and apply filters SVG extends to us to add effects. I won’t get int the details of these much but you can read more about them by visiting the links below:
SVG as <object>
If you don’t dig the “inline” approach you can also use the object
element to display an SVG on the page. Doing so looks a little like this:
<object type="image/svg+xml" data="logo.svg" class="logo">
My Company
</object>
The <object>
approach surprisingly has the most optimal support across browsers when it comes to SVG integration. Unfortunately styling an <object>
element with an SVG within can be a chore. You’ll either need to embed your styles within the element itself or link to an external CSS file.
Embedding CSS looks like this:
<object type="image/svg+xml" data="logo.svg" class="logo">
<style>
/* Your Styles Go Here */
</style>
My Company
</object>
If you prefer to link an external CSS file you can do so with a specific XML
link that goes inside the
SVG file itself. It looks like this:
<?xml-stylesheet type="text/css" href="mysvg.css" ?>
SVG Sprites
Just like image and CSS based sprites SVGs can also be contained in a sprite. You can tie different SVGs together by either handwriting your code or using some cool tools like iconizr PHP developers or grunticon for Grunt users. I typically use Gulp so you can make use of a task like gulp-svg-sprite if you’re into Gulp as well.
Building an SVG manually would look similar to this:
<svg>
<defs>
<symbol id="icon-1">
<!-- insert all paths and shapes for first svg here -->
</symbol>
<symbol id="icon-2">
<!-- insert all paths and shapes for second svg here -->
<symbol>
<!-- keep going for however many you need -->
</defs>
</svg>
Ok, now on to displaying this in our project:
<svg class="icon icon-1">
<use xlink:href="#icon-1"></use>
</svg>
<svg class="icon icon-2">
<use xlink:href="#icon-2"></use>
</svg>
As you can probably guess, If you want to target a specific SVG in the sprite you can do so with CSS:
.icon {
display: inline-block;
width: 1em;
height: 1em;
fill: #333333;
}
.icon-1 {
width: 1em;
fill: green;
}
.icon-2 {
width: 1em;
fill: magenta;
}
SVG sprites are extremely useful if you have a lot of icons to make use of in your project. What’s especially great is the customizable properties you can apply with CSS alone to make each icon unique. Using a task-runner takes some time to setup but, in general, improves the ease of use with sprites. Be sure to check one out if you make any use of task runners in your day-to-day workflow.
The Verdict About SVG
SVGs are becoming the most common solution for displaying graphics, icons, and more with full responsive support. SVGs appear clear no matter the resolution. The code for “inline” SVG can get overwhelming as it’s hard to read and takes up a lot of space but you can work around this by including partials or templates inside your projects. A lot of modern frameworks and tools make use of this approach anyway so it’s two-fold.
As always its best to design with fallbacks in mind and SVGs make this fairly easy with the help of Modernizr. If you haven’t tried SVGs yet you totally should. You’ll see right away why there’s a lot of buzz about them.
The Final Verdict
In my own work, I make use of images, icon fonts, and SVGs. I don’t think you need to restrict yourself into using one or the other in your projects just because some industry buff told you to. In the end, you should use what the project requires.
If you’re cool with producing multiple size images for various screen sizes, then, by all means, go for it with bitmap images. Or, if you want speed and a quick and easy way to get icons on the page, icon fonts are for you. If you want to pick up where icon fonts left off and go nuts then SVG is likely more your cup of tea.
If I had to pick my favorite it is without a doubt SVG. I only began using SVG about a year or two ago. I struggled to see the value in the complicated code you have to work with. Until I finally harnessed the power of that code, I was hooked.
Useful Links
Vector Graphic Editors
Feature image used by pretty much everyone with an internet connection, don't sue me please!
Categories
Products and courses
-
Hello Hotwire
A course on Hotwire + Ruby on Rails.
-
Hello Rails
A course for newcomers to Ruby on Rails.
-
Rails UI
UI templates and components for Rails.