We're going to see some HTML and CSS/SCSS snippets to get an idea of how to work with icon fonts and SVGs, but we're not going to go through the creation of such assets since that process is out of the scope of this section.
When people ask what the difference between vectors and bitmaps/raster images is, the answers I often hear are usually around the idea, "If you enlarge it, it won't lose its quality. No worries for mobile devices." Although true, it doesn't fully answer the question. So here are the differences:
A vector image is a file made out of mathematical equations. The results of these equations are represented by a graphic (lines, shapes, colors). If the size of the image changes in any way, the values of those equations are recalculated and the resulting graphic is painted again.
A bitmap or raster image is a file made out of pixels. These pixels have a specific/defined width, height, and color. If an image is enlarged, the pixels are stretched and that's why the image looks blurry or pixelated.
With those definitions out of the way, let's talk about some of the vector formats used for RWD. Vector formats include:
Let's see how to rapidly implement icon fonts and SVGs; web fonts will be addressed in the next chapter.
Icon fonts are basically a font file but instead of having letters as glyphs it has, well, icons. Some people love icon fonts (I do), and some aren't really too fond of them, especially since SVG has gained so much popularity.
Let's see the pros and cons of icon fonts.
@font-face properties are set once, calling an icon font is a matter of adding a class to the HTML and calling a specific code called the Unicode Point in the CSS.Here are a few recommendations I can give you when using icon fonts:
title="" attribute in the element you're using the icon font on. If the font file fails to load, at least the text in the title tag can be seen.Let's implement an icon font then.
The fastest way to get icon font files is by using a third party web app like IcoMoon.io or Fontello.com. You can also get a copy of Font Awesome.
Once you are able to unzip the provided files, the only file you're going to need is the .woff file. The reason you only need this file is because browser support for .woff files goes all the way back to IE9. Unless you want/need to support legacy browsers (desktop and mobile), you can then use .eot, .ttf, and .svg files.
Let's name our icon font file icon-font.woff. Create a /fonts folder and save the icon-font.woff file in it. This is what we are going to try to accomplish: a soft-blue link with an icon on the left, no underline, and 40px Arial/Helvetica font:

