Using Bootstrap the Right (Semantic) Way

Back in the year 2000, when I first started learning web development, tables were my best friend.

The web was filled with <tr> and <td> and semantics were non-existent. Images were broken down and placed in bits & pieces inside different table cells.

Things changed in mid-2003 when I came across a site This site showcased the new and the right way of doing things, which was to separate content & presentation. After all, that is the reason CSS was created in the first place.

Here’s how HTML was written in 2000. Nothing in this code is semantic or meaningful:


Changes since 2000

Since that time, a lot has changed. Web standards have evolved by focusing on accessibility and semantics. With importance given to page speed by search engines and increase in mobile usage, everyone’s focus is now on a website’s responsiveness and speed. Due to the number of different devices and browsers in use, the time required to develop and test even a basic site has gone up.

Our response to those changes is often a CSS framework

If you develop websites in 2014, there’s a good chance that you have a favourite CSS framework and you have probably tried several. My personal favorite is Bootstrap.

For front-end developers, creating a prototype or an end product has never been easier thanks to these frameworks. By simply including a CSS and a JavaScript file in your project, you now have access to a number of different components such as responsive navigation menu, tabs and carousels. But, are frameworks sending us back in time?

Framework divs are often still not semantic

If you view the source of many sites created using these frameworks, you are more likely to feel that we simply have replaced <tr> and <td> with something like <div class=”row”> & <div class=”col-sm”>.

This is still not good semantic markup.

And now, if the folks at Bootstrap decided to change the class names, and you wish to update your site, then you are very likely to spend a lot of time modifying your HTML again.

Fortunately, the solution is right within Bootstrap itself.

The semantic solution is Mixins

Thanks to CSS pre-processors like LESS and SASS you don’t have to look anywhere else. Using “Mixins” you can create a semantic HTML structure with meaningful class names. With Mixins you can also arrange your content in different columns without stuffing your site with unnecessary divs to structure rows and columns.

Assuming everyone reading is aware of the 12-column Bootstrap grid, let’s discuss a scenario where our website structure looks like this image below:


If we were to use default Bootstrap classes, the HTML structure to arrange our content would be something like this:

<div class=”container”>

    <div class=”row”>

        <div class=”column-md-8″>

            Content – Main


        <div class=”column-md-4″>

            Content – Secondary





So similar to the old days, we seem to have simply removed tables and replaced them with div tags.

To avoid writing code that feels like it’s still the year 2000, we can modify the above code to make it more semantic and leaner. Here’s a better version of the code above:

<div class=”wrapper”>

    <div class=”content-main”>

         Content – Main


    <div class=”content-secondary”>

        Content – Secondary




Due to the size of this code, the reduction of div tags might feel insignificant, but assuming the content on today’s website, it starts piling up.

Structuring the code with Mixins

To now structure the above content using “Mixins” you need create a .less file

In that file, include the bootstrap’s variables.less & mixins.less files followed by the code below:

// Core variables and mixins

@import “variables.less”;

@import “mixins.less”;

