BVision Ruby Blog

Please stop embedding Bootstrap classes in your HTML!

Posted on Feb 29, 2012

A few months ago, Twitter released Bootstrap, a UI framework for websites that caused such an impression that it quickly become the most followed project on Github.

Its popularity is due mostly to the fact that it allows developers with weak design skills such as myself to quickly create an application that looks at worst adequate, and at best, quite attractive. I'm a huge fan.

Bootstrap also appeals to developers because it's implemented in Less, a CSS preprocessor written in Javascript that you can run in your browser, allowing a comfortable developer workflow and compatibility with sites written in Ruby, Python, PHP, or any other technology you can make web applications with.

But along with Bootstrap has emerged an ugly, insidious and destructive developer antipattern: embedding Bootstrap's CSS classes directly in HTML. Not just end-developers: nearly every library that implements support for Bootstrap does it. Twitter's documentation, in fact, encourages you to do it, even though other frameworks realized this was a problem as far back as 2009.

Let's see what these classes look like:

<div class="row">
  <div class="span6">...</div>
  <div class="span6">...</div>
</div>

What's wrong with this? First of all, by embedding appearance-oriented code into our HTML, we're bucking the evolutionary trend of web development of the last 10 years. Jeffrey Zeldman's seminal 2003 work "Designing with Web Standards" explains the benefits of keeping code in separate layers for content, presentation and behavior: by structuring HTML around what content means, rather than how it looks, you can later change the way it looks without having to edit both the HTML and the CSS.

Quoting the W3C:

Think about why you want something to look a certain way, and not really about how it should look. Looks can always change, but the reasons for giving something a look stay the same.

This is why table-based layout fell out of favor. The code above is conceptually little better than this:

<tr>
  <td>...</td>
  <td>...</td>
</tr>

The second problem is this: by hard-coding Bootstrap's class names into your HTML, you're marrying your code to Bootstrap. Bootstrap's very name should indicate that developers should consider it a starter library: something to get you out the gate faster, not your permanent design solution.

At some point in the future you may decide to change CSS frameworks, but if you end up with a mess of code that implements Bootstrap directly in HTML, it's going to be an unpleasant experience. And if Twitter decides to change the class names they use - which they have done already -, then get ready to spend a lot of time with ack or grep while you change your HTML everywhere to match, or never upgrade your Bootstrap version.

The solution

The solution to this is so easy that its lack of popularity and diffusion makes us burn with nerd rage.

Like Sass and SCSS, Less provides mixins, meaning that if you write your stylesheets in Less rather than CSS, you can include the Bootstrap classes in your stylesheet rather than in your HTML.

As a quick example, assume we have a Less class named "loud" that makes type bold and red. We can simply include this class inside the style for another class, and have it applied:

.loud {
  color: red;
  font-weight: bold;
}

// Make all H1 elements loud
h1 {
  .loud;
}

Bootstrap includes Less mixins to apply styles like "row" and "column," specifically to let us get them out of our HTML. Let's see how to use them:

<!- our new, semanticized HTML -->
<div class="article">
  <div class="main-section">...</div>
  <div class="aside">...</div>
</div>

<!-- its accompanying Less stylesheet -->
.article {
  .makeRow();        // Mixin provided by Bootstrap
  .main-section {
    .makeColumn(10); // Mixin provided by Bootstrap
  }
  .aside {
    .makeColumn(2); // Mixin provided by Bootstrap
  }
}

We can make this even better with HTML5:

<!- our new, semanticized HTML -->
<article>
  <section class="main">...</section>
  <aside></aside>
</article>

<!-- its accompanying Less stylesheet -->
article {
  .makeRow();

  section.main {
    .makeColumn(10);
  }

  aside {
    .makeColumn(2);
  }
}

This works for many other parts of Bootstrap as well:

<!-- Before -->
<a href="#" class="btn danger large">Click me!</a>

<!-- After -->
<a href="#" class="annoying">Click me!</a>

a.annoying {
  .btn;
  .btn-danger;
  .btn-large;
}

Voilà. Clean, flexible, semantic HTML with no hard-coded Bootstrap classes. If you've ever used Compass before, this should look familiar to you. Now if at some point down the road, a new CSS framework comes out that you like better than Bootstrap, it will be much easier for you to switch.

This applies to components too

You can also apply this same pattern to components and Javascript plugins such as modals which directly depend on DOM elements using Bootstrap's classes. Simply give your elements whatever classes and id's make sense for your application, and then apply the appropriate Twitter classes using jQuery:

$(".my-dialog-class").addClass("modal fade");

In some cases this may be unnecessary; perhaps Twitter has already chosen the same name for a class that you would have used anyway. That's fine - go ahead and use it. The point isn't to go out of your way to avoid using Bootstrap's naming conventions, the point is to not have to use them or depend on them.

Now, please... for the love of all that is holy, stop embedding Bootstrap classes in your HTML!

Would you like to comment? Please check out our thread on Hacker News.