When CSS Goes Bad
For a technology that can produce such great results with such simple syntax, it’s amazing how often we find ourselves pulling our hair out with bad CSS. We’d like to spend some time figuring out why.
How Can You Tell When CSS Has Started to Go Off?
There are clues:
- The CSS file starts to get very large, good design should be about applying a minimal set of rules to achieve optimal results. If the stylesheets start to ‘bloat’, it may be a sign something is going wrong.
- The appearance of objects becomes unpredictable – particularly when objects appear differently in different places.
- Rules get ever harder to apply. If you find yourself using the
!important
modifier a lot … it’s likely that the rules somewhere have got confused. - The website design starts to look less ‘tight’. When too many differing rules are applied to too many different elements, the design begins to look less harmonious.
Why Does it Happen?
Losing the Design
There are lots of ways this can start to happen but, at its root, the cause is always the same – the clarity of design intent is lost. It might sound grand or pompous, but as a site ages, various things happen which can undermine the original design:
- The developer or designer changes – it’s not uncommon: the original designer may be a freelancer; once completed, maintenance of a site often gets passed to a junior and, once the connection with the original implementors is lost, to some degree it’s inevitable that original design is ‘guessed at’ as maintenance goes on.
- Content is added which is not part of the original brief. Websites develop all the time – the beautiful visuals provided for the original design brief probably didn’t account for a set of tabs, an ‘Add to Cart’ button or an embedded Twitter feed. It’s as likely as not going to be a developer (not a designer) who adds that new code.
- As we’ve mentioned elsewhere, CSS is often reliant on context. If you move an element from one location within the HTML code to another – it becomes likely that some or all of the design is no longer applied.
Think Different
In a modern web design scheme it is unlikely any one individual will have written all the CSS. The complexities of creating layouts which work on a near-limitless range of screen sizes normally necessitates the use of some kind of framework to help the layout look pretty much ‘right’ regardless of the screen size.
Let’s call this Structural CSS.
Structural CSS Needs Structural HTML
More than anything else in the design, Structural CSS tends to have a tight relationship with the HTML (<div>
tags with the class .panel_third
or similar).
Sadly …
… thinking about how best to conquer common layout challenges changes every few years. Since 2008 I think I have seen 3 main approaches to achieving a three-column layout grid. And that’s before the requirements of responsive design are taken into account.
If you wish to change the layout to use a simpler, more lightweight CSS system, you may need to make expensive changes to the HTML files site-wide.
Google, yes, Google. Because they own the monopoly on search, the standards Google exacts to achieve high ranking web pages are slavishly applied by those who wish their website to remain visible (and who wouldn’t?).
And Google changes the way it wishes to rank websites quite frequently.
In the last ten years, Google has gone from expecting:
- the CSS stored in an external file to be loaded before the web page,
- to CSS stored in an external file that does not block the loading of the rest of the web page,
- to needing some core CSS to make the page look mostly right loading before the web page and then load more CSS later
- … and (at the time of writing) Google is encouraging us to add CSS rules directly to the HTML again.
There is logic behind all of those decisions but there are billions of web pages out there. To even try to keep up, developers are bound to chop around with existing code and some chaos is bound to ensue.
Backwards Compatibility
Though it’s a lot less of a problem than it used to be, keeping code backwards compatible can result in code bloating with rules unnecessary for newer browsers. I still find myself writing.
nav a,
nav a:visited {
}
Code language: CSS (css)
… to cope with the fact that earlier versions of Internet Explorer 6 couldn’t display links correctly.
60% of the internet used to be Internet Explorer 6.
If a website didn’t work in IE6, it didn’t work.
Before version 8, Internet Explorer also wouldn’t let you apply more than one rule to an object. Consider this.
<a href="/" class="nounderline red strikethrough padded">
I implement painless modern CSS
</a>
Code language: HTML, XML (xml)
The four rules (classes) potentially assigned to this link allow a total of 24 combinations. Just four rules.
But to achieve this variety in an old browser, you would need to do something like:
<a href="/" class="nounderline">
I am not modern
</a>
<a href="/" class="nounderline_red">
or painless
</a>
<a href="/" class="nounderline_red_strikethrough">
or elegant
</a>
<a href="/" class="nounderline_red_strikethrough_padded">
or easy to remember
</a>
<!-- … and so on … 24 times! -->
Code language: HTML, XML (xml)
It goes without saying, 24 rules take six times as long to maintain as 4 rules. And that’s if you’re familiar with the code.
As I said, although this relates to older code, a lot of HTML has been copied forward over the years.
There is a lot of dated HTML out there.
So often designers and developers will choose to ignore old classes completely and build a new, simple scheme using new classes.
When a time-pressured developer finds old code, more often than not, they remove nothing for fear of breaking what they don’t have time to fully understand.
To avoid potential disruption, they will leave the old classes in there.
This makes the HTML bigger, the website slower and confuses the next guy who comes along.
The next guy may, in turn, be time-pressured and add some more iffy, confusing code …
Modern(ish) Technology
In part to counter the problems of unreliable implementation within the browser, several technologies have emerged which compile CSS from abstracted code (e.g. SCSS or SASS).
Both are similar. Both offer some very alluring possibilities:
Introduce variables into the CSS … don’t like the colour – change it once and it’s updated everywhere.
Nesting Rules and Loops – this can be an incredibly useful feature. Combined with variables, SCSS/SASS can create large sets of rules to cover multiple contexts (such as browser screen sizes) on the fly.
That Sounds Great! So What’s the Problem With SCSS?
To some extent, one of CSS’s key strengths – keeping a single CSS file used by all pages – can work against maintenance of clean, consistent design.
CSS is already at one remove from the HTML, SCSS/SASS even more so.
SCSS and SASS code can be very hard to read. The prevalence of loops within loops means that the final CSS file size can grow exponentially.
A single rule of 6 lines, inside a loop of 3 iterations (say, for the head, main and footer) written for 5 break points (screen sizes) will produce a CSS file of at least 90 lines – for one rule!
As the number of rules increases and loops applied, the likelihood of accidentally creating rules which are never employed increases rapidly. This can make the final CSS file much bigger than it needs to be.
What Else?
When using SCSS and SASS, the developer often never sees the ‘finished’ CSS so strange things can end up going unnoticed.
It’s not uncommon to find rules like this:
header#masthead #logo a {}
Code language: CSS (css)
Now, the #
character in CSS means the rule is intended to apply to a unique entity (like the logo in the top-left corner with the id="logo"
).
When you’re addressing a unique entity you really don’t need context.
Captain James T Kirk
is as meaningful as
the Captain James T Kirk who is on the bridge of the USS Enterprise boldly going where no man has gone before
It’s not wrong as such. But it is unnecessary and unclear. And when code is overlong and confusing, a tired developer (desperately coding before she goes home on a Friday night) is likely to make an inelegant or inaccurate decision as to what to do with it.
Rules for Things That Don’t Exist Yet
Modern websites, which load new content into the HTML all the time, can also make design difficult.
It may be impossible for the person writing the CSS to know what the final, rendered HTML will consist of. It’s unsurprising that sometimes things turn out weird.
Don’t Make Me Think!
When CSS isn’t working, the temptation is always to add more context. This may really, really make it work – but you could end up with a rule like this:
body div.starship#enterprise .bridge a.person#captain_kirk {
color: yellow;
}
Code language: CSS (css)
instead of
#captain_kirk {
color: yellow
}
Code language: CSS (css)
… imagine the mess when Jim gets moved to engineering for the day (geek joke, sorry).
What Can Be Done?
Legacy code of any sort and shambolic legacy code in particular is a classic example of technical debt. The longer it’s left, the more of a problem will become:
- the more expensive it will be to make little changes,
- the fraught it will be to make major changes,
- mobile users will hate you because your website is eating their data-allowance,
- your site may look increasingly improvised – damaging customer trust –
- and your web designer will be sad as their masterpiece turns ugly.
Call in the Cavalry …
Fortunately, technology has improved vastly. In particular:
- Templating systems allow the structural HTML to be changed without manually combing through content. Using an appropriate server-side technology, changing a template so that your content is applied to more up-to-date HTML is relatively straightforward.
- With developer tools, you can experiment directly in the browser to find the rule that does exactly what you want – and nothing else – speeding up development and preventing poor rules from being committed to code.
- HTML5 allows for content to be added in terms of its purpose – an
aside
in an article no longer needs to appear in adiv
tag with the CSS classaside
. This makes CSS easier to read and smaller. You no longer need to understand the CSS to work out what the HTML is designed to display. - CSS is simple. CSS3 is less simple but many of the things you might desire are now embedded without the need for additional technologies. CSS3 allows variables for rapid adjustments of designs. CSS3 features units developed make responsive designs look and work harmoniously.
You may need to carve great chunks out of both your CSS and your HTML to make things elegant again. But, done right, you will end up with a smaller, faster, better looking website.
Every project is different but there will never be a cheaper time to straighten things out than now.