When people talk about semantic code, particularly with HTML they usually refer to using tags that explain what an element is supposed to be. For example you could do <div class="header"></div> or you could use <header></header>. The advantages of using the correct tags is obvious, and that’s not what I’m going to cover here. There are plenty of blog posts that cover that already.

What I’m going to talk about is how you write your classes for your HTML elements (which in turn will affect your CSS, more on that later)

Telling a story with your HTML is about explaining what an element is, rather than what it looks like, or what it does. It may help you to think of your HTML as objects, and individual elements as parts of that object. For example if you were building a car object you’d define that the car has wheels, seats, steering wheel etc, rather than defining that the car has 4 things that are black and round.

When you need to update the HTML/CSS of a component, you will typically be changing how it looks, rather than changing what it does. If you’re changing what a components HTML/CSS does, you’re almost always better off starting again. For example, if you had some HTML with classes like this: <div class="blueBorder"></div> and you need to change this element to have a red border, the class no longer makes any sense, and you need to update both the HTML and the CSS - and who knows where else that class might be used.

Writing a story with your HTML is especially nice when you’re using a preprocessor like Haml/Slim/Jade. An example of how I might write something:

.report
  .customers
    .customer
      .details
        .reference
        .name
        .email

      .orders
        .order
          .reference
          .created-at
          .products
            .product
              .name
              .quantity

When you write your HTML like this, your CSS will typically follow suit, and it will make your CSS semantic.

While I’m an advocate for telling a story with your HTML, there are techniques to giving fewer elements class names, while staying semantic. And example of this would be if you were building a hero with a heading title and sub text, and some bottom text, you could build it like this:

  <div class="hero">
    <header>
      <h1></h1>
      <h2></h2>
    </header>
    <footer>
      <p></p>
    </footer>
  </div>

rather than building it like

  <div class="hero">
    <div class="top">
      <div class="main-title"></div>
      <div class="sub-title"></div>
    </div>
    <div class="bottom">
      <div class="strapline"></div>
    </div>
  </div>

While having the class names makes it more obvious what everything is, using semantic tags works nicely in generic components like this.

Telling a story with your HTML lends itself better to OOCSS than flat CSS. I’ve written a whole series on OOCSS methodologies that I recommend you check out. In the example above, you could write the CSS like this:

  .hero
    header
      h1
      h2
    footer
      p

As you can see, the base structure of this matches the markup pretty much exactly. When fleshing this out, this the structure will be less visible - but having it match the markup will help massively when coming back to the code and/or if someone else comes to work on this code.

A hugely popular CSS methodology that unintentionally promotes non semantic HTML is ACSS (Bootstrap/foundation etc). The methodology uses small classes that define a single thing, usually named as to what they make something look like. Using these classes in your HTML makes it hard for another developer to understand what the element is supposed to be, for example which one of these looks more obviously like a navigation element? <div class="col-xs-12 bg-primary pull-left"></div> <div class="navigation"></div> The first option could literally be anything.

This also touches on another benefits of writing your HTML as story - you or any other developer working on your code will be able to look at your HTML and understand what it might look like without having to cross check the classes against CSS.

ACSS can absolutely be used in semantic HTML however, by extending and including them as mixins. To do this, you just write your semantic HTML, and include the classes in your own CSS.

You may be wondering - how do I do this, and how do I go about adding semantic markup to a existing code that is un-semantic?

My biggest preference is to port as much of the existing code over to being modular and semantic as possible, while leaving the existing stuff mostly in tact. Doing this with something written in bootstrap is really easy, for example this login form:

<form class="form-horizontal">
  <div class="form-group">
    <label for="email" class="col-sm-2 control-label">Email</label>
    <div class="col-sm-10">
      <input type="email" class="form-control" id="email" placeholder="Email">
    </div>
  </div>
  <div class="form-group">
    <label for="password" class="col-sm-2 control-label">Password</label>
    <div class="col-sm-10">
      <input type="password" class="form-control" id="password" placeholder="Password">
    </div>
  </div>
  <div class="form-group">
    <div class="col-sm-offset-2 col-sm-10">
      <div class="checkbox">
        <label>
          <input type="checkbox"> Remember me
        </label>
      </div>
    </div>
  </div>
  <div class="form-group">
    <div class="col-sm-offset-2 col-sm-10">
      <button type="submit" class="btn btn-default">Sign in</button>
    </div>
  </div>
</form>

You could change to be like this:

<form class="login">
  <div class="question">
    <label for="email">Email</label>
    <div class="answer">
      <input type="email" id="email" placeholder="Email">
    </div>
  </div>
  <div class="question">
    <label for="password">Password</label>
    <div class="answer">
      <input type="password" id="password" placeholder="Password">
    </div>
  </div>
  <div class="question">
    <div class="answer">
      <label>
        <input type="checkbox"> Remember me
      </label>
    </div>
  </div>
  <div class="action">
    <button type="submit">Sign in</button>
  </div>
</form>

And then your CSS module would look like this:

@mixin login-form
  .question
    @extend .form-group;

    label
      @include make-sm-column(2);
      @extend .control-label;

    .answer
      @include make-sm-column(2);

      input
        @extend .form-control;

  .action
    button
      @extend .btn;
      @extend .btn-default;

.login
  @include login-form  

Writing a story with your HTML naturally is tricky, and it takes practise being able to write it as if you’re just typing out a story in English. If you would like an exercise to get better at this, I find writing your HTML for a component out in full without ever looking at the page rendered in the browser will help you think about the semantics of your code before actually thinking of how it is supposed to look. Also start by writing out everything as a class, and then you can go back and change things to be specific tags without classes.

Hopefully this gives you a good idea why writing a story with your HTML is awesome. While mostly just give the benefits of semantic HTML for collaborative environments, it’s still a nice practices to follow if you are the only developer working on your code - when you come back in the future you can easily read what you were building without having to look at CSS.