
CSS Sprites vs. Data URIs: Which is faster on mobile? - shawnjan8
http://www.mobify.com/blog/css-sprites-vs-data-uris-which-is-faster-on-mobile/
======
Chris_Newton
I’m all for research and hard data, but I can’t help being a little sceptical
of these results.

We use data: URIs all over the place, typically storing icons and other small
graphics as background-image sources in CSS. Over the broadband connection I’m
using right now (roughly 5Mb/s download speeds) and with a cleared cache, our
home page seems to be downloading and rendering in about 1.5s in all of the
major browsers, and the lion’s share of that is downloading the HTML file
first and then downloading various standalone images that we haven’t yet
optimised at the end. Over a 3G mobile connection of dubious quality, in the
browsers I can readily test with, there’s a lot of extra lag up-front, but
little difference in the middle section where we download and render the
CSS/data: images. These results are both fairly consistent with what we’ve
seen throughout development and testing, across a decent range of test
scenarios over an extended period.

So while I’m not sure from these articles where the difference might lie, I
don’t see how to reconcile the results we’ve seen with the idea that switching
to data: URIs somehow slows things down by 6x or 10x as reported in the linked
article series. I wonder whether either the people doing these experiments
weren’t measuring what they thought they were measuring or perhaps they’ve hit
an awkward use cases that some/all major browsers don’t optimise well rather
than a general problem with using data: URIs. The latter is certainly
plausible, as there are cases with for example SVG where some browsers seem
absurdly slow but everything works with the kind of performance you’d expect
in others.

Meanwhile, data: URIs continue to have some concrete practical advantages for
mobile, perhaps most obviously that they tend to circumvent mobile Internet
providers “helpfully” compressing your graphics on the fly so they look
terrible on your visitor’s 300dpi smartphone/tablet display, which is a
particular problem with image sprites if their compression starts bleeding one
image into the next. For reasons like this, we’ve found that in practice our
decisions about how to send graphics on web pages are rarely dominated by
speed considerations anyway — though they surely would be if using data: URIs
really slowed down our pages by a factor of 6-10x!

------
gojomo
For completeness, it could be interesting to also test:

• separate image files: after the cost of the initial many-separate-loads
(which might be minimized by pipelining/SPDY), once reaching the cached-
condition, might having them as individual artifacts again show some wins (no
translations/trimming; shorter/simpler CSS)?

• data URIs inside CSS rather than HTML: on the off chance that leads to
better post-data-decode image caching than re-parsing the cached HTML

------
srd
The main takeaway seems to be: "This is in spite of the fact that the CSS
sprite actually requires an extra connection and incurs all the associated
connection overhead including TCP slow start!"

However, if the CSS file and sprite reside on the same server, and HTTP/1.1
with keepalives is used, chances are that the sprite will come down a
preheated TCP connection (and thus also foregoing an SSL handshake, if
fetching via https). The article doesn't actually mention how client and
server are set up, and what the base network latency between them is.

It would be nice to see the test results with and without keepalives to see
how this influences the results, as well as what the median network latency
between client and server were during these tests.

------
throwaway03cc
Data URIs use base64 which adds quite a lot more the to image size. Ofcause it
will be slower. Also, using Data URI over images will hang the users
connection longer waiting for the Css to load before being able to see the
page.

~~~
jchulce
even though base64 increases raw size by about a third, this is mitigated by
gzip or deflate encoding by the webserver. The actual transmitted size is only
about 5% bigger

~~~
ajross
I measure less than that:

    
    
        dd if=/dev/urandom bs=1024 count=64 | base64 | gzip | wc -c
        64+0 records in
        64+0 records out
        65536 bytes (66 kB) copied, 0.0127386 s, 5.1 MB/s
        67302
    

This particular run comes out to ~2.7% overhead, and in fact it's very
repeatable. The half dozen runs I did were within 20 bytes of each other.

~~~
Scaevolus
The overhead is slightly worse when it's compressed alongside normal HTML
content (the Huffman trees aren't so favorable).

    
    
        $ wget http://en.wikipedia.org/wiki/ASCII
        $ (cat ASCII;dd if=/dev/urandom bs=8000 count=1 | base64) | gzip | wc -c
        50578
        $ (cat ASCII;dd if=/dev/urandom bs=9000 count=1 | base64) | gzip | wc -c
        51621
    

Around 4% overhead. Either way, it's negligible.

------
jwilliams
I'd be curious as to the underlying why here.

I imagine that CSS parsers aren't particularly designed with any kind of
parallel operation, whereas grabbing images (& decoding them) is largely done
in parallel (up to the number of max connections). So while you're parsing the
CSS you can be getting the images, offsetting the connection cost.

In the CSS case, the device needs to get the (slightly larger) CSS, un-gzip it
(with more complex tables), Base64 decode - and then decode the image as
before. I wouldn't be surprised if this is a completely sequential activity
with the rest of the CSS parsing.

------
quink
I'd be interested in seeing these results with SVG.

There's a lot of commonality between the images, [http://g-ecx.images-
amazon.com/images/G/01/common/sprites/sp...](http://g-ecx.images-
amazon.com/images/G/01/common/sprites/sprite-dp-2._V384267953_.png)

Even with Base64 encoding, much of that commonality would remain and thus I'd
think that if you had all these sprites as SVG in a single file, as Data URIs,
gzip would do a very good job indeed on the CSS file.

In a PNG sprite I wouldn't be so sure.

------
mikeratcliffe
Inlining all of your images as data URIs in your CSS is not a good idea
because it will block the rest of the stylesheet from loading whilst images
will not.

~~~
shawnjan8
and thusly will block the document from loading, most likely delaying first
paint.

------
rblatz
I must have missed the Data URI hype, because I'm not at all shocked that CSS
spriting is faster than using Data URI. We are comparing using a binary image
format, and a base64 encoded image inlined into CSS/HTML.

What isthe basis or the source of the idea that base64 encoded images inlined
into the CSS would be faster?

------
pessimizer
I have the same question as Jochem Bökkers and Anil Namde had in the comments
- why wouldn't you use both? I'm sure there's a good answer, but I don't
understand.

------
codezero
I see the author has previous posts about what is not causing the delay, but
what are the mostly likely culprits and do all browsers suffer similarly?

------
tantalor
Might want to see whether this varies with the number of images (instead of 1)
and the size (instead of 25kb).

~~~
shawnjan8
I wouldn't imagine having two or more images would make much of a difference
until you start reaching the max # of TCP connections per host, since these
images would download in parallel. Would still be interesting to see results
for.

~~~
b1tr0t
Article author here -- I agree, it would be interesting to see results. One
reason for using more than a single image: no navigation timing API in iOS.

iOS may now lag behind Android in handsets shipped -- but it's still a
dominant player in web visits on mobile!

Unfortunately that means that for RUM tests I needed to have results that were
insensitive to differences of a few ms.

Here's a petition asking Apple to include the navigation timing API in a
future iOS release:

[http://www.change.org/petitions/apple-please-support-
navigat...](http://www.change.org/petitions/apple-please-support-navigation-
timing-api-in-safari)

~~~
yojimbo311
As someone who is grateful for your research and analysis, thank you, but
filing a bug report is going to be WAY more effective, at least for iOS.
[https://bugreport.apple.com/](https://bugreport.apple.com/) will get the ball
rolling, even if it's been filed already. The more reports they get, the more
likely they'll look at fixing the issue, especially if good use cases are
provided.

~~~
b1tr0t
Noted and filed! Thank you!

