Last week, a guy from work who can afford to only support webkit browsers—hey Luis, I'm looking at you!—, had hit kind of a brick wall and was asking for help on the company design mailing list... my spidey sense kicked in. I hope this doesn't sound too cocky, but I love the smell of a challenge in the morning.
The problem
He wanted to have the <li>
s from an <ul>
to occupy the entire width regardless of how many they were. If there was only one list item, it would have a width
of 100%. Two would have 50% each and three of them, 33.33%.
Also, he wanted to accomplish this using CSS only, without having to figure out the number either using javascript or a server-side language and apply a class
accordingly (a natural and understandable cop-out if you have to support all browsers). But this is 2009 and he was looking at webkit. There has to be a way
, I thought.
So after scratching my head for a bit, I put together a test page and started throwing selectors together and attempting to figure it out.
The Solution
With the pseudo-class :nth-child
you can easily select elements based on their position in the list of children. This allows you to select one element at a time.
But you need an extra something to take into account how many siblings it has. That was the whole point.
In comes :nth-last-child
. The difference between the two is that nth-child applies to the nth child counting from the top (ie, the child that has n-1 elements before it) while the nth-last-child applies to the nth child counting from the bottom (ie, the child that has n-1 elements after it!).
That said, we could use both of this pseudo-classes together to create sets of rules that would only apply when there are one, two or three items in the list!
Code
Here's the code.
/* one item */
li:nth-child(1):nth-last-child(1) {
width: 100%;
}
/* two items */
li:nth-child(1):nth-last-child(2),
li:nth-child(2):nth-last-child(1) {
width: 50%;
}
/* three items */
li:nth-child(1):nth-last-child(3),
li:nth-child(2):nth-last-child(2),
li:nth-child(3):nth-last-child(1) {
width: 33.3333%;
}
I wish I could find one rule that would automatically figure out the width regardless of the number, instead of enumerating them all. Or even find an expression of the type an+b
that would collapse all those selectors into one... But for now, this'll do.
You can test it if you have either Safari or Firefox 3.5 (beta) on this demo page.
Why am I telling you this?
What made CSS2 so successful or powerful wasn't just what was written in the spec. It was also the myriad of articles that popped up all over the web that showed how to combine little aspects of the spec to amount to pretty amazing things.
In conclusion, the sliding doors, the faux columns or the running with sprites articles of CSS3 are still waiting to be written.
So, what are you waiting for? Push the envelope and try to discover new ways of using the properties, selectors and media queries to achieve something otherwise impossible.
Just let us know when you do.