CodeinWP CodeinWP

Targeting HTML5’s Semantic Elements with CSS

It would seem that with the introduction of HTML5’s semantic elements, styling those new elements should be an easier task. But as I’ve started to use HTML5 more, I’ve realized that it takes quite a bit of forethought to create maintainable CSS that targets the new semantic elements in a future-proof way.

In some cases, it could be fairly straightforward, but in others it’s a little disheartening because targeting the new elements actually creates more verbose markup.

Let’s consider a few examples. If you had a page that used the <header> element to hold the logo, nav, etc, and the <footer> element to hold the website’s footer, then your CSS would look something like this:

header {
  width: 980px;
  background: hotpink;
  border: solid 1px #ccc;
}

footer {
  width: 980px;
  clear: both;
  font-size: 10px;
}

As you can see, that’s pretty clean, easy to read, and easy to maintain. But the <header> and <footer> elements are not just reserved for “website header” and ‘website footer”; you are also permitted to use them as headers and footers for any element that creates a new section, referred to as “sectioning content”.

So, if you used <header> and <footer> for individual articles on a single page, then the styles shown above would obviously apply to all the headers and footers on the page.

Because of this, it’s then necessary to do one of two things. You’ll have to either (1) add a class or ID to every header and footer on the page, or (2) target your headers and footers based on context.

So in your HTML, you’d have to do something like this for the main header/footer for the site:

<header id="main-h">
<p>Heading content...</p>
</header>

<footer id="main-f">
<p>Footer content...</p>
</footer>

Then maybe do something like this for the headers and/or footers that appear in other areas on the same page:

<header class="secondary-h">
<p>Secondary header content...</p>
</header>

<header class="secondary-f">
<p>Secondary footer content...</p>
</header>

Or you could just target the secondary headers/footers contextually using the descendant selector, like this:

article header, section header {
  width: 540px;
  background: hotpink;
  border: solid 1px #ccc;
}

article footer, section footer {
  width: 550px;
  clear: both;
  font-size: 10px;
}

And of course, if you had even further use of a header/footer combo in a sidebar widget or something, then you’d need yet another target for that one. I did something along these lines in my HTML5 template, which actually has quite a bit of example content that shows how the new elements can be used.

Update: As people have mentioned in the comments, in many cases, using the child selector may be the best way to go to target the new elements and keep your HTML clean. As I mentioned a couple of times in the article, you can target the new elements based on the context (using various CSS selectors); I just didn’t specify all the different ways to do that. Personally, I feel it’s safer to use classes and/or IDs because IE6 does not support the child selector and IE7 has some bugs when using it. But naturally, for many projects it would be best to use it because it certainly is future-proof and keeps your code clean. I definitely should have given that more prominence in discussing this topic, but I felt that it’s probably best to use the safest method instead.

Isn’t This Old News?

Of course, this is nothing new for any CSS developer. So why am I bringing this up?

Well, normally when we consider styling for generic elements (like <div> or <span>), we will automatically add the class or ID to ensure that we’re going to be able to target the element. Or else we’ll use a more specific CSS selector to do this (although the latter is not as performance-beneficial).

But with truly semantic elements like <header> and <footer>, we may quickly assume it’s okay to just target the element without a class/ID or specialized CSS selector. We often do this with stuff like <blockquote>, <p>, <cite>, and many others–we style the elements directly to ensure consistency across the site. But this doesn’t always work for the new semantic elements.

So, to ensure your code is future-proofed for later additions, it’s good to get in the habit of adding class names and/or IDs to all your headers, footers, sections, articles, hgroups, etc. Or else be prepared to target based on context, rather than just using the element type selector. Object-oriented CSS principles might also help.

What are your thoughts? Do you think it’s useful to always add classes or IDs to the new semantic elements? How do you target the new semantic elements to ensure future-proofing?

