Writing Semantic Markup

Joshua Ogle

The history of front-end development is not a short one as computer history goes, but it wasn’t until recently that it has started to get the tools and attention it deserves. Writing markup was mostly ignored as being both cumbersome and yet simplistic. The practice of crafting “the view layer” is more enjoyable and exciting now than it ever has been and it is giving us better user experiences.

Traditionally, most layout in HTML has been done with only a handful of tags:

  • <table> : Misused for years to get around the shortcomings of CSS layouts, the backlash against them has led some designers to stop using them altogether. Tabular data belongs in tables. Don’t be afraid to use them.

  • <div> : This is the catch-all element and used as a default when other tags won’t do.

  • <span> : Similar to div, but this is an inline-level element useful for text.

As you can imagine, these few elements don’t give us a lot of differentiation and don’t reflect the structure of the application and the purpose of their parts. They do get the job done, but it could be better.

HTML5 to the rescue

In 2014, HTML5 brought us a cornucopia of new tags that help make it easier to differentiate content and to create meaningful relationships between elements.

In all there are 25 new elements, but these are the elements for layout and will be the most common that you will come across.

  • <main> : Wraps around your main content. This tag often goes unused by designers, but is especially helpful for single-page applications that replace content.

  • <article> : Specifies self-contained content, such as a blog articles.

  • <section> : Pieces of content such as chapters, or even just areas of content that are broken up visually.

  • <header> : Introductory content. Might be a masthead with a logo and navigational links or even used inside a small piece of content.

  • <footer> : Contains information about the containing element, such as meta data for a blog post or as a site footer.

  • <nav> : Contains navigational links.

  • <aside> : Content related to the main content but in an area like a sidebar or suggested content. Side navigation should instead use the nav element.

  • <figure> and <figcaption> : Contains media like illustrations and photos. The figcaption tag is nested inside figure to give additional information.

These tags are meant to be meaningful but also flexible in their usage. You may notice that the definitions of these elements are somewhat vague, and that is intentional. They don’t have any inherent styles of their own and can be used in any combination that makes sense to you. These elements have great browser support, but you may need a polyfill to enable support in older browsers (such as Internet Explorer 8 and below).

To get an idea of how this looks in practice, let’s look at a few examples.

  1. A blog article can use a header and footer to separate the title and meta information from the post itself.
<main class="content">
  <article class="post">
    <header>
      <h2 class="title">Article Title</h2>
      <time datetime="2015-01-30 13:00">Jan 30th</time>
    </header>
    <section>
      <h3>Section Title</h3>
      <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
        eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut
        enim ad minim veniam, quis nostrud exercitation ullamco laboris
        nisi ut aliquip ex ea commodo consequat.</p>
    </section>
    <section>
      <h3>Section Title</h3>
      <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
        eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut
        enim ad minim veniam, quis nostrud exercitation ullamco laboris
        nisi ut aliquip ex ea commodo consequat.</p>
    </section>
    <footer>
      <span class="post-comments" data-show="#comments">24 comments</span>
    </footer>
  </article>
</main>
  1. A header can provide clear navigation links in a nav tag.
<header class="site-header">
  <a href="/" class="logo">Logo</a>
  <nav>
    <ul>
      <li>
        <a href="/register">Register</a>
      </li>
      <li>
        <a href="/login">Log In</a>
      </li>
    </ul>
  </nav>
</header>
  1. These elements can be nested. this is especially helpful for section tags.
<section>
  <h1>Pangolins</h1>

  <section>
    <h2>Habitat</h2>
    <p>Pangolins live in two regions: Southern Africa and South-East Asia</p>
  </section>

  <section>
    <h2>Diet</h2>
    <p>They are insectivorous, mainly eating ants and termites.</p>
  </section>

  <section>
    <h2>Conservation</h2>
    <p>Pangolins are endangered and protected under international laws.</p>
  </section>
</section>
  1. Headers and footers can be used for global elements and also inside other elements.
<header class="site-header">
  <a href="/" class="logo">Logo</a>
</header>
<main class="content">
  <article>
    <header>
      <h1>The Robot Uprising and You</h1>
    </header>
    <section>
      <p>
        ...
      </p>
    </section>
    <footer>
      Posted by Ralph Bot on August 29th
    </footer>
  </article>
</main>
<footer class="site-footer">
  &copy; 2015 Businesscorp
</footer>

Inline and block-level elements

We should take a moment to talk about the difference between block-level and inline-level elements. Inline-level elements are used for text and will not (by default) add a line break before and after. These are tags like <a>, <strong>, and <img>. Block-level elements are your more typical layout tags like <div>, <header> and <h1>. Each can be styled like the other by using the display property in your styles.

a {
  display: block;
}

There is also a hybrid between the two called inline-block. This will cause the element to remain inline, but accept things like top and bottom padding. In some situations, this is a simpler approach than using floats and can be very helpful when aligning elements with text.

img {
  display: inline-block;
  vertical-align: middle;
}