css type selectors/designing the semantic web
published on:July 18, 2008 / 11:43
back to overviewhtml and css are closely connected, no doubt about that. When we style a web document we do it through the mark-up of the document. It's one of the pillars of modern web design and we all take it for granted. But take a closer look and you'll find that this way of working isn't always as logical as it sounds. This article will focus on the way html and css coexist and the effect this should have on the way we write our css.
avoiding inconsistencies
When people start off writing css the results are often pretty chaotic. Starters focus on making things work, which leaves css files badly structured and littered with inconsistencies. It was like that for me too. But the more I learned about css, the more I saw the need to avoid these inconsistencies and to optimize my way of writing css.
Of course, there is no one way to write css, so from time to time I had to decide which choices would be most beneficial in the long run. One particular problem had me puzzled for quite some time and it wasn't until recently that I found some good arguments to base my decision on.
/* css selector with type selector */
ol.breadcrumb
/* css selector without type selector */
.breadcrumb
When looking into the way I composed my css selectors I asked myself whether it would be useful to include the type selector to a class selector. The little piece of code above illustrates the decision I was trying to make. The choice is easy when a class selector can appear on multiple html elements, but what if the class was unique to one html element?
coming up with arguments
There are things to be said about both ways of working. For one, if you leave the type selector off it will decrease the length of your selector which improves the readability of your css file, especially when many selectors are stringed together. Less scrolling sideways is a good thing. On the other hand, adding the type selector does give you extra information on the class and might make it easier to recognize elements as you got the html element to help you out.
A more important argument popped up when I was revising our deliverables (our company only does front-end, so we deliver templates to be implemented by partners). Adding the type selector locks the
css to the html code. By doing this, you create an extra checkpoint for people to implement the templates you deliver. If, for example, they used an <ul> element to
mark up the breadcrumb it wouldn't be styled and they would know there was something wrong with the implementation. The argument was good enough for me and I started to include the type selector.
flexibility, the magic word
This went well for a while, but soon I also started to notice the drawbacks of locking css to html. I became more aware of the semantic meaning of some html elements and as I read through
several discussions I saw the need to change a few things. One of those things was the breadcrumb, which I changed from an <ul> to an
<ol>. When I did that, all the css styling dropped off even though the component itself hadn't really changed. Not a good thing.
It may not seem very likely for things like this to pop up often, but with html5 and xhtml2 in the pipeline I wouldn't be surprised if quite a few html implementations will change over time. And when that happens, it would be nice to simply change the html templates without having to touch the css. So flexibility became my key argument for leaving the type selector off, but something still didn't feel quite right.
the theory
If you really think about applying css to html on a very basic level, it doesn't make too much sense. html might be is a semantic language, but at the same time it's very generic. Of course
we can add styles and layout to a paragraph, but most mark-up elements are too generic to really tell us anything about the actual component we're styling (think of everything marked up with a
<div>).
Going back to our breadcrumb, you'll see that I've used a list to implement it. But a breadcrumb is a pretty specific implementation of a list, which is in itself a very generic term. As a matter of fact, the most important semantic information in this case comes from the class we added on the list (the microformats principal). The reason why we use the list element is because we don't have any better, more semantic ways to implement our component.
Whenever this is the case, I believe it is safe to omit the type selector, as the added information is too generic for the component we're styling, and could be prone to change. In the case of
our breadcrumb, the <ol> could be changed to <nl> (navigation list) over time, but even that would still be a generic definition. So from
now on, I simply omit the type selectors whenever I'm styling a component that hasn't the exact same semantic meaning as the html element (I still use the ul selector to style plain bulleted lists for
example).
concluding
The interesting part here is that many consider it logical to apply css to general semantic elements, while it is definitely not. When we are writing css we are styling components, and these components should be addressed only through their adequate html equivalents. In most cases, this means leaving the type selector off as it is simply too generic to be of any value.
An argument I'm pretty content with, and allows for more flexible css. Double gain.
Article info
contact me
If you want to send me a quick message or you have any questions, don't hold back.
articles in css semantics
the archive
All my articles are neatly filed inside the archive. Search and filter your way to the articles you want:
8 comments in total
Another reason not to "tie" css to the type selector: CSS inheritance. By adding a type selector you increase the weight of that CSS rule. For example, in the following rule, the text in the element
<ol class="breadcrumb">will be black (#000) despite not being last.This is not caused by specificity (using the type selector), but because the CSS rule ol.breadcrumb is "heavier".
This is a useful trick when you have multiple stylesheets, as you can use something like:
on a later stylesheet to override an earlier one.
An interesting piece of writing. I decide whether to use a type selector only when it is absolutely needed. Only when I am somehow re-using bits of styling. The example of the ol vs ul element could work. You could have a special class on that to style these similar elements in a similar way .special { /* set font, height, width for both ul and ol / } ul.special { / set the unordered list style type / } ol.special { / set the ordered list style type */ } In other situations I always leave out the type selector.
Beware of bloating with classes, I think .content p { /* to set the styling of a paragraph inside the content div / } to be much much much much better than use a special class .contentparagraph { / to set the styling of a paragraph inside the content div */ }
Good article!
I absolutely agree with you there, the example you've given falls under the rule that a styled component has the exact same semantic meaning as the html element (in this case a simple paragraph).
There are cases though where paragraphs are used to markup simple bits of text (for example the "* = required" indication above forms) where I'd rather use a class than simple style on the paragraph element. This element is not really a "paragraph of text" and the markup is prone to change (you could use a 'div', though more generic, or in the future we might be using the 'line' element).
xtfer: Actually, the example you gave has everything to do with css specificity, check out my article on the subject of css specificity
I second xtfer's comment about specificity. The leaner your initial CSS is the leaner is your override CSS and eventually your CSS file size and your loading time.
Maybe I'm a bit of a tidy freak. But I prefer to tie my selectors to classes and id's. It makes for an orderly and clear stylesheet that helps me immeasurably when, months after I first created it, I'm asked to change or add something.
What if I had applied a .breadcrumb class to a breadcrumb ul list and to an h4 (for whatever perverse reason). I then change some rule in the .breadcrumb class, forgetting that it would affect my h4. I'd then run the risk of not realising that my h4's had gone out of whack (followed by an upset client call), or spend another hour unpicking my rashness.
Much better if you append multiple classes to the same rule (and comment profusely next to each).
ul.breadcrumb, /* Breadcrumb list / h4.breadcrumb { / Lazy hacky application of same style to author's name */ blah: blot; }
The argument that it bloats your css is a marginal issue, now that most users have cable/adsl lines and servers just get fatter. If you're really huffy about slimming down a 60kb stylesheet, compress it.
The argument that it makes for more flexibility is an overly clever path to follow that can lead to double-jointed abuse and memory prone mistakes. As much as it is desirable to create flexible and concise stylesheets, I think we need to be precise with our designs. xhtml, css and class-naming all need to be rigorously tied together. There is no such thing as separating content from presentation and behaviour.
Please honestly tell me that you do worry about 60k stylesheets, if not, try working for a site that has a lot of traffic. When your server is being hit over a million times an hour, you start to concern yourself with best practices and concise code.
But not every site has lots of traffic, and we're usually making sites for bigger companies who're not on some small shared hosting account. I never had complaints about server load or the size of the css files I deliver.
Well, best practises and concise code have very little in common if you ask me. Concise code is something of a hack to fix a very specific problem (bandwidth usage). It has nothing to do with how to best code and structure your web pages. To the contrary actually, you're usually left with less flexible and dirtier code.
I'm not saying concise code is a total taboo, but it's nothing more than an ugly hack to fix less than perfect circumstances.
@Lee, Have you tried server-side pre-processing and caching? Shaun has been tinkering at an interesting solution that has seen a few other spin-offs.
A million hits and hour. Busy busy.
* required fields