The great thing about using a pseudo-element is that our source markup always stays clean. In this case, we're going to use the :before pseudo-element, but this technique also works with an :after pseudo-element.
Let's take a look at the build.
This is the HTML snippet:
<a href="#" class="icon icon-headphones" title="Headphones">Headphones</a>
Here's the SCSS. The first thing we need is a mixin to handle any custom web fonts. In this case, it is an icon font:
//Web font mixin
@mixin fontFace($font-family, $file-path) {
@font-face {
font: {
family: $font-family;
weight: normal;
style: normal;
}
src: url('#{$file-path}.woff') format('woff');
}
}Then, we create a rule using attribute selectors to handle the basic styling properties of the icon font:
//Icon Font specific rule
[class^="icon-"], [class*=" icon-"] {
font: {
family: icon-font, Arial, "Helvetica Neue", Helvetica, sans-serif;
weight: normal;
style: normal;
variant: normal;
}
text-transform: none;
line-height: 1;
speak: none;
// Improve Font Rendering
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}Then, we need to call the fontFace mixin in order to bring the font into the compiled CSS file:
@include fontFace(icon-font, '/fonts/icon-font');
The great thing about the fontFace mixin is that all we need to do is declare the font name and then the file path. There is no need to declare the file extension; that's taken care of by the mixin.
This will compile to:
@font-face {
font-family: icon-font;
font-weight: normal;
font-style: normal;
src: url("/fonts/icon-font") format("woff");
}Here is the rule that makes the magic happen using :before:
.icon-headphones:before {
content: "\e601";
margin-right: 10px;
}For basic styling enhancement, we create these other two rules. However, they are not required. The code is as follows:
.icon { font-size: 40px; }
a {
padding: 5px;
text-decoration: none;
color: #2963BD;
transition: .3s;
&:hover { color: lighten(#2963BD,20); }
&:focus { outline: 2px solid orange; }
}The final compiled CSS looks like this:
[class^="icon-"], [class*=" icon-"] {
font-family: icon-font, Arial, "Helvetica Neue", Helvetica, sans-serif;
font-weight: normal;
font-style: normal;
font-variant: normal;
text-transform: none;
line-height: 1;
speak: none;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
@font-face {
font-family: icon-font;
font-weight: normal;
font-style: normal;
src: url("https://s3-us-west-2.amazonaws.com/s.cdpn.io/9988/icon-font.woff") format("woff");
}
.icon-headphones:before {
content: "\e601";
margin-right: 10px;
}
.icon {
font-size: 40px;
}
a {
padding: 5px;
text-decoration: none;
color: #2963BD;
-webkit-transition: .3s;
transition: .3s;
}
a:hover {
color: #6d9adf;
}
a:focus {
outline: 2px solid orange;
}Here's a demo I created for this in CodePen: http://codepen.io/ricardozea/pen/e62b201350efe7f59f91c934f9fc30fa
Here's another demo I created in CodePen with the icon fonts a bit more advanced: http://codepen.io/ricardozea/pen/5a16adffb6565312506c47ca3df69358
To be honest, using an extra HTML element goes a little against the principle of separating content from styling, since adding an extra HTML element for styling reasons is not something some developers recommend. However, we can also argue that the icon itself really is content, not styling. Either way, here's the run down.
Here's the HTML snippet:
<a href="#" title="Headphones"><i class="icon-headphones" aria-hidden="true"></i>Headphones</a>
The SCSS code from the previous example is practically the same, except we move the font-size: 10px; declaration from the .icon class to the a rule and then delete the .icon class altogether. You will also see some extra properties but only for styling reasons.
The final SCSS looks like this:
//Web font mixin
@mixin fontFace($font-family, $file-path) {
@font-face {
font: {
family: $font-family;
weight: normal;
style: normal;
}
src: url('#{$file-path}.woff') format('woff');
}
}
//Icon Font specific rule
[class^="icon-"], [class*=" icon-"] {
font: {
family: icon-font, Arial, "Helvetica Neue", Helvetica, sans-serif;
weight: normal;
style: normal;
variant: normal;
}
text-transform: none;
line-height: 1;
speak: none;
// Improve Font Rendering
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
@include iconFont(icon-font, '/fonts/icon-font');
.icon-headphones:before {
content: "\e601";
margin-right: 10px;
}
a {
font-size: 40px;
//Styling stuff
padding: 5px;
text-decoration: none;
color: #2963BD;
transition: .3s;
&:hover { color: lighten(#2963BD,20); }
&:focus { outline: 2px solid orange; }
}The compiled CSS looks like this:
[class^="icon-"], [class*=" icon-"] {
font-family: icon-font, Arial, "Helvetica Neue", Helvetica, sans-serif;
font-weight: normal;
font-style: normal;
font-variant: normal;
text-transform: none;
line-height: 1;
speak: none;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
@font-face {
font-family: icon-font;
font-weight: normal;
font-style: normal;
src: url("https://s3-us-west-2.amazonaws.com/s.cdpn.io/9988/icon-font.woff") format("woff");
}
.icon-headphones:before {
content: "\e601";
margin-right: 10px;
}
a {
font-size: 40px;
padding: 5px;
text-decoration: none;
color: #2963BD;
-webkit-transition: .3s;
transition: .3s;
}
a:hover {
color: #6d9adf;
}
a:focus {
outline: 2px solid orange;
}Here's a demo I created for this in CodePen: http://codepen.io/ricardozea/pen/8ca49cb06aeb070f4643f0a8e064126c.
SVG graphics have gained incredible popularity very quickly. Browser support is 100 percent, even Opera Mini supports SVG images. Let's discuss some pros and cons of SVG images:
<svg> tag.An SVG file is basically an XML-formatted file. This is what the markup of the headphones graphic looks like:
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<path id="left-ear-pad" d="M9 18h-2v14h2c0.55 0 1-0.45 1-1v-12c0-0.55-0.45-1-1-1z"/>
<path id="right-ear-pad" d="M23 18c-0.55 0-1 0.45-1 1v12c0 0.6 0.5 1 1 1h2v-14h-2z"/>
<path id="headband" d="M32 16c0-8.837-7.163-16-16-16s-16 7.163-16 16c0 1.9 0.3 3.8 1 5.464-0.609 1.038-0.958 2.246-0.958 3.5 0 3.5 2.6 6.4 6 6.929v-13.857c-0.997 0.143-1.927 0.495-2.742 1.012-0.168-0.835-0.258-1.699-0.258-2.584 0-7.18 5.82-13 13-13s13 5.8 13 13c0 0.885-0.088 1.749-0.257 2.584-0.816-0.517-1.745-0.87-2.743-1.013v13.858c3.392-0.485 6-3.402 6-6.929 0-1.29-0.349-2.498-0.958-3.536 0.62-1.705 0.958-3.545 0.958-5.465z"/>
</svg>There are many ways to use SVG images: inline via the <img>, <object>, <use>, or <svg> tags; as background images with CSS; using Modernizr in conditional classes to address fallbacks; or with jQuery or plain JavaScript, using third-party services such as grumpicon.com, you name it.
To keep things simple, we're going to focus on two methods:
<svg> tag.<img> tag.Inlining SVGs is the go-to method of many web designers and developers. The fact that we can control individual parts of the SVG with CSS and JavaScript makes it very appealing for animations.
One of the drawbacks of inlining SVG markup is that the image is not cacheable. In other words, every time the image appears, the browser has to read the XML of the SVG. If you have too many SVGs on your page, these can potentially be detrimental to the page speed and eventually the user experience. So be careful of the objective of the page and the types of visitors using your website/app.
Here's an HTML snippet of the SVG of the headphones inlined in a link tag:
<a href="#">
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<path id="left-ear-pad" d="M9 18h-2v14h2c0.55 0 1-0.45 1-1v-12c0-0.55-0.45-1-1-1z" />
<path id="right-ear-pad" d="M23 18c-0.55 0-1 0.45-1 1v12c0 0.6 0.5 1 1 1h2v-14h-2z" />
<path id="headband" d="M32 16c0-8.837-7.163-16-16-16s-16 7.163-16 16c0 1.9 0.3 3.8 1 5.464-0.609 1.038-0.958 2.246-0.958 3.5 0 3.5 2.6 6.4 6 6.929v-13.857c-0.997 0.143-1.927 0.495-2.742 1.012-0.168-0.835-0.258-1.699-0.258-2.584 0-7.18 5.82-13 13-13s13 5.8 13 13c0 0.885-0.088 1.749-0.257 2.584-0.816-0.517-1.745-0.87-2.743-1.013v13.858c3.392-0.485 6-3.402 6-6.929 0-1.29-0.349-2.498-0.958-3.536 0.62-1.705 0.958-3.545 0.958-5.465z"/>
</svg>Headphones
</a>To control its size, distance from the text, and appearance, we add the following CSS:
svg {
width: 40px;
height: 40px;
margin-right: 10px;
fill: #2963BD;
}
a {
font-size: 40px;
text-decoration: none;
color:#2963BD;
}However, this markup has a problem. It doesn't provide a fallback for legacy browsers, specifically IE8 and below. Let's try to fix this.
There are two ways to provide fallback images to legacy browsers for inline SVGs.
Create a <foreignObject> element inside the <svg> tag and include an <img> tag that calls the fallback image:
<a href="#">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="32" height="32" viewBox="0 0 32 32">
<path d="M9 18h-2v14h2c0.55 0 1-0.45 1-1v-12c0-0.55-0.45-1-1-1z"/>
<path d="M23 18c-0.55 0-1 0.45-1 1v12c0 0.6 0.5 1 1 1h2v-14h-2z"/>
<path d="M32 16c0-8.837-7.163-16-16-16s-16 7.163-16 16c0 1.9 0.3 3.8 1 5.464-0.609 1.038-0.958 2.246-0.958 3.5 0 3.5 2.6 6.4 6 6.929v-13.857c-0.997 0.143-1.927 0.495-2.742 1.012-0.168-0.835-0.258-1.699-0.258-2.584 0-7.18 5.82-13 13-13s13 5.8 13 13c0 0.885-0.088 1.749-0.257 2.584-0.816-0.517-1.745-0.87-2.743-1.013v13.858c3.392-0.485 6-3.402 6-6.929 0-1.29-0.349-2.498-0.958-3.536 0.62-1.705 0.958-3.545 0.958-5.465z"/>
<foreignObject>
<img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/9988/headphones.png" alt="Headphones">
</foreignObject>
</svg>Headphones
</a>As we all know, there's isn't an <image> tag… or is there? In the SVG world, there is! This solution is very similar to the first method. The two differences are that we do not use a <foreignObject> element and we use an <image> tag. This is all inside the <svg> tag:
<a href="#">
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<path id="left-ear-pad" d="M9 18h-2v14h2c0.55 0 1-0.45 1-1v-12c0-0.55-0.45-1-1-1z" />
<path id="right-ear-pad" d="M23 18c-0.55 0-1 0.45-1 1v12c0 0.6 0.5 1 1 1h2v-14h-2z" />
<path id="headband" d="M32 16c0-8.837-7.163-16-16-16s-16 7.163-16 16c0 1.9 0.3 3.8 1 5.464-0.609 1.038-0.958 2.246-0.958 3.5 0 3.5 2.6 6.4 6 6.929v-13.857c-0.997 0.143-1.927 0.495-2.742 1.012-0.168-0.835-0.258-1.699-0.258-2.584 0-7.18 5.82-13 13-13s13 5.8 13 13c0 0.885-0.088 1.749-0.257 2.584-0.816-0.517-1.745-0.87-2.743-1.013v13.858c3.392-0.485 6-3.402 6-6.929 0-1.29-0.349-2.498-0.958-3.536 0.62-1.705 0.958-3.545 0.958-5.465z"/>
<image src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/9988/headphones.png" xlink:href="" alt="Headphones">
</svg>Headphones
</a>Now, the reason this works is because we are combining a feature of SVGs and HTML into one element.
The SVG feature is that the <image> tag is a valid element within the SVG world. Now, as weird it sounds, all browsers see the <image> tag as an out-of-standards tag that resembles the <img> tag from HTML.
The HTML feature is that normally we use the src attribute to point to the asset's location. In the SVG world, assets are called with the xlink:href attribute. If we add a src attribute pointing to the asset and leave the xlink:href attribute empty, then legacy browsers will see the fallback image while modern ones won't because the xlink:href attribute is empty.
I recommend sticking with the second method; it's just more succinct and less hassle. Just remember that instead of <img>, we use <image>. Also, for the purpose of the book, I left the xlink:href attribute in the markup but this is optional. If it's empty, you can remove it altogether if you want.
None of these methods I just mentioned cause double download on browsers that support SVG. That's a win-win situation if you ask me.
SVG is a type of image file, so calling it within an <img> is perfectly valid:
<img src="images/headphones.svg" alt="Headphones">
We know that SVG has flawless support in modern browsers, but the prior image isn't displayed in legacy browsers (IE8 and below).
Remember the previous explanation about the xlink:href and src attributes in SVG and HTML? Well, we're going to do pretty much exactly the same we did there. However, instead of inlining the SVG markup, we're just going to link to an SVG file while providing a fallback image for old browsers.
This clever trick was created by Alexey Ten. Here's the markup:
<a href="#">
<svg width="39" height="39">
<image xlink:href="https://s3-us-west-2.amazonaws.com/s.cdpn.io/9988/headphones.svg" src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/9988/headphones.png" width="39" height="39">
</svg>Headphones
</a>There are issues here as well. Alexey's technique is not the offender, it is the browsers—specifically IE9, 10 and 11 as well as iOS 3 and 4. They download both the SVG and the fallback image.
If this double download is acceptable for you and you understand the consequences, go for it. Nonetheless, keep a mental note of where you can improve things like this for your next project.
Here's a demo I created for this in CodePen:
http://codepen.io/ricardozea/pen/594e718f36976f8e77d4f9cf1640e29a
We can't talk about SVGs without referencing three of the most noticeable names in the web design and development industry today: Amelia Bellamy-Royds, Sara Soueidan, and Chris Coyer. Amelia and Chris created one of the most complete guides about how to use SVG with fallbacks that I've read, A Complete Guide to SVG Fallbacks (https://css-tricks.com/a-complete-guide-to-svg-fallbacks/).
Sara Soueidan's blog is a must-read if you want to learn everything about SVG: http://sarasoueidan.com/articles/.