DEV Community

Cover image for Increasing my PageSpeed score from 92% to 100% using CSS only
Omar Sinan
Omar Sinan

Posted on

Increasing my PageSpeed score from 92% to 100% using CSS only

This was originally posted on my personal blog at https://omarsinan.com/blog/increasing-my-pagespeed-score-from-92-to-100-using-css-only

In this blog post I will show you how I was able to improve my personal website’s PageSpeed score from 92% to 100% and decrease the loading time by 0.3 seconds on average using CSS only!

PageSpeed score

Let’s talk about CSS sprites

The trick here is using CSS sprites, I’ve spent the past couple of days looking through different portfolios of people I follow on Twitter and there was a pattern. A lot of people didn’t make use of CSS sprites.

So what are CSS sprites? Like any other sprite sheet, CSS sprites are a collection of icons/images in a single image file. Let’s say you have a social media icons bar on your website. Instead of having every icon as a single image, you could create an image with all the icons separated by 1 pixel as shown below:

Preview of icons

How are CSS sprites beneficial?

Well, instead of making 6 requests for your 6 social media icons, you’ll make 1 request for the sprite sheet and then by using CSS, you could chop the image up appropriately so that you can create 6 separate images out of one.

I was also able to decrease my page loading speed by 0.3 seconds on average and improve my Google PageSpeed score by 8% (from 92% to 100%)

Compatible with all major browsers

The CSS property used here is the background-position property which is supported by all major browsers as shown below:

Compatibility across browsers

How can you use them?

They’re very simple to use, once you create an image with all icons separated by 1 pixel (you could use any photo editing software or applications like Figma and sketch), you create a div whose width is the width of 1 icon, let’s say it’s 26px and whose height is the height of 1 icon let’s say it’s 30px, and then set the background of the div to be the URL of the image at x y. Where x is the background-position-x property and y is the background-position-y property. Below is an example of how I styled my divs on my personal website (https://omarsinan.com/)

<div class="githubSocial"></div>
<div class="linkedinSocial"></div>
<div class="devSocial"></div>
<div class="twitterSocial"></div>
<div class="rssSocial"></div>
<div class="resumeSocial"></div>
Enter fullscreen mode Exit fullscreen mode
div {
    display: inline-block;
    height: 30px;
}

.github-social {
    width: 26.25px;
    background: url($url) 0 0;
}

.linkedin-social {
    width: 26.25px;
    background: url($url) -27.25px 0;
}

.dev-social {
    width: 26.25px;
    background: url($url) -54.5px 0;
}

.twitter-social {
    width: 26.25px;
    background: url($url) -81.75px 0;
}

.rss-social {
    width: 26.25px;
    background: url($url) -109px 0;
}

.resume-social {
    width: 22.5px;
    background: url($url) -136.25px 0;
}
Enter fullscreen mode Exit fullscreen mode

As you can see it is very simple. I am using the background property in CSS while using the shorthand form of combining it with the background-position property in a single line. It could be split into 2 lines and would have the same effect.

It also still looks the same so there are no disadvantages to adopting this method:

Preview of icons on website

What’s next?

Check out https://web.dev/fast/ where there are more tips on how you could make your website load faster. Also, try to serve your images in .webp format and if the quality of the image isn’t an issue, reduce the quality of the image to maybe 80%.

Using tools like Cloudinary makes this soooo much easier by using the f_auto parameter which selects the optimal format and the q_auto parameter which selects the optimal quality.

By following many of the tips highlighted in https://web.dev, i was able to reduce my website’s loading time from the initial 2.1 seconds to 1.3 seconds. This is a significant improvement and it could be even more significant on your website!

If you decide to use CSS sprites, please share your results and thoughts with me I’d love to see the changes it has made to your website.

You can also connect with me on Twitter @oohsinan

Top comments (19)

Collapse
 
pavelloz profile image
Paweł Kowalski • Edited

Your icons could be svg, probably A LOT smaller than whatever sprite you got there. ;)

And it would be much crisper, than this blurry png/webp ;)

PS. For some reason on my firefox its not working at all on your site, but i have aggressive adblock so that might be my fault.

Collapse
 
aleksandrhovhannisyan profile image
Aleksandr Hovhannisyan

This. SVGs are pretty much the standard these days for icons. Simple Icons has tons of social media icons.

Collapse
 
oohsinan profile image
Omar Sinan

Hmmm very interesting thanks for the feedback I’ll look into it! 🙌

Collapse
 
s_aitchison profile image
Suzanne Aitchison

