In the last years, sites are gradually become richer in functionality while demanding more network and device resources. Over the years, the experience shows that faster site engage and retain users better than slower one. As Google announced that site speed is used as a factor in their web search ranking algorithm, Site speed become even more important and can be the difference between successful site and poorly performing one.

One way to make the site faster is consolidate HTTP requests. As the number of HTTP requests from the browser increases, the overhead and load time of the site increases. Thus, when we combine several HTTP requests when possible (For example, consolidate several CSS files to one file), we can dramatically decrease the load time of our web pages.

Let’s see how Data URLs can improve the site speed.

What are Data URLs

Data URLs are special type URLs which allows to embed small files inline in documents(HTML or CSS files). Data URLs are prefixed with the data: scheme and have up to 3 parts.

Data URL structure
data:[<mediatype>][;base64],<data>
PartDescription
mediatypethe mediatype is a MIME type string. For example image/png for a image file in png format, image/jpeg for image in jpeg format, image/svg for image in svg format. If emitted text/plain;charset=US-ASCII will be used
base64Whether the encoding of the following data part is base64 and not text. Using this encoding we can embed binary formats such as images in a text based document. If this part is emitted, data is plain text which should use the appropriate entities or escapes based on the enclosing document
dataThe data

Let’s see some examples:

Sample 1 – text/plain

Data URLs - text/plain example
<div><a href="data:,I am text file" download="a1.txt">Download text file 1</a> </div>
<div><a href="data:text/plain,I am text file" download="a2.txt">Download text file 2</a> </div>

The above data URLs has equal semantics – when we click in the above links, the browser will download a text file with the contents I am text file.

Sample 2 – text/csv

We can set text mime type. In the following example we will embed CSV file.

Data URLs - text/csv example
<div><a href="data:text/csv,col1,col2%0A1,2%0A3,4" download="a1.csv">Download CSV file</a></div>

When we click in the above link, the browser will download CSV file. Please, note how we use the URL encode to decode the newline character with %0A

Sample 3 – text/html

let’s see how can we embed HTML in iframe

Data URLs - text/html example
<iframe style='width:100%; height: 100px;background:#dddddd' src='data:text/html,<!DOCTYPE html><html><head></head><body><h1>Hello</h1><p>I am HTML</p></body></html>'></iframe>

Sample 4 – text/xml

let’s see how can we embed xml.

Data URLs – text/xml example
<div><a href='data:text/xml,<?xml version="1.0"?><note>I am an XML</note>' download='a1.xml'>Download xml</a></div>

Sample 5 – image/png

Not all mediatypes are text. lets see how we can embed binary image files:

Data URL in base64 encoding
<img src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAIAAAAC64paAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOwQAADsEBuJFr7QAAABl0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC4yMfEgaZUAAAAfSURBVDhPY/j+v49sNKqZRDSqmUQ0qplENPI0/+8DAOnW7m6FxOUUAAAAAElFTkSuQmCC' />

Note that the base64 is used and the data is encoded in base64.

CSS and data URLs

The data URLs can also be used in CSS files. Using data URLs instead of external links to the image files decreases the number of HTTP requests and may improve the page speed.

Suppose we have the following CSS file:

Data URL in CSS sample #1
header {
  background : url('../img/header-bg.png')
}

Let’s replace it with data URL. Since image format is png, the image mediatype is image/png. As png is binary format, we will use base64 encoding. So here how the new CSS file should be:

Data URL in CSS sample #2
header {
  background : url('data:image/png;base64,<binary data of the header-bg.png>')
}

Finding the binary data via uuencode

If you have access to linux machine, you can find the binary data via uuencode command

Encode file in base64 encoding with uuencode
# uuencode -m header-bg.png out
begin-base64 644 out
iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAIAAAAC64paAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOwQAADsEBuJFr7QAAABl0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC4yMfEgaZUAAAAfSURBVDhPY/j+v49sNKqZRDSqmUQ0qplENPI0/+8DAOnW7m6FxOUUAAAAAElFTkSuQmCC
====

The binary data is located in the second line until ==== delimiter.

Finding the binary data via PHP

Encode file in base64 encoding with PHP
# php -r "echo base64_encode( file_get_contents('header-bg.png')) .\"\n\";"
iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAIAAAAC64paAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOwQAADsEBuJFr7QAAABl0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC4yMfEgaZUAAAAfSURBVDhPY/j+v49sNKqZRDSqmUQ0qplENPI0/+8DAOnW7m6FxOUUAAAAAElFTkSuQmCC

SASS and data URLs

While the above methods works , they are error-prone and time consumining. You need to manually update the CSS file when the images are changing.

If you use SASS you can use the following sass script with inline_image function extension. create a bin\sass.rb

binsass.rb - scss with inline-image extention function
#!/usr/bin/env ruby
# The command line Sass parser.
require 'sass'
require 'sass/exec'
require 'mime/types'
require 'base64'
module Sass::Script::Functions
  def inline_image(path)
    path = File.join( File.dirname(environment.options[:filename]),path.value )
    data = File.open(path, 'rb') { |io| io.read }
    data64 = Base64.encode64(data).gsub("\n", '');
    mime   = MIME::Types.type_for(path)[0].content_type.force_encoding 'UTF-8'
    data_uri = "data:#{mime};base64,#{data64}"
    Sass::Script::String.new "url('#{data_uri}')"
  end
end
opts = Sass::Exec::SassScss.new(ARGV, :sass)
opts.parse!

Now Suppose you files in the css directory

css/main.scss
header {
  background: inline-image("../img/header-bg.png");
}

Now, to generate the CSS file, use the following command:

Data URI in CSS sample
# ruby bin/sass.rb --update css

The main.css should be generated in css directory:

Data URI in CSS sample
header {
  background : url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAIAAAAC64paAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOwQAADsEBuJFr7QAAABl0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC4yMfEgaZUAAAAfSURBVDhPY/j+v49sNKqZRDSqmUQ0qplENPI0/+8DAOnW7m6FxOUUAAAAAElFTkSuQmCC');
}

Summery

Data URLs can reduce the number of HTTP requests from the server, which may make the site faster and improve the page load time. We show what are data URLs, use cases and how can we generate them (manually and automatically via sass).