15 Responses

  1. Great little article you wrote up here Louis, I’m currently in the process of redesigning my website with some of the new HTML5 features and this has helped a bit.

  2. Sam Bowler says:

    I like to use body > header and body > footer to specifically target the root header and footer. Adding classes just seems a bit “messy” semantically to me!

    Nice article nevertheless.

    • Yes, absolutely, I agree. I didn’t mention the child selector specifically, but I did mention “targeting based on context”, which can be done using the > selector.

      But, as usual, there are drawbacks to using that, depending on the project. The child selector doesn’t work in IE6. Don’t care about IE6? That’s fine, but it is a bit buggy in IE7 as well. My problem is that I don’t like advocating methods that fail in some browsers when you can easily use another method instead.

      It would be nice if something like Selectivzr resolved this problem for IE6/7, then we could use it more confidently. But unfortunately, many developers in certain parts of the world still face huge numbers of users on IE6. And something like this is not going to degrade gracefully, it will break your entire website for those users, so it’s a little more serious than seeing missing rounded corners or something.

      Anyhow, I think I’ll put a note in the article to mention the possibility of using the child selector if developers are not concerned with IE6 support.

  3. I have to agree with Sam – one of the benefits of HTML5 is to finally be free of all those functional ids for all the divs we used. Using proper selectors makes the structure of the HTML document obvious in the CSS (wow, we can eliminate some unnecessary commenting as well).

  4. Tim Davis says:

    I agree with Sam, all your doing is <header id=”header”>… Target the first header inside body and first footer inside body, “>” FTW!

  5. Johan Brook says:

    A great way to ensure you're targeting the correct header/footer/section is to make use of ARIA roles (http://www.google.se/search?sourceid=chrome&ie=UTF-8&q=aria+roles).

    The main ones I use is <code>banner</code>, <code>main</code>, <code>navigation</code> and <code>contentinfo</code>:

    <pre><code><header role="banner">
    // Stuff
    </header>

    <section role="main">
    // Content
    </section>

    <footer role="contentinfo">
    // Stuff
    </footer></code></pre>

    In the CSS:

    <pre><code>section[role="main"]{
    // Styles
    }

    header[role="banner"]{
    // Styles
    }</code></pre>

    So now we don't have to deal with unnecessary ID and class attributes.

  6. Ferdy says:

    Great suggestion @Sam, your suggestion basically solves the problem the author describes.

    On a side note, I once read that a CSS property is on its way that basically disables inheritance for that selector. Forgot what its named. That would solve it too.

  7. Chris says:

    A little ironic, that “You might also like” under this post links to your own article, http://www.impressivewebs.com/cleaner-html-by-avoiding-attributitis/ – where you’re advocating against making everything messy using too many class- and id-attributes (and rightly so).

    To me, more specific selectors are preferable (most of the time).
    They are not “hurting” performance as bad as some people want to make you believe – as long as you keep them reasonable, and don’t start creating “selector monsters”.

    • Chris, that is a very old article that was written long before HTML5 became a reality. :)

      In some niches, due to high numbers on IE6 and IE7, if developers are going to use HTML5, then they may have to use classes and IDs as opposed to the child selector.

      But, as I mentioned in the article, I have no problem with targeting based on context, as opposed to adding classes and IDs. I just personally feel that IDs and classes are safer for all types of projects.

  8. neha sharma says:

    HTML5 is good to see and work but however I am concern for the IE users..as my major audience is coming from the IE browser so keeping that in mind I cant ignore the IE and have to compromise with the HTML5 and css3 : (

  9. Chris says:

    Am exploring what HTML5 has to offer all the time. I suppose there are some advantages that can be gained with the semantic elements. Through application in real practice is where this is discovered, as always. Appreciate the articles here, btw.

  10. Anders Te says:

    I attended a seminar about HTML 5 a couple of days ago and even though I think there is many intersting features about this technique, many of those whom I spoke to thought that there was a bit of a hype surrounding HTML 5.

  11. Dhruv Thaker says:

    Thanks for the tutorial. This will help in creating site structure using HTML5 and CSS3.

Leave a Reply

Comment Rules: Please use a real name or alias. Keywords are not allowed in the "name" field and deep URLs are not allowed in the "Website" field. If you use keywords or deep URLs, your comment or URL will be removed. No foul language, please. Thank you for cooperating.

Markdown in use! Use `backticks` for inline code snippets and triple backticks at start and end for code blocks. You can also indent a code block four spaces. And no need to escape HTML, just type it correctly but make sure it's inside code delimeters (backticks or triple backticks).