Structuring CSS - State of Play in 2012
There seem to be a growing consensus that some of CSS best practices are actually detrimental. Here’s a roundup of some discussions on the issue.
Structuring CSS has long been a struggle, due the limitations of the language. There seem to be a growing consensus that some of the best practices, particularly the admonition against “classitis” and introducing non-semantic elements, are actually detrimental. Here’s a round-up of some discussions on the issue.
Before looking at semantics, a couple of reminders from back in the day about performance.
Performance Impact of CSS Selectors
Two conclusions:
Based on these tests I have the following hypothesis: For most web sites, the possible performance gains from optimizing CSS selectors will be small, and are not worth the costs. There are some types of CSS rules and interactions with JavaScript that can make a page noticeably slower. This is where the focus should be
The key to optimizing CSS selectors is to focus on the rightmost selector, also called the key selector
Writing efficient CSS
- David Hyatt
- Writing efficient CSS
Main points (bear in mind, this is rather old):
Matching rules are split into families - either tags, IDs, classes, universal. It’s more efficient if each selectors is in just one of these categories.
Don’t qualify ids or classes with tag names -
a#homeora.sidebarbetter:#homeor.sidebarUse the child selector instead of the descendant, but not for tags
.sidebar > .homebut notdiv > asome rules are inherited by elements (e.g., list-style-image, font-size), make use of that
And now, for some modern stuff.
CSS Selector Performance has changed! (For the better)
Main points:
- Forget what David Hyatt said. That was a long time ago. CSS engine have now been optimized to the point where it makes no difference.
Profiling CSS for fun and profit. Optimization notes
Main points:
There are now tools to profile CSS in Opera and Webkit.
Some selectors are slower than others - universal selectors, multiple classes and others
The whole post is a summary of main points, no point in me summarizing it.
CSS for Grown Ups: Maturing Best Practices
This is my favourite of the lot.
- Andy Hume
- CSS for Grown Ups: Maturing Best Practices (audio)
CSS for grown ups: maturing best practises (slides)
His main points:
nothing wrong with “classitis” if it allows us to decouple the CSS from the HTML markup.
the fewer tags in the CSS - the better. E.g., .social .link is better than .social a, because it is not reliant on specific type selectors
Sass / LESS / Stylus are all good tools, but are an extra step and can’t be removed easily from the stack if the problem they were trying to solve has gone away
OOCSS / SMACSS / CSS Lint are better, because they are approaches
he advocates a multi-layered approach similar to SMACSS with layout, module, base, and document layers (missing the states and theme layers). The document layer is the HTML code.
He advocates thinking more in term of modules and using CSS cascade rules to avoid too complex selectors. He uses a double slash convention to signify a selector should appear after another, e.g.
1 2 | |
advocates prefixing all selectors introduced by JavaScript with .js-
A selector like
.promo-box h3is bad because it mixes the module layer (.promo-box) with the document layer (h3). He’d replace it withpromo-box .promo-box-hh1 { font-size : 2em; } h2 { ... etcis also bad - this mixes base and document. He suggests either using custom classes like.h1 { ...or something more typographic like.masthead { ... }modules variations shouldn’t be associated with IDs of elements - e.g.,
#sidebar .promo-boxis bad, better use.promo-box { ... } .promo-box-light { ... }. The same holds for page specific styles, i.e. when adding a class to the body element to signify a different pageHe doesn’t like the syntax for media queries for the same reason. Therefore he created selector-queries, a JS tool to allow him to restructure his CSS more semantically
He doesn’t mind small presentational classes such as
.margin-top { ... }, .gutter-left { ... }etc.It’s a good idea to add extra semantic elements in the document when needed. For example, small icons like comment icons on blogs, instead of of being added to the container
<p class="icon icon-comment">should have their own semantic tag, and the icon style applied to that. Twitter bootstrap has made i a popular choice.He advocates writing online style guides with code samples. Good examples are Twitter Bootstrap, and Paul Robert Lloyd’s styleguide. Plus he shows one he’s been working on, which looks quite good.
Our Best Practices Are Killing Us
Her main points:
A little bit of classitis is not bad
Counting specificity rules. For each CSS selector, count the number each of inline, IDs, classes (and pseudo classes), and elements (and pseudo elements), in that order. For example,
#sidebar ul li a.myclass:hover {}has: 1 ID, 2 classes, 3 elements, whereas* {}has: 0 ID, 0 classes, 0 elements, hence it ‘loses’!important adds another stack of ID, classes, elements to the left of everything, so the specificity stack becomes: ID !important, classes !important, element !important, inline, ID, classes, important, element.
Not keen on preprocessors, but there are some good ideas in there that are becoming part of the CSS Working Group
Top 5 Mistakes of Massive CSS
Their main points:
Print style sheets often slow down rendering even though they are not used
Used a small PHP script to open files in IE. The script creates a new COM( “InternetExplorer.Application” );
A lot of sites neither GZip, nor minify nor combine CSS files.
Serving CSS files (and images) with cookies is pointless
Advocates Object Oriented CSS. Basically abstract UI elements into patterns. Note that CSS objects != JS or backend objects.
Use star and underscores hack, if you have to
Avoid IDs, style classes only
Avoid !important, although they are ok for mixins - but not too many
When optimizing existing CSS, use grep to look out for:
floats - too many is a symptom of a bad grid
margin / padding - they can often be abstracted
font-size - there are only a few readable font-size actually used on a site, and nobody notices 1px differences
Help! My Stylesheets are a Mess!
He says…
Classitis is not so bad after all
Advocates no less many layers: grid, layout, background, container, spacers, typography, foreground, margin / padding, widgets, theming
Advocates naming styles together with designers
About HTML semantics and front-end architecture
His main points:
Pretty much echoes what Andy Hume said
advocates prefixing all selectors introduced by JavaScript with .js-
finds the Twitter Bootstrap practice of using universal CSS selectors, e.g.
[class*="btn-"] {risky. Instead he prefers multiple classes, e.g..btn .btn-close {long class names or multiple selectors don’t really matter after CSS files are minimized and GZipped. Removing 30000 class names from a file only removed 1.6k after compression
he advocates structured class names, somewhat similar to BEM
Measuring and sizing UIs, 2011-style
His main points:
Use percentages for main layout sections
Use no units on any module / widget
Use rems with a pixel fallback for fonts
pixels only for external icons and the like
BEM
I think BEM is taking things way too far, but it may make sense in some scenarios.