Skip to: Navigation | Content | Sidebar | Footer


Weblog Entry

Counter Intuitive

November 01, 2006

You might assume, having written a book on the subject, that I would be intimately familiar with all the ins and outs of the CSS spec. But since I usually keep my focus on the practical bits that actually work today, that’s not necessarily so. Sometimes I get to thinking I’d really like some way to do x with CSS, and it turns out it’s actually been around for the better part of a decade.

For example, every time I style an ordered list I wish there were some way to style list item counters independently of the content. Sure you could wrap extra markup around the content to achieve that somewhat, but it’s not always practical and rarely desirable.

But, there is a way. There’s the counter-increment and counter-reset properties. As a part of generated content, I’ve simply overlooked them. Turns out they’re good at this sort of thing.

You take the style for a simple ordered list (see example):


ol {
	margin-left: 1.5em;
}
li {
	margin: 0.5em 0;
	list-style: upper-roman;
	list-style-position: inside;
}

And turn it into something a little fancier by taking control over those list items (see example):


ol {
	margin-left: 1.5em;
	counter-reset: steps;
}
li {
	margin: 0.5em 0;
	list-style: none;
	counter-increment: steps;
}
li:before {
	content: counter(steps, upper-roman) ". ";
	font: 11px "Lucida Grande", "Lucida Sans Unicode", arial, sans-serif;
	color: #4e6672;
	float: left;
}

Of course it only works in Gecko-based browsers and Opera at the moment, so it’s still useless for now.

My point isn’t really to reveal this as something new, since many of you are likely to comment that you’ve known about it for years. It’s just a nice surprise to find something exists that I often wish existed. Now I guess I can start wishing it were ready to use.

As a tangent, some will argue (not incorrectly) that generated content is a job for script. I suspect this example is a use case that exemplifies how it can be useful for general styling, in the spirit the spec intends; moving this kind of activity to script seems pointless.


November 01, 12h

That will become even easier to do when ::marker gets implemented, which will allow you to just style the list marker directly, instead of removing it and faking it with ::before.

Carl says:
November 01, 12h

Question: Can you get it to auto-generate roman numerals in front of H1s, H2s, etc.? That would be pretty useful.

3
sn says:
November 01, 13h

Psst… <ol> = ordered list. ;-)

I didn’t know about this, so thanks for bringing it up and providing examples.

November 01, 13h

Yes, its a bit of a bummer we can’t use this sort of thing now. You’d think the new IE7 would allow us to do a lot more than it does. We can wish for some speedy updates I guess (as well as a speedy adoption). On the plus side, I’ve now got a strange craving for roasted fennel.

Dave S. says:
November 01, 13h

“Can you get it to auto-generate roman numerals in front of H1s, H2s, etc.?”

Yes, you can. See the link “generated content” in the post for examples.

Dave S. says:
November 01, 13h

“That will become even easier to do when ::marker gets implemented, which will allow you to just style the list marker directly, instead of removing it and faking it with ::before.”

Sure. But given the decade-long adoption curve of CSS2 so far, I’ll remain a little more excited about counter than CSS3 properties for now.

November 01, 13h

“My point isn’t really to reveal this as something new, since many of you are likely to comment that you’ve known about it for years.”

Now I feel guilty for my original thought of “Yes! I knew and use something a guru didn’t and doesn’t” *shame*

I also completely agree with your use of generated content. I shall be a cheeky scamp and point to a post I wrote about the subject of when to use generated content:
http://www.mattwilcox.net/archive/entry/id/736/

November 01, 13h

This is why IE is so tiresome. So much of my brain-space is taken up with remembering IE bugs and limitations, I can’t concentrate on the actual potential of CSS.

Client-side web developers have spent years of effort working out IE CSS bugs and kludgy ways to achieve things, rather than being able to concentrate on the language itself, and what we want for it.

Roll on ubiquitous IE 7, and hopefully an IE 8 that moves things on as much 7 did from 6. And quickly.

will says:
November 01, 14h

“As a tangent, some will argue (not incorrectly) that generated content is a job for script. I suspect this example is a use case that exemplifies how it can be useful for general styling, in the spirit the spec intends; moving this kind of activity to script seems pointless.”

