Jesse Buchanan (“jbinto”)

I’m a software developer, a Torontonian, and a Leafs fan.

Using semantic classes with Twitter Bootstrap

| Comments

Twitter Bootstrap is a CSS framework used to provide some commonly used design elements for web projects. It’s great to get your project up and running quickly.

I’m not much of a designer, and (most of the time) Bootstrap helps me easily achieve things I’d be hard-pressed to do on my own: well-designed margins & padding, carefully selected colours, and fluid grid layouts that work cross-browser.

One thing that irks me about Bootstrap, however, is the fact that it litters your markup with their non-semantic class names. If you’re not familiar with semantic markup, the idea is that your HTML markup should only indicate meaning, not presentation. For example:

Semantic markup compared to non-semantic markup
1
2
3
4
5
6
7
8
9
10
11
  <!-- Not semantic: we're saying "this is bold" in the markup. -->
  This is some <b>important</b> text.

  <!-- Not semantic: there's a tag to indicate headers. -->
  <div class="header">Welcome to the site</div>

  <!-- Better: screen-readers can understand the meaning of the strong tag. -->
  This is some <strong>important</strong> text.

  <!-- Better: a web scraper like the Googlebot will understand this is your header. -->
  <header>Welcome to the site</header>

However, when you look at Bootstrap’s example code, the markup is filled with non-semantic class names:

A typical Bootstrap example
1
2
3
4
5
6
7
8
9
<div class="row">
  <div class="span9">
    Level 1 column
    <div class="row">
      <div class="span6">Level 2</div>
      <div class="span3">Level 2</div>
    </div>
  </div>
</div>

I’m working on an NHL hockey prediction game in Rails, and in it, I want to use some Bootstrap elements:

  • Buttons to select the home team by 1, or the away team by 2
  • Badges to show the user’s score

For instance, if I want to quickly use the green and turquoise buttons, I could just stick btn btn-success classes for some buttons (say picking the home team), and btn btn-info for others (say, picking the away team). But now I’ve lost the ability to do things by meaning: I’m not being DRY. If I ever decide the colours should change, I have to search-and-replace on btn-success and this may affect other places in my markup.

Luckily, I’m using the bootstrap-sass gem in my project. This allows me to use SCSS in my project, even though Bootstrap uses the older LESS framework.

This means I can make use of the @extend directive, and keep my class names semantic. So, rather than giving my buttons class names like btn-success, I can do the following:

HAML markup
1
2
3
  - css_class = (team == game.home) ? "home" : "away"
  - css_class += (spread_wager == 1) ? "by1" : "by2"
  = f.submit "#{team.code} +#{spread_wager}", class: "#{css_class}"
SCSS styles
1
2
3
4
5
6
7
8
9
input.homeby1, input.homeby2 {
  @extend .btn;
  @extend .btn-success;
}

input.awayby1, input.awayby2 {
  @extend .btn;
  @extend .btn-info;
}

Now, my markup has no Bootstrap classes in it. It looks like:

1
<input class="awayby2" name="commit" type="submit" value="PIT +2" />

Cool! I did the same thing with badges elsewhere in the project. To show the impact of a user’s pick, I apply either the win or loss class, and @extend the Bootstrap badge classes in my SCSS.

Some people believe this isn’t worth it, and when it comes to structural/grid layout classes, maybe they’re right. I still think it’s a good idea to separate my “home team by 1” buttons from my “create a new user” buttons, even if they both have the same btn-success class in the end. It will make things easier to change in the future, and won’t require me to apply a second CSS class if I ever need to do more.

For my next project I’m going to take a closer look at Foundation, a competing CSS framework. This framework seems to have native support for Sass, a first-party Rails gem, and their documentation treats using mixins as a first-class citizen.

« Multiple forms in Rails Loading Toronto Bikeways data into PostGIS »

Comments