Writing Clean Code

1 August 2004 · Last updated: 11 December 2006

Comments


Forget span tags with classes. Here's how to write clean, efficient and simple HTML. Consider the following example of text you might wish to mark up. It is based on a recent comment I made on this site.

Chris Hester:
D'oh! It was all so simple in the end. To get a consistent zoom across nearly all elements, just style the body tag! No need to separately style different elements! This also restores list bullets.

Posted on 26 July 2004 at 10:27 am.

So what's the deal? Well normally I would have littered this code with spans and classes to style each bit separately from the rest of the page. So there would be a class for the first line ("Chris Hester"), a class for the post date on the last line, maybe even a class for the link. It would come out looking something like this:

  1. <p><span class="author">Chris Hester:</span>
  2. <br />D'oh! It was all so simple in the end. To get a <strong>consistent</strong> zoom across <em>nearly</em> all elements, just style the <strong><em>body</em></strong> tag! No need to separately style different elements! This also restores list bullets.
  3. <br />
  4. <br /><span class="postdate">Posted on 26 July 2004 at 10:27 am. <a href="#" title="Fake link"><span class="clink">&#182;</span></a></span></p>

Yeuch. Too many span tags and classes. But what happens when styles fail to load, or the user deliberately toggles them off? I recently had a revelation: I would aim to make the unstyled text appear as close to the styled text as possible. How? Simply by using the closest tags, so the meaning of the text was not lost. By doing so, I also managed to come up with a way to get rid of all those spans and classes. Allow me to explain.

Let's say styles are turned off in the above example markup. What happens? Firstly, the author of the example comment is styled in bold via the class "author". But that doesn't work without styles. So we're left with a line of plain unboldened text. Say I'd used a header tag instead and removed the line-space beneath it, making it smaller in font-size. I tried that – when the styles were turned off, it ruined the effect I was trying to achieve.

The same problem occurs with the last line which has the post date details on it. Because a class is used (also for the link) the style information is simply lost when styles are turned off. I didn't want to see just lines of plain text, where contrast between sections was removed, where the user would feel confused and frustrated.

No more confusion. By using tags that give a similar style to that seen when a stylesheet is used, you can strip out all the spans. The resulting code is much cleaner:

  1. <p><strong>Chris Hester:</strong>
  2. <br />D'oh! It was all so simple in the end. To get a <strong>consistent</strong> zoom across <em>nearly</em> all elements, just style the <strong><em>body</em></strong> tag! This also restores list bullets.
  3. <br />
  4. <br /><em>Posted on 26 July 2004 at 10:27 am.</em> <a href="#" title="Fake link">&#182;</a></p>

Now this also makes for code that's far easier to read through. But how do you style it now, you ask? It's dead easy – just use the order of the tags. Here, we've got a paragraph followed by a bold piece of text. This is all the style you need below – no spans or classes!

  1. p strong {color:blue;}

So wherever there's a paragraph followed by the <strong> tag, no matter how many times it tag appears in the paragraph, it'll be styled blue. It's already bold by default, so when styles are turned off, only the colour is lost.

We can style the last line in the same way:

  1. p em {color:red;}

Combined tags can also be styled in a simple way:

  1. p strong em {color:purple;}

Here's the code so far – try it out yourself. Use the link I've put in to toggle styles. (Note: In the Opera browser you can toggle styles on and off quite easily if you have the Author/User Mode button on your toolbar.)

If you have a group of paragraphs and only want to style certain ones, you can also make use of selectors. The first line in the code below styles all paragraphs that follow a paragraph. This provides a neat way of not styling the first paragraph. The second line of code avoids the first two paragraphs. (This technique is also very handy for styling lists.)

  1. p+p {color:green;}
  2. p+p+p {color:maroon;}

The Literary Moose has written a handy guide that explains all about selectors: CSS Selectors: a Visual Guide for Absolute Beginners. The only problem with using them is this: They don't work in Internet Explorer 6 or below. A pity – they are brilliantly useful.

Even without selectors, just using basic tags in a clear way allows you to style your page with ease. But what happens when you want to style a tag in one part of your page, but not the rest? This is where the true power of this technique comes into play. The <div> tag allows part of a page to be set as a 'division'. Layouts already tend to use this for columns and headers etc, so what better to define an area where you want only certain styles to work? (You don't have to make a division a separate part of the page – it can be a set of paragraphs, or anything you want, so long as it's a block. (Eg: an area separated by line-breaks.) If you want to style part of a line or existing block, then use the <span> tag.)