Totally agree. It’s presentational ‘content’. There’s no need for it to be anywhere but css.

Bramus! says:
November 01, 15h

Awesome tip! Didn’t know of that one yet. Too bad IE7 screws up, which I kinda expected it to do :P

November 01, 15h

I just tested this in Konqueror (I’m running Kubuntu, which uses KDE 3.5.5) and it seems to work in that as well.

12
Paul D says:
November 02, 00h

I’m surprised this doesn’t work in Safari yet. I’ve always wanted a consistent and easy way of doing this.

November 02, 00h

Don’t call it useless, call it another bonus for Gecko and Opera users. :) It’s like the text-shadow you can use in Safari, a bonus for those users.

I’m a big fan of using stuff like that to heighten the experience for users with the good taste to be using a good browser.

I did some testing at work for stuff like this: http://people.su.se/~matlin/css3.html

November 02, 01h

Interesting. I was aware of the technique, but I was under the impression that Gecko didn’t support counters. Since which Firefox does this work?

November 02, 01h

It is a bit strange that it doesn’t work in Safari since it is based on Khtml (KDE’s engine).

16
andris says:
November 02, 01h

counters would be an alternative to <ol start=”5”> (FAQs broken into groups, separated by headings), because “start” is a “no no” attribute, but at the time only opera supported generated content, so we used javascript.

dtamas says:
November 02, 03h

Great solution, but as you said also:
“it only works in Gecko-based browsers and Opera at the moment” :(

November 02, 04h

“Of course it only works in Gecko-based browsers and Opera at the moment, so it’s still useless for now.”

That’s not really in the spirit of your MOSe article from way back when ;-)

Marty says:
November 02, 05h

It’s not good, that in IE isn’t any number near the list. List in your example seems better than ordinary list, but in this time that isn’t acceptable solution for browsers. What a pity…

Dave S. says:
November 02, 08h

“Don’t call it useless, call it another bonus for Gecko and Opera users. :) It’s like the text-shadow you can use in Safari, a bonus for those users.”

Except there’s no way I can see to ensure Safari/IE get the backup list-style, and Gecko/Opera get the counters. That would require some CSS hack that targets the latter two and weeds out Safari/IE. The best I could do was remove the list-style entirely, which means Safari/IE don’t get counters at all. Not an acceptable compromise.

“That’s not really in the spirit of your MOSe article from way back when ;-)”

See above.

November 02, 09h

oooo nice one… never noticed that. I love those aha! moments, when you discover or rediscover bit of CSS, or even JavaScript or HTML for that manner. Last year after reading a book about typography, I wanted more control of the type. I thought couldn’t until I discovered letter-spacing, word-spacing, line-height and so forth. Those are truly great moments.

Jere says:
November 05, 10h

You should read through the entire CSS 2.1 specification sometime. It could reveal a lot of neat features you’ve never known about.

http://lofotenmoose.info/css/ is very enlightening about the power of CSS as well.

Jake says:
November 06, 17h

The great thing about CSS is that whenever you think you know everything, there’s always something more to learn. Nice post!

November 10, 14h

Hmm… something I would have done in JavaScript, but now I know it’s there for the future (for CSS).

25
Matt Lilek says:
November 11, 23h

Counters were recently implemented in WebKit nightly builds, which are available at http://nightly.webkit.org Download a build and give it a try, your example works perfectly :)

November 15, 15h

Using a non-globally supported CSS attribute is a matter of style and taste really. I get a greater feeling of completion from a project when the finished design looks identical (or as close to) in all browsers I test it on.

You could argue that this CSS control is a bonus for Gecko users, like text shadowing is for Safari users - and they would logically be correct as most benefits are gained. But it just goes against my personal preference. Still, it’s nice to know this is available. Hopefully support it will become more widespread in future.

Alice says:
November 16, 11h

Just when you think you know it all is when you start to learn your just beggining for only when you master something do you actually start to practice it.Great post and I love your book.

April 21, 13h

I just tested this in Konqueror and it seems to work in that as well.