The canonical example of using multiple classes for variations of a UI element is the button element. Here’s an example of the typical markup straight from the Bootstrap framework:

<button type="button" class="btn btn-default">Left</button>

The default button gets btn (setting styles that apply to all btn’s) and the variation of that button is handled with the btn-default (specifics such as colour, spacing, whatever). Crudely:

.btn {
  border: 1px solid #666;
  padding: .3rem .6rem;
  display: inline-block;
}

.btn--blue {
  background-color: lightblue;
  color: #fff;
  border: 1px solid #cbcbcb;
}

Why do we do that? Is it because we (incorrectly) assume other selectors are slow?

Why don’t we do this (note, I actually prefer naming HTML classes this way but ‘whatevs’ as the kids say):

<button type="button" class="btn--blue">Left</button>

And then use the substring matching attribute selector with our CSS/Sass:

[class^="btn"] {
  border: 1px solid #666;
  padding: .3rem .6rem;
  display: inline-block;
}


.btn--blue {
  background-color: lightblue;
  color: #fff;
  border: 1px solid #cbcbcb;
}

Same result, just as flexible but crucially less markup. This way it removes the need for practices such as grouping selectors in the markup and prevents ‘groups’ of classes being separated. For example, this is no longer a possibility:

<button type="button" class="btn sausages are great btn--blue">Left</button>

The related classes, btn and btn--blue are always together as they are the same class: just btn--blue.

Anyway, I’m probably missing something obvious so feel free to tell me I’m stupid in the comments.

Update: 28th May 2014 A few people mentioned in the comments that they believe partial string matching with attribute selectors is too vague. If inheriting a code base, the lack of explicitness with others HTML class naming conventions could certainly be problematic with substring matching. However, if you are in control of the naming conventions for your project, I still feel this is a totally valid approach. To exemplify; in my own naming convention (not used on this site, but I use it on ‘work’ projects) I name UI variants using an underscore so [class^="Btn_"] is not going to match anything other than another button variant. Obviously, this may not work for everyone. It’s therefore important to consider the potential pitfalls of substring selection before adopting this kind of technique wholesale.

Learn to use CSS effectively, 'Enduring CSS' is out now

Get $5 off HERE ↠

Write and maintain large scale modular CSS and embrace modern tooling including PostCSS, Stylelint and Gulp