Using Sass To Semantically @extend Bootstrap

Brad Barrow
Tweet

Bootstrap provides a quick and easy way to create a scaffold for your latest site or app whether you’re a novice or a professional developer. For this reason, more and more developers are including the framework in their personal toolbox.

There is, however, a dark side to Bootstrap, in that it makes it incredibly easy to write cluttered, non-semantic and non-reusable markup that will render correctly across all browsers.

In this article, I’ll explain how you can use Bootstrap in a more robust and semantic way. Bootstrap’s latest version shipped with an official Sass port of the framework so we’ll use one of Sass’s most powerful features to achieve this: the @extend directive.

Some Basics on Semantics

First, let’s cover what we mean when we say that we want to make things more “semantic”. HTML documents are intended to be descriptive of their contents from an information hierarchy perspective. One should be able to read them and know what they are about, not how they will look.

With the rise in popularity of CSS and especially CSS frameworks, HTML is often written with a CSS sheet in mind rather than a reader/developer.

It’s not uncommon to see HTML markup like this in the source code of modern websites:

<div class="row">
    <div class="col-md-4">
        Name:
    </div>
    <div class="col-md-4">
        John
    </div>
    <div class="col-md-4">
        Smith
    </div>
</div>
<div class="row">
    <div class="col-md-12">
        <p>
            "I enjoy writing code in my spare time."
        </p>
    </div>
</div>

Bootstrap’s CSS files know exactly what to do with that. Two rows, one split into thirds and the other full width. As developers who are familiar with Bootstrap, that’s easy enough for us to figure out, but what if you’d never used the framework before? What is this snippet of HTML for? What does the information pertain to? The markup isn’t revealing anything practical.

Semantic markup is code that describes it’s content rather than its appearance. We could write the code above semantically as follows:

<div class="author-name">
    <label class="author-nameLabel">
        Name:       
    </label>
    <span class="author-nameFirst">
        John        
    </span>
    <span class="author-nameLast">
        Smith
    </span>
</div>
<div class="author-bio">
    <p>
        "I enjoy writing code in my spare time."
    </p>
</div>

It’s not all that different but it immediately tells us what each element is for and how each one might relate to other elements. What we’ve lost is the knowledge of how this will be presented visually. But that’s not the purpose of HTML after all.

How is Bootstrap Supposed To Style That?

You might be wondering how you’re going to use Bootstrap without any of its built-in class names in your markup? Well, we can leverage the power of Sass’s @extend functionality to solve this problem.

From Sass’s documentation:

@extend works by inserting the extending selector anywhere in the stylesheet that the extended selector appears.

This means we can use our semantic selectors and extend Bootstrap’s selectors to get all of its goodness. Here’s how:

/* Import bootstrap-sass so that we have access to all of its selectors */
@import "bootstrap";

/* Author Bio and Author Name are just Bootstrap .row elements */
.author-bio,
.author-name {
  @extend .row;
}

/* Author nameLabel, nameFirst and nameLast need
   to be a third of their container's width */
.author-nameLabel,
.author-nameFirst,
.author-nameLast {
   @extend .col-md-4;
}

/* The paragraph inside the author's bio should be full width */
.author-bio p {
    @extend .col-md-12;
}

Through the magic of @extend, our selectors are slotted in to the compiled stylesheets alongside the Bootstrap selectors they extend. As you’ll see by examining the compiled code, our selectors have all the exact same properties as the classes they’re extending.

For example, among other things, you should see this in the compiled CSS:

/* one of the compiled rule sets */
.col-md-4, .author-nameLabel,
.author-nameFirst,
.author-nameLast {
  width: 33.3333333333%;
}

You can view the Sass side by side with the compiled CSS here. Neat huh?

Reusability

Another great thing about this method is that it creates readable and reusable components. For example, you don’t have to rebuild the author component out of rows and columns each time you need to use it. Instead, you have sensible names for each part of the component, making it easy to construct. You can also rely on Bootstrap to make sure it’s presented uniformly across your site.

Portability

While Boostrap is one of the best frameworks available, the time may come when you want to move your site to a different framework or even write your own. With the above outlined method you can do so easily because your markup is cleanly decoupled from your CSS.

Fill Your Toolbelt

If you haven’t yet tried the Sass version of Bootstrap, you’re in for a treat. It’s easy to get started on their github page.

Sass isn’t the only thing at play here. If you truly want next-level semantics in your HTML and CSS, I recommend adopting a naming convention such as BEM or SMACSS to keep your selectors standardized and easy to remember.

Go Forth And Extend

