Semantic HTML, CSS Classes and JS Selectors
If you write any HTML, then you'll soon realise that careful choice of HTML elements and class namings will reap many a reward. The HTML document you create is an interface, an interface that is not only read by a browser to render your page to the user's screen, but also the interface in which:
- JavaScript can traverse, interact with the page and extract content to post back to the servers (AJAX).
- Drive automated & scripted web test tools - Geb Selenium
- Third parties can access content from the page and re-purpose on other web sites.
A well chosen interface will allow your HTML code to stand the test of time, be picked up and maintained by others, drive increasingly interactive JavaScript driven experiences and survive site redesigns. Below are listed a few key drivers which I follow.
Readability
Write classes with meaning
Plain Old Semantic HTML (POSH) gives us the POSH check list and helps drive some semantic HTML that I create.
- The first rule of POSH is that you must validate your POSH.
- Second, drop the use of TABLEs for purely presentation purposes, spacer GIFs, and presentation HTML in general.
- Next, fix your Bed and BReakfast markup.
- Eliminate Anorexic Anchors.
- Re-use pre-existing posh-patterns.
- Use good semantic class names.
- Choose naming that gives meaning, not naming that indicates presentation, for example, "indent", "red" and "bottom-margin" are bad choices.
Define classes for reuse
Use
<div class="event">
<div class="time">18:00</div>
</div>
instead of
<div class="event">
<div class="eventTime">18:00</div>
</div>
since this allows the class time to be used in other contexts to identify times of different items, but still allows you to pick out the event time with .event .time
Avoid obtuse acronyms and word shortenings
The following :
.checkbox.email.selected {
...;
}
.address {
...;
}
are better than
.cbem.sel {
...;
}
.addr {
...;
}
The extra characters saved by shortening the words does not make the pain for reading of code by third parties worthwhile. And, anyhow, downstream automatic optimisers could always deal with minification if it was worth while. Don't let the goal for keeping pay load to a minimum, lead to unreadability.
Reliability
Don't make your rules too specific
Be careful of using too much specificity in a CSS selector rule, e.g.
.events ul .event .time {
...;
}
Today, you may have
<section class="events">
<ul>
<li class="event">
<div class="time">18:00</div>
</li>
</ul>
</section>
but you may move it out to a ol or out of a list tomorrow. Only use the
ul in selector if you only wanted to apply the rule if it was in a
<ul>
. Also in the runtime stack this ul might be adapted to alternative
elements on another, perhaps legacy, device - so locking the style selector
unnecessarily to the <ul>
could have an adverse effect on alternative
renderings of the site.
The dangers of relative locators
Be careful with locating an element through relative traversing APIs, like parent(), prev() and next()
$(this).parents().parent().prev().show();
If you move an element slightly this logic might mis-fire. Consider locking down the rule a little, e.g.
$(this).parents(".event").find(".time").show();
i.e. go up to find the ancestor with class event and then within that find the element with class set to time. This second approach is more robust to HTML shuffles.
For example you may have a display control that displays a content item, but also provides an edit button update the content item. You might toggle between the display and update controls as follows:
// Click edit
$(".event .action.edit").click(function () {
$(this).parents(".event").find(".read-control").hide();
$(this).parents(".event").find(".update-control").show();
});
// Click save
$(".event .action.save").click(function () {
saveEvent();
$(this).parents(".event").find(".update-control").hide();
$(this).parents(".event").find(".read-control").show();
});
IDs vs classes
ids must be unique in a complete HTML page, so ensure that it is. Don't use an id on an element that is likely to be repeated or reused across a page, e.g. a date control. If in doubt, then you probably should be using a class.
Further reading
- Efficiently Rendering CSS - Golden rules on selector rules_
- Optimize browser rendering
- Good selector rules / bad selector rules*
- CSS Child Selector Performance
- Evidence that
.className
is faster thantable tr td.className\*
- Evidence that