.wrapper {



.content-main {



.content-secondary {




Finally, use a compiler to convert your new .less file into a CSS file.

You could also add mixins to offset columns or push and pull them, similar to using classes such as .col-md-push-2.

Check the Bootstrap LESS grid guide or open the mixins.less to see the available mixins.

Now in the future, if you decide to change the CSS framework used in your website or if bootstrap changes its class names, you only need to edit your LESS files and nothing else.


  • Steve Burge

    Steve is the founder of OSTraining. Originally from the UK, he now lives in Sarasota in the USA. Steve's work straddles the line between teaching and web development.

0 0 votes
Blog Rating
Notify of
Newest Most Voted
Inline Feedbacks
View all comments
Hugo Firth

This is one of the main reasons I like AngularJS directives. If used properly (huge caveat) they allow your template markup to take on far more semantic meaning.
I also agree with the idea that we should use Mixins to allow for more semantic meaning in our plain HTML. As an added bonus, this can make things a lot more maintainable down the road.


AngularJS is very bad tool because it breaks Progressive Enhancement, with AngularJS you mix HTML with JS or even CSS and this is not good…

Matheus Araujo

If you need progressive enhancement there’s no JavaScript framework you can use. AngularJS is made for web apps and only supports modern browsers (IE9+).
Also, if HTML, CSS and JS are mixed, it’s not the framework that is not good, it’s the developer. AngularJS doesn’t force you to do that and they actually have guidelines suggesting exactly the opposite.


Progressive enhancement just does not make sense for web apps. You wouldn’t use AngularJS for content-rich sites. You might want to use it, however, for a web-based CRM, or perhaps a dashboard. That’s when Angular makes sense.
And, frankly, if my userbase is below IE9 then I don’t care to support them. Long live web standards.

Lars Jeppesen

Really? I just implemented a full website using AngularJS and Drupal8 as a backend (using it only as content management, giving access to content via a Rest API). I would say Angular is super super for content-rich sites.


The main concern is SEO, which is where Angular lacks. I’m not saying you can’t create a content rich site with Angular, but you have to compensate for SEO by using this escaped fragment wizardry.
All said and done, though, Angular2 will solve this issue.

Lars Jeppesen

First: NG2 rocks – totally rocks!

Second: Google can now crawl Angular sites – in fact they now discourage the use of _escape_fragment for their crawler. We have only had some issues with dynamically updated meta tags – but that is solveable as well. Try to remove the escaped fragment meta tag and you should be good.
My site is [url=][/url] fyi


I may be reading something incorrectly, but doesn’t your second example (the one using mixins) lose the functionality of the ? I’m all for getting rid of extraneous divs, but I think you’re losing some functionality here in the process.

Shane P.

First thing I noticed as well. You’re right. Basically moving the “row” up one level in the DOM. The CSS needed for both examples would be structured differently.

Amadeo DeSouza

yea, this is confusing. We still need a container which is also a wrapper just at a higher level.

Stephen Bateman

Posted this on Hacker News, but here’s a LESS mixin that will make this easy to actually do:
.make-column(@large, @medium, @small, @tiny: 16) {





Then use it with: section#main-content { .make-column(8,8,9,12); }


Thanks for sharing Stephen. Great mixin example.

Sam Vanstechelman

Hello Stephen why are you using @tiny: 16 as ure primary value ? shouldn’t that be 12 ?

Stephen Bateman

This was 2 years ago, but I think we were using a 16 column grid.

Andrew Luca

Good mixin, but if we look into compiled CSS we have on the same selector duplicated, paddings, position, min-height for each size
position: relative;

float: left;

width: 100%;

min-height: 1px;

padding-left: 15px;

padding-right: 15px;

position: relative;

min-height: 1px;

padding-left: 15px;

padding-right: 15px;

position: relative;

min-height: 1px;

padding-left: 15px;

padding-right: 15px;


Web Components, bro


This! Very much this 🙂

Fatih Kadir AKIN

Love the post. You are completely right. We tried to bring the HTML into cleaner and more semantical, but Bootstrap screwed it up with their representional classes.


Well Bootstrap makes it easy but it also provides the necessary tools to still make a site with semantic HTML structure.


To me theres not much difference between those examples. Go all the way and make the HTML code meaningful to screen readers also: [url=]…[/url]. Win win!


Does anyone know if mixins similar to these are available for the latest version of Foundation?

Scott Grodberg

That totally helps from a development standpoint. But if you wanted a more semantic document, couldn’t you replace the column divs with specific block elements? Paragraphs, lists, sections, and articles come to mind!

Harish Narayanan

Yes, but that would require much more surgery than the method discussed in this article.

Grab offers

nice information thanks for sharing…..

[url=]Bluestone Coupons[/url]

Renee Thomas

Isn’t it possible to use the html5 tags (ie. , , , etc.) with the bootstrap classes inside? This would keep the site semantically correct right? I tried it here at work and so far it seems to be working.

Jegan Chandran

nice post):)

Devin Walker

The comparison to the old web way, and how if we aren’t using more semantic markup, is a beautiful way to express your point: mixins can really help clean up the code structure. Really enjoyed reading this article.


What no one seems to reference with any of these Bootstrap mixins and class extends is how to properly handle the .container which is normally attached at the root container of the page. Simply using @extend .container(); does not cut it. 🙁


Hello Guys we, have used semanitc less in my website with bootstrap
When i checked in gtmetrix, i’ve found “charset has eariler” error & its a http request error.
Anybody know how can i resolve this issue help us guys
[url=][/url] our website

Ashu M

just use


and so on…

Would love your thoughts, please comment.x