1510 CSS Optimization Basics
1510 CSS Optimization Basics
This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License
Tweet This Book!
Please help Jens Oliver Meiert by spreading the word about this book on Twitter!
The suggested hashtag for this book is #cssoptim.
Find out what other people are saying about the book by clicking on this link to search for this
hashtag on Twitter:
#cssoptim
Contents
Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
Why Optimization Is Important . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
What’s Not Covered by Optimization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
Development Mindsets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
Do One Thing Really, Really Well . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
Know Your Needs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
Stay in the Present . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
Keep It Simple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
Automate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
Operational Optimization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
Understandability . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
Performance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
Quality . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
Maintainability . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
Production Optimization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
Performance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
Output Control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
Tools . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
Websites . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
Books . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
Feedback . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
Optimization has a touch of perfectionism, but it’s truly a means and not an end; with optimization,
we acknowledge that our initial work can improve.
The code in this book follows Google’s HTML/CSS style guide. (For an introduction to coding
guidelines and commentary on the Google style guide, see The Little Book of HTML/CSS Coding
Guidelines.)
Before we begin, this is a self-published book made with little extra help. You can blame me, the
author, for mistakes—but you also have an opportunity to help make the book a little better. Please
file an issue for problems you find, or submit a pull request for specific fixes and suggestions. If you
bought the book from Leanpub or Google Play Books, you should get updates containing your and
other people’s fixes automatically. (Otherwise, there’s always the original source.)
Thank you for your support.
Development Mindsets
We all know the adage, “Give a man a fish, and you feed him for a day; teach a man to fish, and
you feed him for a lifetime.” To me, we feed developers for a lifetime by teaching and cherishing
certain mindsets. By themselves, they aren’t enough, but I view them as the foundation that shapes
our work and our careers. They’re not all related to CSS optimization—that would be odd given that
we’re dealing with so many different technologies—, but they’re generally useful. Let’s look at the
key ones.
Keep It Simple
The idea to keep it simple has a lazy touch, yet requires a high level of skill. Keeping it simple means
to focus, to know what’s important, and through that, to be efficient. Keeping it simple does not
mean to do less; it means to do what matters.
As such, keeping things simple requires that we thoroughly understand our field—the core technolo-
gies, first and foremost, but everything in between and to the sides as well. And it means economy
of motion, because we don’t want to engage in something we don’t need to do.
As a mindset, keeping it simple is truly grandiose. To dive deeper, you may not need to start with a
book on simplicity or minimalism, but rather one about focus—my recommendation is Gary Keller’s
The One Thing.
Automate
Lastly, a most powerful mindset is the one to automate. Every step of our work should, if possible,
be automated. Sometimes that will be obvious—every time after we made a CSS change we run
an optimization script, so let’s automate this step. Sometimes that will require a bit of listening—a
team member mentions how they manually update documentation each time someone reports a
downtime issue. At other times it will be obscure—no one on the team realized there was the option
to automate visual regression testing.
Whenever we repeat something in our work, we should look into whether that repeat work can
be automated: Is there a tool for this task? Can we script this? Automation is powerful because it
makes us more efficient and allows us to tackle more important priorities. However, automation
also requires vigilance. Personally, I work with a recurring reminder to review work processes for
automation options. Everything that keeps us mindful of automation, helps.
Operational Optimization
Let’s talk about our options for writing higher-quality CSS while we’re right at it, during develop-
ment and in operation. This type of optimization benefits us as developers. (The next section will
deal with options to optimize for production, that is, for release and live use, and for the benefit of
our users.)
To get a better look at CSS itself, it didn’t seem useful to cover preprocessors. Likewise, we’re not
going to discuss documentation or guidelines, either, like code comments or formatting standards.
Documentation is an entirely different topic that has more to do with maintenance than with
optimization. Coding guidelines, as important as they are and as many of them we can set up, are
often a matter of preference and don’t necessarily have a bearing on quality (for more on coding
guidelines, see The Little Book of HTML/CSS Coding Guidelines). We’re already applying one of the
mantras: keeping it simple.
Understandability
In operation, we need to make sure our work is understandable. This doesn’t only refer to multi-
person environments in which we’re not alone working on a project. With consistency, for example,
there’s at least individual consistency, which means to write code consistent with ourselves.
Understandability can, in part, be achieved through documentation and comments. Yet other aspects,
and we’ll right start with one (consistent declaration sorting), are so important to take care of that
we’ll need to go over them in detail. Consistency and simplicity, the next two sections, make for the
two pillars of more understandable CSS code.
Consistency
Consistency in the case of code means to write and format things the same way every time. With
individual or “level 1” consistency, this means to be consistent with how we ourselves write code.
With collective and “level 2” consistency, we strive to stay consistent within the realm that we work
in, as when we touch third-party code and stick to their code style. And then there’s institutional or
“level 3” consistency—being consistent with coding standards put up by our organization.
Consistency is a foundational part of optimization; it’s the first step of optimization. Without
consistency, other optimization work is a lot harder.
Operational Optimization 7
1 .feeds ul,
2 .posts ul ,
3 .events ul {
4 list-style: none;
5 margin: 0
6 }
7
8 .feeds li,
9 .posts li,
10 .events li {
11 border-top: 1px solid #eeeeee;
12 padding: 0.7667em 0;
13 }
14
15 .feeds li:first-child,
16 .posts li:first-child,
17 .events li:first-child {
18 border-top: 0;
19 padding-top: 0;
20 }
21
22 .feeds li:last-child,
23 .posts li:last-child,
24 .events li:last-child {
25 padding-bottom: 0;
26 }
27
28 .authors > ul > li > a {
29 margin-bottom: 1em;
30 display: inline-block;
31 }
32
33 .authors ul {
34 list-style: none;
35 margin:0;
36 }
37
38 .authors li {
39 padding: .7667em 0;
40 border-top: 1px solid #eee;
41 }
42
43 .authors li:first-child {
Operational Optimization 8
44 border-top: 0;
45 padding-top: 0;
46 }
47
48 .authors li:last-child {
49 padding-bottom: 0;
50 }
1 .feeds ul,
2 .posts ul ,
3 .events ul,
4 .authors ul {
5 list-style: none;
6 margin: 0;
7 }
8
9 .feeds li,
10 .posts li,
11 .events li,
12 .authors li {
13 border-top: 1px solid #eee;
14 padding: .77em 0;
15 }
16
17 .feeds li:first-child,
18 .posts li:first-child,
19 .events li:first-child,
20 .authors li:first-child {
21 border-top: 0;
22 padding-top: 0;
23 }
24
25 .feeds li:last-child,
26 .posts li:last-child,
27 .events li:last-child,
28 .authors li:last-child {
29 padding-bottom: 0;
30 }
31
32 .authors > ul > li > a {
Operational Optimization 9
33 display: inline-block;
34 margin-bottom: 1em;
35 }
Example: Revised sample code (note the order of declarations and selectors). Since the writing of
this book, the :is() pseudo-class emerged as a great option to simplify code like this.
Consistency is reasonably easy to achieve. We establish coding guidelines, we use (or build) tools
to help follow and test for the guidelines, and then we enforce the guidelines. Many guidelines can
be enforced right after writing and editing our CSS; others when shipping the code to production,
where we may apply slightly different rules.
We’ll cover this last part in the chapter “Production Optimization,” and go over tools under “Tools
and Resources.” Next, we review aspects of consistency that are of import to CSS optimization. One
is automatable; the other isn’t: declaration sorting and selector sorting.
Declaration Sorting
This is trivial and, at the same time, automatable: Sort declarations alphabetically. As Google
advocates, the only exception are vendor-specific extensions—self-destructing declarations that start
with hyphens—which are to be located right before the respective main declaration. (Disclosure:
I had been driving the last major initiative around Google’s HTML and CSS guidelines, which
introduced alphabetical sorting.)
1 .example {
2 background: none;
3 border: 1em dotted #069;
4 color: #096;
5 display: block;
6 -moz-filter: blur(33.35px) sepia(0.34);
7 -webkit-filter: blur(33.35px) sepia(0.34);
8 filter: blur(33.35px) sepia(0.34);
9 float: none;
10 font-size: 1em;
11 font-style: italic;
12 height: 100px;
13 margin-top: 1em;
14 max-width: calc(100vw - 10em);
15 outline: 2em solid #609;
16 overflow: auto;
17 padding: 1em;
18 position: relative;
19 text-align: center;
Operational Optimization 10
20 top: 1em;
21 white-space: pre-wrap;
22 width: 100%;
23 z-index: 1;
24 }
Example: Where to add transform: rotateY(10deg) so that everyone can immediately find it?
This is trivial and automatable but still, in my mind, one of the key optimization methods. That’s
because an almost failsafe, easily repeatable, soon to become habitual, quickly communicable, and
universal method to structure our code is something that has tremendous value. A simple and
robust sorting scheme, like the alphabetical ordering of declarations, at once makes our code more
understandable and navigable.
I intentionally raise alphabetical sorting to “optimization status” because of its many benefits; our
code will be better once we structure it, and we’ll write better code once we can do it ourselves and
not require tooling to do that for us. (Not all CSS we’ll touch will have a script behind it that sorts
for us, so we benefit from internalizing this way of sorting.)
Sort declarations alphabetically.
Selector Sorting
Selector sorting is the antithesis to declaration sorting. It’s far less trivial to standardize and also
more difficult to automate. (On a brief investigation it seems that until now, my own draft is the
only public attempt at a system. I welcome feedback!)
Yet selector sorting is the next impactful method at our disposal to make style sheets consistent
and, in a way, optimize them for further optimization. When it comes to maintenance, a defined
and followed selector order is crucial to successfully DRYing up our style sheet declarations (“DRY”
from “Don’t Repeat Yourself,” a principle that helps with maintenance). It makes us avoid an extra
round of DRYing selector groups and spares us from additional testing complexity.
1 html {
2 font: 87.5%/1.5 'helvetica neue', helvetica, sans-serif;
3 max-width: 600px;
4 padding: 1em;
5 }
6
7 footer {
8 border-top: 1px solid #eee;
9 margin: 2.5em 0 0;
10 padding: 3px 0 0;
11 }
Operational Optimization 11
12
13 h1 {
14 font-weight: 300;
15 margin: 0;
16 }
17
18 ul {
19 list-style: none;
20 margin-left: 0;
21 padding-left: 0;
22 }
23
24 a {
25 color: #e30613;
26 text-decoration: none;
27 }
28
29 a:focus,
30 a:hover,
31 a:active {
32 text-decoration: underline;
33 }
34
35 strong,
36 em {
37 font-style: normal;
38 font-weight: 600;
39 }
40
41 .info,
42 #intro,
43 #error {
44 border-radius: 5px;
45 padding: 5px;
46 }
47
48 .info {
49 background: #fff3ca;
50 margin: 1em -5px;
51 }
Example: High level block elements, then text level elements, then classes and IDs, &c.
Operational Optimization 12
Although it seems that many teams of web developers have survived without a firm idea of how to
arrange selectors, only when we have some sense of order can we truly get to consistent style sheets
(granted that this is our goal). More importantly, only then do we have a chance of eliminating
unnecessary work caused by chance ordering. As we’ll see with the avoidance of repetition, that
unnecessary work is otherwise awaiting us.
Accordingly, the lack of initiatives and options for selector orders should give us something to think
about and work on in our community. If you’re in a position to do so, consider what we have and
help us come up with additional options and conventions.
Simplicity
Making code simpler is the next optimization goal. However, the goal of code simplicity is often
also a goal of code minimalism. Simplicity and minimalism don’t necessarily correlate—they don’t
correlate in our coming case of shorthands, yet they do when we speak about character minimization
as part of production optimization.
The goal of simplicity is important: Optimizing for it makes code more understandable and, in most
cases, faster. It makes our work easier. And it generally makes our work better, because using simple
and concise code challenges ourselves as craftspeople.
In times of a surprisingly alive OOCSS and BEM and Atomic CSS [and, later, Tailwind], ID and class
naming has drowned as a developer topic, sinking to a second-order afterthought. And yet when we
consider that not all web projects are super-complex mega sites with internationally distributed
teams of dozens of developers and third-party agencies in automated testing and deployment
environments, in order to warrant presentational naming schemes because our guideline and
communication processes are so difficult to implement that no hand knows what the other hand is
doing—short pause—, we don’t need or benefit from naming schemes that sacrifice understandability
and maintainability for brief presentational class soups from the 90’s (Atomic CSS). The time to know
how to name IDs and classes, and to use both aren’t over yet; IDs aren’t blindly to be discarded, just
as little as universal selectors, !important, or shorthands.
The rules for ID and class naming are simple and lasting:
This doesn’t aim to rule out other naming schemes, but should be the starting point. It’s useful to
learn and apply these rules before switching to a scheme that violates them. Only when we have the
experience of developing and maintaining web projects will we be able to tell whether the violation
is smart and justified, or haphazard and premature.
Operational Optimization 13
Because the topic of ID and class naming, although a beginner topic, has been so neglected, it’s
important to note: No matter how otherwise optimized, a style sheet that uses poor ID and class
names is still a poorly crafted style sheet.
Shorthands
Shorthands—CSS declarations that combine other declarations, like font, border, or animation—are
a useful part of CSS because they help to make CSS more minimal-simple. They allow us to write
less code, though not necessarily more understandable code. This is a situation that perhaps made
one camp declare that CSS shorthands were an anti-pattern, and the other say they weren’t.
Modifying what I put to protocol as a part of that other camp, they’re both.
Shorthands make code less understandable in complex projects, but do make code more minimal.
What tips the simplicity scale is the fact that shorthands always make our CSS more minimally
simple. Only in large and complex projects, they make it less understandably simple because they
imply so much: Everything a shorthand declaration doesn’t say still means something, because the
values that aren’t set are set to their initial values. And that can—in large projects—lead to problems.
1 html {
2 background: #fff;
3 font: 100%/1.88 palatino, lora, georgia, cambria, serif;
4 }
5
6 body {
7 margin: auto;
8 padding: 1.25em 1em;
9 }
10
11 #announcement {
12 background: #ff0;
13 margin: 1em auto 1.5em;
14 padding: .5em;
15 }
Example: In this shorthands-only piece from an actual website, the shorthands simplify and
improve the code.
Because of their value in making code more compact, and their generally positive effects on small
projects, we benefit from using shorthands.
Operational Optimization 14
Performance
Performance is an obvious goal to optimize for. The faster, the better. We know that the user
experience improves when everyone gets what they want, quickly, and that with better speed,
conversions increase as well.
What we can also say is that improving rendering performance may not be nearly as effective as
improving loading performance. That is, not omitting optional tags for the reason that the browser
would otherwise need to “put them back” is not as helpful for performance as is compressing images.
These calculations are generally done so quickly that the respective issues don’t matter in practice.
(There’s nothing to worry about when omitting optional tags and unneeded quotes.)
The cases we’ll look at now exemplify this situation. Performance is not nearly as clear-cut as it’s
often presented.
any more elegant code in terms of code minimalism (though those who connect verbosity with
understandability may have a point).
Where we are right now, selector performance is a box better left closed.
As such, yes, inline CSS is good for performance, and as such, we should consider it a CSS
optimization measure. But unless we deal with truly unique styling on truly unique single pages, a
Operational Optimization 16
categorical “no” to inline CSS. Our vision of web development discourages this: It asks to write the
leanest possible HTML for maximum freedom of movement in terms of updates and maintenance.
We don’t want to touch HTML for formatting updates—and inline CSS prevents that.
With improvements to our content management, build, and deployment processes, HTML
maintenance has become a lot easier and cheaper. Not only due to component-based
development have we gotten to a point at which we can speak of a new paradigm for web
development, where the first paradigm, absolute separation of concerns, has been softened
decisively. That’s practically speaking a helpful and theoretically speaking a fascinating
development. Personally, I still recommend following the first paradigm and to separate
concerns (like structure, presentation, and behavior).
Rule Hygiene
We can have a big impact on performance by removing unused and unneeded CSS. This sort of
hygiene is simple in theory—just get rid of what isn’t necessary—but a bit more tricky in practice.
The trickiness lies in the fact that it’s often hard, if not impossible, to tell what rules truly aren’t
needed. There are tools for this purpose, but it’s difficult to be certain of where styles are used, and
often not feasible on large websites—sites so large that they have similarly looking marketing sites
Operational Optimization 17
run by third parties that secretly hot-link the main site’s core style sheets. On top of that, it’s difficult
to automate the procedure.
Here are some actions that help keep unused CSS in check:
The Unused CSS crawler has the most to offer, telling us with considerable certainty what’s used
and what’s not. (It has become one of my favorite tools for CSS rule hygiene optimization.)
Images have always been a matter of optimization on the Web. At first they hadn’t been
recognized as something to optimize for and rather, like the infamous “spacer GIFs,” served
the widespread deterioration of websites by being used endlessly to build entire layouts in
conjunction with layout tables. But then our attention was on
These topics, without the redundancy of the formats and compression questions, are exactly
the ones we still focus on today. But although I’ve debated to make image optimization a
part of this book, it’s not CSS optimization—it’s image optimization. And Addy Osmani has
written such a book.
Quality
What is code quality, or quality code? A great question for technical interviews, the answers are
linked to almost everything in this book. However, there’s one aspect that’s key.
Operational Optimization 18
Validation
How can we tell that what we’re coding works? We test. How can we tell it’s error-free? We validate.
Yes, testing also exposes errors in our code, and we depend on validators to be up-to-date on the
latest (which they aren’t always). Still, validation plays the critical part in making sure that our
code is syntactically correct, and that it uses selectors and declarations (CSS) as well as a document
structure and elements and attributes (HTML) that actually exist.
There’s a gray area when the respective working groups have just come up with new features (that
is, recently extended the specifications), and the validator teams haven’t caught up yet. That gray
area must not prevent us from validating. That would be like refusing to use cellphones unless the
batteries are fully charged, or declining to wear clothes unless they’re brand-new.
Example: Issues.
Operational Optimization 19
Through validation—whether using the W3C CSS validator or another tool—we optimize our style
sheets because we can correct or remove code that doesn’t work. We also benefit by getting a
better technical understanding (validation issues can be instructive) and with that becoming better
professionals (everyone can write invalid code—we’re experts because we write valid code). These
are the two great things about validation.
Maintainability
Optimizing for maintainability means doing everything to make maintenance as easy as possible. It
starts with avoiding work that’s unnecessary, and surprisingly, this begins with the mundanest of
things—proper style sheet naming. We won’t dive deeper into this here, but it’s important to keep an
eye on the senseless activity of changing style sheet names. When we’re doing that, we’re not taking
care of a maintenance task—we instead mess up one of the simplest things in web development.
(Defensive caching assumed, let’s just use functional or generic names. Personally, I’ve never in my
20-year career changed a style sheet’s name once it was just called “default.css”.)
Irrelevant: !important
Similar to performance, there are myths to debunk. Contrary to some views, there’s nothing harmful,
dangerous, or unmaintainable about using !important. !important, a part of the cascade, is a tool.
As with every tool, one can use it wrong. Using a knife to eat soup is frustrating. Using a hammer to
solder circuit boards is difficult. Using !important to fix every layout problem is like using pesticides
against bugs: It’s tough on the environment.
Alas, that doesn’t mean one shouldn’t use knives, hammers, or !important. What it means is to
learn when it’s best and most effectively used.
In essence, let’s not refrain from using !important. Let’s not shy away from using it for quick testing
and debugging. Let’s use it for declarations that come early in our style sheets but that are rather
unspecific, and hence run the risk of (or probably just suffered from) being overridden in some way.
That’s not bad development practice. That makes sense.
Use of !important is legitimate.
Separation of Concerns
Separation of concerns is one key for maintainability. It’s defined as follows in Wikipedia:
specific as “the name of which class to instantiate.” A program that embodies SoC well is
called a modular program. Modularity, and hence separation of concerns, is achieved by
encapsulating information inside a section of code that has a well-defined interface.
The first and most important part of separation of concerns is to separate structure (HTML),
presentation (CSS), and behavior (JavaScript or, more accurately, ECMAScript).
On a macro-level, separation of concerns ensures that we develop using the appropriate language
(in the 90’s and 2000’s we’ve seen what solving design issues in HTML leads to: millions of layout
tables), and that we know where to look when there are issues (we don’t want to address document-
structural issues in JavaScript).
For CSS, that means to make sure we collect everything that’s related to the appearance of our
site or app, and place that in our style sheets. In a way, separation of concerns is the basis for all
optimization—that way, we know that our CSS is actually handled in style sheets (and not in HTML
templates or JavaScript files).
On a micro- and intra-style sheet level, there are now two options for separation of concerns.
One, reflecting the Single Responsibility Principle, is to separate all styles by functionality and to
break them into modules, blocks, or elements (BEM).
Two is not to do anything, as we don’t have to do anything if we’re sorting selectors consistently
(sorting will inherently lead to a modular order within our style sheets). This is especially true when
we DRY our style sheets. As we’ll see, we can DRY individual CSS modules, but we can also DRY
our style sheets entirely, something for which module separation is inconvenient. (This is another
example of where our work requires prioritization and balance. We may opt for a different approach
when our projects are particularly large.)
Be cautious with OOCSS (object-oriented CSS), BEM (Block Element Modifier), Atomic CSS
[and Tailwind], and similar methods and solutions. Monitor closely how they help and how
they hinder you.
What they do is address some of the problems of large-scale web development, while curbing
freedom and flexibility affecting all of web development. (In the case of utility CSS, it may
lead everyone back to standardized beginner code.)
When we’re asked to avoid the descendant selector (OOCSS), then great, no worries about
inheritance—but also no elegance through contextual styling. When we shall avoid nested
selectors (BEM), but “in this case they are reasonable,” then we are not better off than
before. When we must memorize more than 40 new classes (Atomic CSS) only to write
the most presentational markup (the opposite of separation of concerns), then we negate all
the advantages of CSS.
Using declarations just once (“UDJO”) is an old technique. It means what it says: to use each
declaration just a single time.
It’s a tangible optimization step in that we’re still encouraged to write CSS the natural way, to then
go over what we’ve written to make sure we leave no repetition behind. That process is roughly as
follows:
• Write CSS.
• Decide on DRY boundaries: section (functionally separate CSS parts) or file, component, @media
level?
• Be sure to format code consistently, as background: none, background:none, and background-image:
none could all mean the same but make our task of finding duplicates unnecessarily compli-
cated.
• Search for duplicate declarations:
– For new style sheets: after the initial setup has been done.
– For new features and bug fixes: after the respective work has been done.
– Tip: If version control highlighting for file changes is not enough, temporarily indent
changed declarations only to check for their repetition.
• Dissolve duplicate declarations:
– Check each declaration (in new style sheets) or each changed declaration for re-occurrence
within the set boundary (when limiting de-duplication to sections, limit search scope to
these sections).
– For each duplicate declaration (the actual work):
+ Determine which respective rule should come first in the style sheet (for this, one has to
have an unwritten or written standard for how to order selectors).
+ If this first rule contains additional declarations, i.e., declarations that we haven’t checked
yet or that aren’t duplicates, copy the entire rule and paste it after the original. Keep the
discovered duplicate in the first rule and remove the other declarations, and vice versa in
the second rule, so that that rule is like the old rule just without the declaration we found
to be used more than once.
+ Copy the selectors of the other rules that contain the respective duplicate declaration to
the rule that comes first.
+ Be sure to remove the duplicate declarations whose selectors have just been copied up in
the style sheet, and to remove the entire rule if the rule only consisted of the now moved
duplicate declaration.
+ (Repeat.)
Operational Optimization 22
– Be sure to check the correct order of the selectors for the rules that now handle the formerly
duplicate declarations.
– Be sure to check for the correct placement of the rules that now combine formerly
duplicate declarations.
• (Repeat.)
• Test.
This may seem intimidating, but is precise; and it’s only a lot of work when we just wrote and
optimized an entire style sheet. For small updates, the process is considerably easier and feels much
more grateful. (Unfortunately, there’s no tooling yet for UDJO. As it’s difficult to automate, it’s a
technique that belongs to the craft of writing CSS.)
What we receive is a style sheet that’s in most cases lighter than what we started with. Yet as
file size is not always a factor for performance (thanks to compression), the main benefit is greater
maintainability: We end up with style sheets that are more compact, easier to understand, and easier
to manage. The benefit of this optimization step is so great that we may not even need something
like variables anymore. When, unlike the average website, we don’t repeat each declaration about
four times, we don’t suffer from the issues of that much repetition.
Try this process on for size, and apply it to components or CSS sections first (that is, avoid declaration
repetition within functional blocks, as with page styles, navigation styles, form styles, however the
blocks are divided). This way, it’s easier to get acquainted with the process, to get a moderate result,
and also to feed back your own ideas on DRY CSS to the community.
This concludes the section on operational optimization. What we’ve covered are all things we need
to focus on while working on style sheets. Most of that couldn’t be automated (except controls that
inform us when, say, our style sheet contained too much repetition, or if we were about to submit
something invalid). But even if it could all be automated, I believe it makes sense for us to internalize
and live what we’ve just discussed. Not only does that improve our code, but also us as professionals.
Operational Optimization 23
That exception there in parentheses, about controls, looks innocent but hints at the future of
professional development: automatic live feedback. A priority for modern editors of which
some (Visual Studio Code, WebStorm) have begun to pick it up, this will mean to instantly,
on editing, get notifications on unused code, inconsistencies, redundancies, validation issues,
&c. The way still seems long at this point: We’ll need great UI and AI features to make it all
work effectively, from easy ways to mark false positives to train the software false negatives.
Still it’s what’s missing from the current way of development in which code is only evaluated
once we checked it into a repository or deployed it to a staging or production environment.
Production Optimization
For production, we usually take care of all the things that are good for end users. Software can handle
much of this. Some things, however, we benefit from doing ourselves. For example, we can get into
the habit of writing more minimal CSS (as with omitting leading 0’s). Or, in static environments and
in small projects, we can work with a single style sheet (to keep the number of requests low and to
avoid future HTML changes), without resorting to tools.
Performance
Performance is one of the primary optimization goals and again, rendering performance is not the
subject here. This is due to the so far practical impediments to measure and optimize it, and hence
the often comparatively marginal results.
As long as our code is consistent, the steps suggested here can all be taken care of right before
production, automatically. They don’t have to find their way back into the operational repository.
We’ll start with the exceptions, because they can be covered by our code style guidelines and also
be handled manually.
Character Minimization
To make our style sheets more compact (that is, to make them easier to read and smaller in size), we
remove all unneeded characters. That doesn’t refer to whitespace and comments yet. (Both can be
covered by the same tool, so let’s make that a separate step.) Instead, it refers to removing CSS that
isn’t strictly needed. This includes:
As noted in the introductory section, these items can be covered by coding guidelines, but they’re
also easy to automate and process just before pushing style sheets to production.
Production Optimization 25
Code Minimization
In the last step, we minimized our CSS code in a way that doesn’t impair understanding. The
next step is to remove all characters that aren’t needed for the style sheet to work. This makes
it production-ready.
Again, this is only presented as a separate step to illustrate that we can remove certain characters
manually. The outcome of full code minimization makes working with style sheets rather cumber-
some, if not practically impossible (note the minified style sheet below).
We’re doing two things at this step:
1. removing comments,
2. removing (non-required) whitespace characters.
1 html {
2 font: 87.5%/1.5 'helvetica neue', helvetica, sans-serif;
3 max-width: 600px;
4 padding: 1em;
5 }
6
7 footer {
8 border-top: 1px solid #eee;
9 margin: 2.5em 0 0;
10 padding: 3px 0 0;
11 }
12
13 footer small,
14 label {
15 display: block;
16 }
As mentioned at the beginning of this book, we benefit from automating our work. As this
optimization step is ugly to perform manually, we have a case here that should be and that is almost
always automated.
For both character and code optimization there are several web-based tools and scripts, for
example:
For the Node.js ecosystem, some of the more popular packages for CSS compression include:
• clean-css
• css-minify
• CSSO
• Minify
• UglifyCSS
File Normalization
We can work with as many style sheet and preprocessor files as we want, even though that makes
it more difficult to avoid declaration repetition (see “Using Declarations Just Once”). However, for
production, we should make sure we combine them into a single file to load. That’s important for
more effective compression and, even more so, to reduce the number of HTTP requests. (HTTP/2
alleviates but at the moment I still advise to limit the number of requests.)
The idea behind this is that HTTP request overhead makes for 500–700 bytes, costing “about 100 ms”
(Steve Souders, Kyle Simpson).
This data has led to the recommendation to inline files smaller than 1 KB, but not bigger than 4 KB
(Guy Podjarny).
Let’s assume that most sites that use several style sheets (to then be combined to a single one for
production) work with files that are larger than 1 KB. As such, it’s useful to have these as individual
files (and not inline). For each style sheet that we get rid of and merge, we save roughly half a
kilobyte and 10 ms. This leads to the general recommendation to merge all styles into one file and
link that from our documents.
Yet, there must be something else. What about small sites, and what about overall file size and
caching?
Small sites, particularly one-pagers with just a few rules, may be under the threshold. If the site
is and will be a one-pager forever, we have a stronger incentive to inline all code, both styles and
Production Optimization 27
scripts. But that also depends on the page itself and our ideas about separation of concerns. If the page
resources are so few and light that an extra CSS request is not noticeable, it may well be fine to stick
with a separate style sheet. If we strongly believe in separation of concerns, we might just always
go for that separation (and what may at first sound rigid then becomes consistent and simple).
File size and caching are normally the issues of biggest concern. They’re linked with the following
two questions:
1. If all our styles are in one style sheet, but a user visits just one page, how can we justify pushing
all the unused styles onto them?
(Per RocketFuel and Kissmetrics, the average bounce rate on the Web is around 50%—just to provide
a number, as bounce rates vary per field as well as per type of content.)
2. Same scenario—if all our styles are in one style sheet, what is a good balance to make sure that
the style sheet gets cached but we can swiftly roll out updates?
I set out to go over both questions in detail, but believe it to be more useful now to leave them open.
This should remind us that, even though technical questions often beg definite answers, there are
questions that don’t lead to a strict “right” or “wrong”—the answers often depend on our priorities.
What’s there to consider for a decision?
• For performance, in terms of efficiency and file size, each page should only come with the
styles it uses.
• For performance, in terms of caching, each style sheet should be cacheable.
• For performance, in terms of efficiency and file size when a user visits many pages (low bounce
rate with visitors covering a high percentage of needed styles), a single style sheet is fastest.
• For HTML maintainability, style sheets should not be versioned manually (we don’t want to
update HTML code every time we update CSS code).
• For CSS maintainability, style sheets should not be broken up manually (we don’t want to
merge style sheets every time we update CSS code).
• For general maintainability, code should be kept simple.
• Tooling helps.
et cetera.
I’ll offer a perspective. There are a few reasons for only providing the styles that are actually used
on each page. This approach, CSS tree shaking, should be taken if 1) the project is large (perhaps
>10,000 pages, or >10,000 declarations) and 2) it can be automated.
Production Optimization 28
1 � index.css (or)
2 � contact.css (or)
3 � search.css (or)
4 � …
Example: Page-oriented, automated, cacheable style sheets carrying everything each page needs.
(Not covered: Dynamic loading of styles needed on subsequent page visits.)
In other cases it seems most effective to go for a single style sheet. That holds both for fresh starts
(easiest to set up, especially in small projects) as well as for production (in which case the merging
or bundling of style sheets should be automated).
1 � default.css
Compromises and exceptions should be made sparingly and wisely, as I may demonstrate with an
approach I took in Google’s Go framework: Provide a small core style sheet sufficient for basic pages,
a bigger one for more complex pages, and individual style sheets for custom subsites and pages.
1 � go.css (or)
2 � go-x.css (or)
3 � default.css (extending either go.css or go-x.css)
Ultimately, there’s no single answer for CSS file management. The solution we choose benefits from
being simple, but the approach depends on project complexity and our options to automate. And
sometimes, as of recent years, our frameworks and tooling answer this for us.
Output Control
As the final step, it’s important to check what we’re shipping. Did all our optimization steps work?
Have we missed anything?
Production Optimization 29
Manual checks can be swift—scan the output, perhaps re-formatted to be more readable. (If browser
developer tools don’t suffice for an in-depth look, web-based services like CSSTidy allow us to
“uncompress” a style sheet.)
Automated checks take time to be set up properly and depend on needs and priorities. Solutions
include free and paid services used in conjunction with task runners or hooked up to the respective
CI pipeline. A simple setup may involve making use of Git hooks to use a script like pre-commit to
validate and lint on commit. Nowadays there are more elegant options, notably stylelint.
The topic of reviews brings together much of what we’ve discussed so far: We enforce our desire
for quality (the reason why we optimize in the first place) through our development mindsets (like
doing our work really well and automating it in order to focus on the things that matter).
This concludes the basics of CSS optimization. We’ve covered the most important parts, and more
than basics. I don’t say that to inflate the idea of “basics” but because pretty much everything else
now depends on development paradigms, priorities, and the big picture.
That, then, I’m willing to put to the test: Please share your thoughts on what else should be required
optimization steps. Share them privately by contacting me, or share them publicly, perhaps tagging
them so that others can find your views. For this, I propose the hashtag #cssoptim.
Other than that, it’s my wish that everyone, the aspiring CSS developer as well as the senior CSS
tech lead, could take something from this book. Its value is surely related to how much you can take
with you. To compound that value, we’ll finish with an overview and a selection of resources.
Summary
CSS optimization is important because we, especially as individuals, don’t always write perfectly
efficient, understandable, and maintainable code.
Writing quality code, however, is what makes us professionals.
CSS optimization does not entail “everything” that can be done with a style sheet; it entails what
makes it more efficient, understandable, and maintainable, while looking for a healthy balance.
As professionals, we benefit from doing one (or two, or three, but not eighty-five) things really, really
well; as web developers, it’s a good idea if CSS is one of those things.
It’s useful when we know our needs.
It’s sound when we develop for the present.
It makes our work easier when we keep it simple.
There’s nothing wrong with doing less work—by automating more of it.
There’s nothing wrong, either, with not doing any work, of a certain type—by automating all of it.
(There’s much wrong with not doing important work because we haven’t yet managed or automated
the unimportant work.)
Code should be understandable and for that, it’s useful when it’s consistent and simple.
Consistent CSS is founded on alphabetical declaration sorting (everything else is too complicated)
and on a robust order for selector sorting.
Simple CSS uses functional or generic names or avoids IDs and classes altogether.
Simple CSS also likes shorthands (yes).
Speed is important.
Selector performance doesn’t matter and inline CSS often is a crime.
(Web development is not software development.)
Some declarations may be slower than others but there’s rarely reason for panic.
Rule hygiene may be most important for CSS performance.
The first step in determining quality is through validation, where higher error counts mean lower
quality scores.
Every piece of code gets at least touched twice.
Web design is a process.
Summary 31
(For these last two observations, maintainability and maintenance are critical.)
!important is not an obstacle to maintenance; it’s a tool.
One of the most important principles is separation of concerns. Content, structure, presentation,
behavior are different concerns.
In code, we don’t want to repeat ourselves.
Accordingly, in CSS, we want to limit the repetition of declarations.
Optimization for production is an important second step because, in production, machines use our
code whereas, in operation, humans use it.
When we cannot production-optimize automatically, we should do as much as we can manually, as
part of our craft.
For production, we remove all unneeded characters. All of them.
We typically want to reference one style sheet that includes all styles, though there are cases of high
complexity where a modular approach leads to better performance.
(We cannot be absolved from thinking and making decisions about our projects.)
(Exceptions prove the rule.)
We regularly review our CSS, both pre-production and in production.
We are professionals.
As professionals, we feel responsible, we hold ourselves accountable, and we set high ethical
standards for ourselves.
And, as professionals, we lead by example.
Resources
The following is a small selection of useful CSS tools, sites, and books. They’re geared towards more
experienced developers, yet novice developers may benefit from them as much, if not more, than
staying with beginner materials.
Tools
A few handy CSS tools, for manual and automated testing:
Websites
A small collection of initiatives and individuals covering CSS:
• Andrew, Rachel
• Atkins Jr., Tab
• Barker, Michelle
• Can I Use
• Comeau, Josh W.
• CSS-Tricks
• Eckles, Stephanie
• Frain, Ben
• Heilmann, Christian
• Kinlan, Paul
• Meiert, Jens Oliver
• Meyer, Eric
• Roberts, Harry
• Shadeed, Ahmad
• Van Damme, Bramus
• W3C (Cascading Style Sheets)
• Verou, Lea
• Weyl, Estelle
Books
An even smaller selection of books:
• CSS Secrets: Better Solutions to Everyday Web Design Problems (Lea Verou)
• CSS: The Definitive Guide: Visual Presentation for the Web (Eric A. Meyer and Estelle Weyl)
• CSS: The Missing Manual: The Missing Manual (David Sawyer McFarland)
• The Little Book of HTML/CSS Frameworks (Jens Oliver Meiert)
Feedback
How did you like this book? Please take a short, anonymous survey.
About the Author
Jens Oliver Meiert is a German web developer and author who has been a technical lead at companies
like GMX and Google. He has written a few lightweight books about a variety of topics, notably
quality web development. Online, he lives at meiert.com. Please say hello.
Other titles by Jens Oliver Meiert:
Available at Amazon, Apple Books, Kobo, Google Play Books, and Leanpub.
Available at Amazon, Apple Books, Kobo, Google Play Books, and Leanpub.
About the Author 36
Available at Amazon.
Available at O’Reilly.
About CSS Optimization Basics
Written by Jens Oliver Meiert. All rights reserved.
Published by Frontend Dogma, c/o Jens Oliver Meiert, Apartado de correos 3, 36070 Pontevedra,
Spain.
Editor: Kirsty MacRae
Reviewer: Tony Ruscoe
While author and publisher have used good faith efforts to ensure that the information in this
book is accurate, they disclaim responsibility for errors or omissions, including, without limitation,
responsibility for damages resulting from the use of or reliance on this book. Use of the information
in this book is at your own risk. If code or technology this book contains or describes is subject to
open-source licenses or property rights of others, it is your responsibility to ensure that your use
thereof complies with the respective licenses and rights.
Contact +34-610859489 or info@frontenddogma.com for more information.
Follow Frontend Dogma on Mastodon.
[1.5.1]