CSS must pass through a relatively complex pipeline, just like HTML and JavaScript. The browser must download the files from the server and then proceed to parsing and applying them to the DOM. Due to extreme levels of optimisation, this process is usually pretty fast – for smaller web projects not based on frameworks, CSS usually makes up just a small part of total resource consumption.
Frameworks upset this equilibrium. Include a JavaScript GUI stack like jQuery UI, and watch CSS, JS and HTML sizes skyrocket. Often, developers usually feel the pinch last – when seated behind a powerful eight-core workstation with T3 internet, no one cares about speed. This changes as latencies or CPU-constrained devices come to play.
Optimising CSS requires a multi-dimensional approach. While hand-written code can be slimmed down using various techniques, going over framework code by hand is inefficient. In these cases, using an automated minimiser yields better results.
The following steps will take us on a journey through the world of CSS optimisation. Not every single one might be directly applicable to your project, but do keep them in mind. Want something simpler? Try a website builder.
01. Use shorthand
The fastest CSS clause is one that never gets parsed. Using shorthand clauses, such as the margin declaration shown below, radically reduces the size of your CSS files. A lot of additional shorthand forms can be found by googling 'CSS Shorthand'.
p { margin-top: 1px;
margin-right: 2px;
margin-bottom: 3px;
margin-left: 4px; }
p { margin: 1px 2px 3px 4px; }
02. Find and remove unused CSS
Eliminating unneeded parts of your mark-up obviously causes immense speed gains. Google's Chrome browser has this functionality out of the box. Simply go to View > Developer > Developer Tools and open the Sources tab in a recent version, and open the Command Menu. After that, select Show Coverage and feast your eyes on the coverage analysis window highlighting unused code on the current webpage.
03. Do it in a more comfortable fashion
Navigating through the line-by-line analysis is not necessarily comfortable. Chrome's Web Performance Audit returns similar information – simply open it from the toolbar, View > Developer > Developer Tools > Audits and let it run. When done, a list of problematic elements will pop up.
Get the Creative Bloq Newsletter
Daily design news, reviews, how-tos and more, as picked by the editors.
04. Be aware of the problems
Keep in mind that an automatised analysis of a CSS can always lead to errors. Perform a thorough test of the entire website after replacing your CSS files with the minified ones – one never knows what mistakes the optimiser caused. And moving forward, decent web hosting can help you iron out the creases in your site.
05. Inline critical CSS
Loading external stylesheets costs time due to latency – anyone remember the 'flash of unstyled content'? The most critical bits of code can therefore go into the header tag. Make sure not to overdo it, however. Keep in mind that the code must also be read by humans performing maintenance tasks.
<html>
<head>
<style>
.blue{color:blue;}
</style>
</head>
<body>
<div class="blue">
Hello, world!
</div>
06. Permit antiparallel parsing
@import adds structure to your CSS code. Sadly, the benefits are not for free: as imports can nest, parsing them in parallel is not possible. A more parallelisable way uses a series of <link> tags, which the browser can fetch at once.
@import url("a.css");
@import url("b.css");
@import url("c.css");
v<link rel="stylesheet" href="a.css">
<link rel="stylesheet" href="b.css">
<link rel="stylesheet" href="c.css">
07. Replace images with CSS
Years ago, a set of semi-transparent PNGs to create translucent effects on websites was commonplace. Nowadays, CSS filters provide a resource-saving alternative. As an example, the snippet accompanying this step ensures that the picture in question appears as a grayscale version of itself.
img {
-webkit-filter: grayscale(100%); /* old
safari */
filter: grayscale(100%);
}
08. Use colour shortcuts
Common wisdom teaches that six-digit colour descriptors are the most efficient way to express colours. This is not the case – in some cases, shorthand descriptions or colour names can be shorter.
target { background-color: #ffffff; }
target { background: #fff; }
09. Eliminate unneeded zeros and units
CSS supports a wide variety of units and number formats. They are a thankful target for optimisation – both trailing and following zeros can be removed, as is demonstrated in the snippet below. Furthermore, keep in mind that a zero always is a zero, and that adding a dimension does not add value to the information contained.
padding: 0.2em;
margin: 20.0em;
avalue: 0px;
padding: .2em;
margin: 20em;
avalue: 0;
10. Eliminate excessive semicolons
This optimisation is somewhat critical, as it affects changes of code. CSS' specification lets you omit the last semicolon in a property group. As the savings achieved by this optimisation method are minimal, we mention this mainly for those who are working on an automated optimiser.
p {
. . .
font-size: 1.33em
}
11. Use a texture atlas
Loading multiple small sprites is inefficient due to protocol overheads. CSS sprites combine a series of small pictures into one big PNG file, which is then broken apart via CSS rules. Programs such as TexturePacker simplify the creation process greatly.
.download {
width:80px;
height:31px;
background-position: -160px -160px
}
.download:hover {
width:80px;
height:32px;
background-position: -80px -160px
}
12. Chase down the px
One neat way to increase performance uses a specialty of the CSS standard. Numeric values without a unit are assumed to be pixels – removing the px saves two bytes for each number.
h2 {padding:0px; margin:0px;}
h2 {padding:0; margin:0}
13. Avoid expensive properties
Analysis has shown some tags to be more expensive than others. The list accompanying this step is considered to be especially performance-hungry – avoid them when given the opportunity to do so.
border-radius
box-shadow
transform
filter
:nth-child
position: fixed;
etc.
14. Remove whitespace
Whitespace – think tabs, carriage returns and spaces – makes code easier to read but serves little purpose from a parser's point of view. Eliminate them before shipping. An even better way involves delegating this job to a shell script or similar appliance.
15. Eliminate comments
Comments also serve no purpose to the compiler. Create a custom parser to remove them before delivery. Not only does that save bandwidth but it also ensures that attackers and cloners have a harder time understanding the thinking behind the code at hand.
16. Use automatic compression
Yahoo's user experience team created an application that handles many compression tasks. It ships as a JAR file, available here, and can be run with a JVM of choice.
java -jar yuicompressor-x.y.z.jar
Usage: java -jar yuicompressor-x.y.z.jar
[options] [input file]
Global Options
-h, --help Displays this
information
--type <js|css> Specifies the
type of the input file
17. Run it from NPM
Should you prefer to integrate the product into Node.JS, visit npmjs.com/package/yuicompressor. The badly maintained repository contains a set of wrapper files and a JavaScript API.
var compressor = require('yuicompressor');
compressor.compress('/path/to/
file or String of JS', {
//Compressor Options:
charset: 'utf8',
type: 'js',
18. Keep Sass et al in check
While CSS selector performance is not nearly as critical as it was some years ago (see resource), frameworks such as Sass sometimes emit extremely complex code. Take a look at the output files from time to time and think about ways to optimise the results. Got results to share with a team? Keep files in shareable cloud storage.
19. Set up caching
An old adage claims that the fastest file is one that never gets sent across the wires. Making the browser cache requests achieves this efficiently. Sadly, the setup of the caching headers must take place on the server. Make good use of the two tools shown in the screenshots – they provide a swift way to analyse the results of your changes.
20. Bust the cache
Designers often dislike caching due to fear of problems with upcoming changes. A neat way around the problem involves including tags with the file name. Sadly, the scheme outlined in the code accompanying this step does not work everywhere as some proxies refuse to cache files with 'dynamic' paths.
<link rel="stylesheet" href="style.css?v=1.2.3">
21. Don't forget the basics
Optimising CSS is just part of the game. If your server does not use HTTP/2 and gzip compression, a lot of time is lost during data transmission. Fortunately, fixing these two problems is usually simple. Our example shows a few tweaks to the commonly used Apache server. Should you find yourself on a different system, simply consult the server documentation.
pico /etc/httpd/conf/httpd.conf
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE text/css
This article was originally published in issue 282 of creative web design magazine Web Designer. Buy issue 282 here or subscribe to Web Designer here.
Related articles:
Thank you for reading 5 articles this month* Join now for unlimited access
Enjoy your first month for just £1 / $1 / €1
*Read 5 free articles per month without a subscription
Join now for unlimited access
Try first month for just £1 / $1 / €1
Tam Hanna is a software consultant who specialises in the management of carrier and device manufacturer relationships, mobile application distribution and development, design and prototyping of process computers and sensors. He was a regular contributor to Web Designer magazine in previous years, and now occupies his time as the owner of Tamoggemon Software and Computer Software.