People working on laptops

Optimize Image Assets for Web: SVG

by Nikita Verkhoshintcev

I noticed that even in 2017 many websites on the internet still haven’t optimized their static assets. For instance, people keep using individual PNGs for each icon. It requires a bigger amount of requests to a server, and the web browser needs to download bigger files. Eventually, it results in slower loading speed of the website.

In this post, I would like to show you which technique I’m using in most of my projects to build fast and responsive websites. By applying it you will be able to reduce the number of unnecessary requests and decrease the amount of data needed for page rendering.

Alternatives

First of all, I would like to mention what alternatives we have for asset optimization, specifically, repetitive items, such as social media icons.

1. PNG sprites

This is a technique to combine all of your mostly used assets into one PNG file. Then you can use this image as a background and display a specific portion of it. It’s a widely used approach, for instance, even Google uses this one.

Here is an example from their Calendar application.

How they use it to display a logo by manipulating background-position property in the CSS:

.gb_4b .gb_6b {
    background-position: 0 -762px;
    height: 33px;
    width: 92px;
}
.gb_6b {
    background-image: url(‘//ssl.gstatic.com/gb/images/v1\_76783e20.png');
    background-size: 92px 2541px;
}

This method helps you to limit the number of requests to one. There are a bunch of sprite generators on the internet, e.g. https://draeton.github.io/stitches/.

You can even generate them via Gulp task runner (e.g. by using gulp-sprite-generator package).

There are some drawbacks:

  1. Images aren’t scalable;
  2. You need an image for every icon, even if the only difference is color or opacity. By using fonts or SVG, you can easily change them via CSS properties.
  3. It’s relatively harder to maintain. For instance, you need to use absolute values like pixels instead of better options, such as ems. You need to generate a new sprite each time you want to add an item.

2. Fonts

The idea of this approach is to generate font files from SVGs and images files as a normal text. You can do this by simply applying setting a font family and adding a CSS pseudo element.

I, personally, use this method when doing Salesforce development, because VisualForce pages don’t allow me to use SVG tags, required for my favourite method.

There are a lot of websites and frameworks who uses this approach, for instance Bootstrap is using Font Awesome library.

It’s easy to set up and there are a lot of already built options for you.

If you want to create your own icon set I can suggest using IcoMoon application. Interface is very simple, you just import all your icons, click generate font and download it. It will contain all font files and ready to use CSS, which looks like this:

@font-face {
  font-family: 'icomoon';
  src:  url('fonts/icomoon.eot?xaz8xu');
  src:  url('fonts/icomoon.eot?xaz8xu#iefix') format('embedded-opentype'),
    url('fonts/icomoon.ttf?xaz8xu') format('truetype'),
    url('fonts/icomoon.woff?xaz8xu') format('woff'),
    url('fonts/icomoon.svg?xaz8xu#icomoon') format('svg');
  font-weight: normal;
  font-style: normal;
}
   
[class^="icon-"], [class*=" icon-"] {
  /* use !important to prevent issues with browser extensions that change fonts */
  font-family: 'icomoon' !important;
  speak: none;
  font-style: normal;
  font-weight: normal;
  font-variant: normal;
  text-transform: none;
  line-height: 1;
 
  /* Better Font Rendering =========== */
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
 
.icon-mail:before {
  content: "\\e900";
}

Good things are that fonts are scalable, it’s easy to change the size and color.But it still has a lot of disadvantages comparing to an inline SVG method.

  1. Browser considers font icons as a text. It might affect rendering and they might be blurry.
  2. It might be hard to position an element correctly.
  3. The font load might fail due to some reason, or user may disable custom fonts as well.
  4. Accessibility problems.
  5. You need to generate new font every time you want to add an icon. Also, you might have many unused icons.

3. Inline SVG

Using inline SVGs are my favorite method to dealing with the icons. The idea is very simple. You need to create symbol elements within the SVG tag, representing icons and then referring to them in the document.First of all, I would start with the advantages, why I chose this approach, and then show you how to use it.

  1. There are no requests to a server.
  2. Native support by a browser.
  3. Scales perfectly.
  4. You can specify title and description for a better accessibility.
  5. Easy to use and maintain.
  6. Take advantage of SVG animations.

Example

Let’s take a look at an example. First of all, create a hidden SVG container for our symbols straight after the opening tag.

<svg xmlns="http://www.w3.org/2000/svg" style="display:none" role="img"></svg>

Now we need to create a new symbol element inside. Consider having the following Facebook icon in the SVG format.

Let’s create a symbol with the id “facebook” and viewBox attribute. We would need id to reference images to this symbol.

<symbol id="facebook" viewBox=""></symbol>

Open the icon in any text editor. You will see something similar to this one:

<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
    <path fill="#3b3b3b" d="M29 0h-26c-1.65 0-3 1.35-3 3v26c0 1.65 1.35 3 3 3h13v-14h-4v-4h4v-2c0-3.306 2.694-6 6-6h4v4h-4c-1.1 0-2 0.9-2 2v2h6l-1 4h-5v14h9c1.65 0 3-1.35 3-3v-26c0-1.65-1.35-3-3-3z"></path>
</svg>

Copy the viewBox value from the SVG to our symbol. It defines the size of the image canvas. Then copy everything from the inside of the to the .Then we could specify both the title and the description for accessibility.Here is the final markup of our SVG sprite:

<svg xmlns="http://www.w3.org/2000/svg" style="display:none" role="img">
    <symbol  id="facebook" viewBox="0 0 32 32">
        <title>Facebook</title>
        <desc>Black facebook social media icon</desc>
        <path fill="#3b3b3b" d="M29 0h-26c-1.65 0-3 1.35-3 3v26c0 1.65 1.35 3 3 3h13v-14h-4v-4h4v-2c0-3.306 2.694-6 6-6h4v4h-4c-1.1 0-2 0.9-2 2v2h6l-1 4h-5v14h9c1.65 0 3-1.35 3-3v-26c0-1.65-1.35-3-3-3z"></path>
    </symbol>
</svg>

At this point, we have everything ready to start using our icon. It’s very easy, you can access it by its Id via element like so:

<svg>
  <use xlink:href="#facebook" />
</svg>

You can also generate inline SVG via the IcoMoon web application.Now you can create multiple symbols and use them on your website to increase its performance!

Nikita Verkhoshintcev photo

Nikita Verkhoshintcev

Salesforce Consultant

Senior Salesforce and full-stack web developer. I design and build modern Salesforce, React, and Angular applications for enterprises. Usually, companies hire me when complex implementation, custom development and UI is required.

Let's work together!

Contact us today and take your digital end-user experience to the next level.

Contact us