The reason for using <div> is to add an ID or a class to it. (An ID is used for elements that only occur once, such as a footer. Classes are used when the element may occur many times.) Now we can style only the tags that appear within the <div>. So the HTML might be written like this:

  1. <div id="comments">
  2. <p><b>Chris Hester:</b>
  3. <br />D'oh! It was all so simple in the end. To get a <strong>consistent</strong> zoom across <em>nearly</em> all elements, just style the <strong><em>body</em></strong> tag! This also restores list bullets.
  4. <br />
  5. <br /><em>Posted on 26 July 2004 at 10:27 am.</em> <a href="#" title="Fake link">&#182;</a></p>
  6. </div>

All that's needed next is to add the ID name into the styles, and they won't affect the rest of the page. Use a '#' to refer to an ID name, and a '.' to refer to a class.

  1. #comments em {color:red;}

If you only have one paragraph in the section you want styling, you can do without the <div> altogether – just add the ID or class to the paragraph tag itself:

  1. <p id="comments"><strong>Chris Hester:</strong>

You can go one further and add an ID or class to the whole page by using the <body> tag. This allows you to keep using just one stylesheet, yet give completely different styles to each page.

If there's a cleaner way to write code – well I've yet to see it. The above method allows you to strip out masses of unnecessary span tags, saving many bytes on a large page. It also means that when you come to restyle the page, you shouldn't have to change much more than the stylesheet.


Comments (2)

Comments are locked on this topic. Thanks to everyone who posted a comment.

  1. yah:
    Nice!

    Posted on 22 November 2004 at 3:50 pm
  2. Zach Blume:
    How about:
    1. <h1>Comments</h1>
    2. <div id="comments">
    3. <h2>Chris Hester</h2>
    4. <p class="normal">D'oh! It was all so simple in the end. To get a <strong>consistent</strong> zoom across <em>nearly</em> all elements, just style the <strong><em>body</em></strong> tag! This also restores list bullets.</p>
    5. <p class="footer"><em>Posted on 26 July 2004 at 10:27 am.</em> <a href="#" title="Fake link">&#182;</a></p>
    6. </div>

    You see I used classes....well, they're fine when you use them correctly, as I did.

    CSS:
    1. h2:after(content:":";}
    2. p strong, h2 {color:blue;}
    3. p em {color:red;}
    4. p strong em {color:purple;}

    A sad thing is that IE does not support the :after, :before phsudo-elements or the content attribute. So you'll have to stick with using a colon in the actual (X)HTML.

    Now if you wanted to get rid of the space between the first and second paragraph:
    1. #comments.normal {margin-bottom:0;padding-bottom:0;}
    2. #comments.footer {margin-top:0;padding-top:0;}

    Tada!

    Posted on 19 December 2004 at 2:39 am

Useful Info

EMAIL: www.designdetector.com (replace the 1st dot with "@")

NEWSFEED: Subscribe to news of fresh posts and site updates. (RSS 2.0 compatible newsreader required.)

Disclaimer

Some links on this website lead to information provided by external services not under my control, therefore I am not responsible for the content or accuracy of the linked information.

All code examples are not guaranteed 100% free from bugs and/or mistakes. Use them at your own risk. I do not take any blame should a problem occur relating to use of code on this site given as an example for your own use. Such code has been tested and found to work for me, but I cannot vouch for other computer systems (existing now, or in the future) which it may be used on, or changes you introduce yourself based on my code.

This website is © 2008 Christopher Hester, except where separate authors are named. No part of this website may be reproduced or re-used in any way without my prior permission, except content added from separate authors (who retain the copyright on their material), examples of code, and any other content I explicity state is free to copy and make use of.

This page was last updated on 11 December 2006.

What's New

Recent Finds


View previous finds


Current Reading

book cover Digital Photographer's Handbook by Tom Ang
70%
book cover Barefaced Lies and Boogie-Woogie Boasts by Jools Holland
100%
book cover The Brutal Art by Jesse Kellerman
100%
book cover Frothy Tales by Davey Spens
100%
book cover The Suspicions Of Mr Whicher (Or The Murder At Road Hill House) by Kate Summerscale
100%
book cover Genesis: Chapter & Verse by Tony Banks, Phil Collins, Peter Gabriel, Steve Hackett & Mike Rutherford
100%