If you have your icons as plain divs with background images like this, you lose the semantic html that allows screen readers to pick them up, and for users to tab and click them via keyboard 🤔

Collapse
 
oohsinan profile image
Omar Sinan

Oh, i didn’t know this! Would using the img tag be better?

Collapse
 
s_aitchison profile image
Suzanne Aitchison

Yep, the problem is div doesn't have any semantic value, and isn't focusable by keyboard by default either.

Usually for this use case you would have a link with an img inside with meaningful alt text.

There's a nice article on this by W3: w3.org/WAI/tutorials/images/functi...

Thread Thread
 
oohsinan profile image
Omar Sinan

Ah that’s so interesting, I’ll check it out. Thank you for sharing! 🙌

Collapse
 
fjones profile image
FJones

Notably, sprites are becoming less useful with H2 and with Google increasingly checking for unused image space. If you're not actually using every sprite element on first load, this method may instead cause a penalty rather than a gain!

So for other people, I'll also echo using SVG here, as well as very closely checking what is penalizing your pagespeed score!

Collapse
 
johnbacon profile image
John Bacon

I appreciate this article, as these are definitely performance best practices in the past, but with HTTP/2 capability on the server and in the browser this is now an anti-pattern.

The best solution (easier to create & maintain, faster to send to browsers, and better at caching) is to utilize HTTP/2. Whatever server you're using should support it. If it doesn't, or if you can't use it, consider serving your domain with Cloudflare, which has supported HTTP/2 for a few years.

Collapse
 
weblings_co profile image
Mark

Totally! With HTTP/2 it can be done the way it was intended without the sprite hack and it means altering one image won't ruin the cache of others let alone techniques like lazy loading of images. Never forget that tools like PageSpeed Insights are there to give you insights not for you to serve them.

Collapse
 
patricknelson profile image
Patrick Nelson • Edited

Is it still worth it, though? 🤔

That's the question I've been asking myself now, these days. For it's time, this was a pretty revolutionary idea. The technique has been around for many years now, really catching on by the late 2000's. These days, however, with HTTP/2 and HTTP/3, the overall benefit of bundling images together into one (to reduce HTTP overhead due to TCP/IP latency + protocol overhead) it's becoming theoretically less important. This is assuming your server is using those new protocols and the connecting clients support it as well (most modern browsers support HTTP/2 right out of the box). I say "theoretically" because we need benchmarking to be more certain.

I ended up stepping back and asking myself this question thanks to the fact that a 5yr-6yr old grunt workflow we already had setup was becoming cumbersome to manage, beginning to fail due to legacy module/node reasons (especially since phantomjs is is now a... ghost). I personally still see a huge value in "spriting" single color SVG's into a font (due to the flexibility of being able to easily colorize) but I've begun to wonder if it's still worthwhile for PNG/GIF (bitmaps) and colorized SVG's (vectors), considering the benefits of the alternative, i.e.: Lower maintenance (reduced legacy support), the ability to inline SVG into an already gzip'd or brotli'd page and better caching (by keeping them separate), as noted elsewhere.

Collapse
 
shymmer69 profile image
Nick Ryan

Aside from the obvious comments about using SVG instead of background image hacks, why do you need 1 pixel gaps and then to use sub-pixel sizing for the sizing? Sub-pixel sizing will create blurred pixelmaps which really isn't so useful

Collapse
 
assafalmog profile image
assafalmog

Nice article.
I would preffer to use font icons instead of image sprite.
You can use service like ICOMOON to convert your svg's and create your own font icons to get better performance.

Collapse
 
oohsinan profile image
Omar Sinan

Yeah 2 popular opinions I’m seeing are font icons and SVGs. I found it very interesting, will certainly look into both to see how the performance improves. Thanks for sharing 🙌

Collapse
 
duomly profile image
Duomly

Good article.
As a Hunt: If these are mono-color, you can try to make a font from them. Or if multicolor you can use svg, it decrease size a lot in compare to png.

Collapse
 
moatazabdalmageed profile image
Moataz Mohammady

Awesome I will check also I loved you landing page

Collapse
 
oohsinan profile image
Omar Sinan

Thank you! Means a lot 🙌

Collapse
 
longzero profile image
LONG • Edited

The comments mentioning svg make me think of base64. Has anyone tested if background-image was a sprite in base64? It would mean one request for CSS AND for icons which is pretty neat.

Collapse
 
fjones profile image
FJones

Since base64 image urls are just that - urls - it should work. That said, you wouldn't want a sprite in there (unless used as a custom property). You'd just want individual images. That said, reusability, readability, and effort to change the icons later can make this more tedious than it's worth for pagespeed.