Bootstrap gives us an incredibly powerful set of styles – but it’s all too easy to cobble them together into something presentable at the loss of quality markup. With Sass’s @extend directive, you’re free to write markup that speaks clearly both to its contents and to the developers reading it.

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • http://www.growingwiththeweb.com/ Daniel Imms

    This doesn’t really seem to accomplish that much other than bloat your CSS file though, you could just use the very understandable bootstrap classes with the semantic elements. This is simpler as well since it’s kind of difficult to tell how <label class="author-nameLabel"> is going to be styled by looking at the markup.

    • http://www.designingsean.com Sean Ryan

      Coming as someone who works on one large app, the benefit to me is that I can eventually walk away from Bootstrap without having to scrub the DOM of Bootstrap classes. This approach means I could flip from Bootstrap to Foundation (or my own custom-built) just by focusing on changing the CSS.

      • harishchouhan

        Nice Article. Totally agree with you @designingsean:disqus. Even for smaller sites that do not even utilize much of Bootstrap, following this technique helps include only the CSS required without needing complete Boostrap styles.

        • http://hugogiraudel.com/ Hugo Giraudel

          I’m not sure it helps doing that whatsoever. No matter whether you choose to apply the class through HTML or CSS, you need the part of Boostrap that is actually defining the class.

          • harishchouhan

            Take for example mixins. If you use them or other techniques you need them for development and don’t have to include it in final product.

        • LouisLazaris

          @HugoGiraudel:disqus is right, so maybe a few people misunderstood the post. What he’s doing here is not removing unnecessary Bootstrap classes, but instead he’s extending them so that he can use more intuitive (i.e. “semantic”) and thus memorable names, to help future maintenance.

        • Brad Barrow

          Yep, the method I described in my article is intended to facilitate reusable semantic class names. It doesn’t get around having to include the framework code.

          If the framework size is something you’re concerned about, I’d recommend including only the components of Bootstrap that you need as a foundation. Then, I’d employ a method such as the one in this article to ensure that you write re-usable, modifiable classes so that you only create the bare minimum CSS for you application.

          If this is really a concern for you, then an extend-only framework would go a long way to addressing your concerns. @vinayraghu:disqus has made some progress in this direction :)

    • Brad Barrow

      Hi Daniel,

      You’re right there’s always a risk of bloating when it comes to using @extend. Used carefully however, it can actually result in less code than re-writing similar rules or outputting countless mixins because it re-uses rule sets that have already been defined.

      Regarding your point “[it's] difficult to tell how is going to be styled by looking at the markup”: HTML (at least in it’s purest form) is not meant to tell you how something looks but rather what it is, much like XML and other markup languages. Lately however, it’s being relied on to communicate page style, which is really CSS’s responsibility. That’s what the article was intending to address :)

      We all have our own way of doing things though, and if you prefer your markup to tell you how something looks then I say go for it! I’d still suggest extending bootstrap with your own classes…even if they are more descriptive and less semantic…to ensure that your site/app is still portable between frameworks.

      Thanks for your feedback :)

    • antanas

      ” This is simpler as well since it’s kind of difficult to tell how is going to be styled by looking at the markup.”

      that’s exactly why it should be like this. Markup is for data structure; CSS is for how it will look like, so you SHOULD tell how website will look like by looking only to CSS, not html.

      • http://www.growingwiththeweb.com/ Daniel Imms

        These lines can be, and always are, blurred though. I think something like .author-nameLabel is such a crazy specific style that it’s not going to be very useful compared to a more modular .fancyBox .label or something, far better and you could apply this trick to it.

        I’m not really a fan of Bootstrap, or any of these CSS frameworks for exactly this reason; styles shouldn’t be in your HTML. However, if I was using Bootstrap I’d make a conscious design decision to add the Bootstrap classes to the HTML as it will lead to a faster loading page and because Bootstrap was designed to do it this way. Trying to bend your framework so you have ‘perfect’ markup sounds like adding additional levels of complexity for very little reason, ie. over engineering.

        • Brad Barrow

          Hey @Tyriar:disqus, you’re right it’s really a matter of opinion. I think it comes down to choice. If you want to go down the path of having definitive html and descriptive css then this is the way I’d do it. If you’d rather have descriptive markup then that’s fine too :)

          I disagree about the label style being too specific however. Writing something in this fashion means it’s ready to be re-usable and it’s segregated from other instances of similar components. If instead you used something generic like “fancybox label” here and elsewhere on the site but later you wanted to change the appearance of just the author area, you cant change the fancybox style because it’s relied on by many other areas of the app. If instead, a specific style for the author extended fancybox…then you could change just the specific implemenation.

  • Brad Barrow

    That’s really cool @vinayraghu:disqus. I’ve been wondering whether either of the two framework behemoths would release a version with placeholders, looks like you’ve made a good start though. Well done

    • Vinay Raghu

      Thanks @bradbarrow:disqus I really enjoyed your article. We are pushing this forward and trying to see if we can implement it. Currently there seems to be an issue / block with @extends on libsass. But I am digging deeper. I will keep you posted!

  • Tom

    Be mindful when using @extend to strike a balance between semantic classes and class reuse — if two elements act, look, and behave similarly give them a common class. Otherwise you may come up against older IE’s stylesheet limits (http://stackoverflow.com/a/9906889) and seriously bloat your css. Don’t be afraid of using the bootstrap classes themselves.

  • Karen Menezes

    As far as I know, Sass or Less will throw an error if you have an extend inside a media query directive… It’s a big downer, IMHO, because extends are the way to go…

  • http://wellagain.lt Julija Wellagain

    Is there a way to make standard bootstrap classes silent (and then use it as @extend %col-md-4;)? This way representative classes (.col-md-4) don’t compile, and only semantic classes (.author-nameLabel) get into final css.