Writing Clean Code
1st August 2004 · Last updated: 5th October 2016
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:
<p><span class="author">Chris Hester:</span>
<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.
<br />
<br /><span class="postdate">Posted on 26 July 2004 at 10:27 am. <a href="#" title="Fake link"><span class="clink">¶</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:
<p><strong>Chris Hester:</strong>
<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.
<br />
<br /><em>Posted on 26 July 2004 at 10:27 am.</em> <a href="#" title="Fake link">¶</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!
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:
p em {color:red;}
Combined tags can also be styled in a simple way:
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.)
p+p {color:green;}
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:
<div id="comments">
<p><b>Chris Hester:</b>
<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.
<br />
<br /><em>Posted on 26 July 2004 at 10:27 am.</em> <a href="#" title="Fake link">¶</a></p>
</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.
#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:
<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.
Nice!
Posted on 22nd November 2004 at 3:50 pm ¶
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">¶</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 19th December 2004 at 2:39 am ¶