Hire a web Developer and Designer to upgrade and boost your online presence with cutting edge Technologies

Wednesday, November 9, 2011

How To Use CSS3 Pseudo-Classes

CSS3 is a wonderful thing, but it’s easy to be bamboozled by the transforms and animations (many of which are vendor-specific) and forget about the nuts-and-bolts selectors that have also been added to the specification. A number of powerful new pseudo-selectors (16 are listed in the latest W3C spec) enable us to select elements based on a range of new criteria.
Screenshot
Before we look at these new CSS3 pseudo-classes, let’s briefly delve into the dusty past of the Web and chart the journey of these often misunderstood selectors.
[Editor's note: A must-have for professional Web designers and developers: The Printed Smashing Books Bundle is full of practical insight for your daily work. Get the bundle right away!]

A Brief History Of Pseudo-Classes

When the CSS1 spec was completed back in 1996, a few pseudo-selectors were included, many of which you probably use almost every day. For example:
  • :link
  • :visited
  • :hover
  • :active
Each of these states can be applied to an element, usually , after which comes the name of the pseudo-class. It’s amazing to think that these pseudo-classes arrived on the scene before HTML4 was published by the W3C a year later in December 1997.

CSS2 Arrives

Hot on the heels of CSS1 was CSS2, whose recommended spec was published just two years later in May 1998. Along with exciting things like positioning were new pseudo-classes: :first-child and :lang().
:lang
There are a couple of ways to indicate the language of a document, and if you’re using HTML5, it’ll likely be by putting just after the doc type (specifying your local language, of course). You can now use :lang(en) to style elements on a page, which is useful when the language changes dynamically.
:first-child
You may have already used :first-child in your documents. It is often used to add or remove a top border on the first element in a list. Strange, then, that it wasn’t accompanied by :last-child; we had to wait until CSS3 was proposed before it could meet its brother.

Why Use Pseudo-Classes?

What makes pseudo-classes so useful is that they allow you to style content dynamically. In the example above, we are able to describe how links are styled when the user interacts with them. As we’ll see, the new pseudo-classes allow us to dynamically style content based on its position in the document or its state.
Sixteen new pseudo-classes have been introduced as part of the W3C’s CSS Proposed Recommendation, and they are broken down into four groups: structural pseudo-classes, pseudo-classes for the states of UI elements, a target pseudo-class and a negation pseudo-class.
Screenshot
The W3C is the home of CSS.
Let’s now run through the 16 new pseudo-selectors one at a time and see how each is used. I’ll use the same notation for naming classes that the W3C uses, where E is the element, n is a number and s is a selector.

Sample Code

For many of these new selectors, I’ll also refer to some sample code so that you can see what effect the CSS has. We’ll take a regular form and make it suitable for an iPhone using our new CSS3 pseudo-classes.
Note that we could arguably use ID and class selectors for much of this form, but it’s a great opportunity to take our new pseudo-classes out for a spin and demonstrate how you might use them in a real-world example. Here’s the HTML:
01<form>
02 <hgroup>
03 <h1>Awesome Widgetsh1>
04 <h2>All the cool kids have got one :)h2>
05 hgroup>
06 <fieldset id="email">
07 <legend>Where do we send your receipt?legend>
08 <label for="email">Email Addresslabel>
09 <input type="email" name="email" placeholder="Email Address" />
10 fieldset>
11 
12 <fieldset id="details">
13 <legend>Personal Detailslegend>
14 <select name="title" id="field_title">
15  <option value="" selected="selected">Titleoption>
16  <option value="Mr">Mroption>
17  <option value="Mrs">Mrsoption>
18  <option value="Miss">Missoption>
19 select>
20 
21 <label for="firstname">First Namelabel>
22 <input name="firstname" placeholder="First Name" />
23 
24 <label for="initial">Initiallabel>
25 <input name="initial" placeholder="Initial" size="3" />
26 
27 <label for="surname">Surnamelabel>
28 <input name="surname" placeholder="Surname" />
29 fieldset>
30 
31 <fieldset id="payment">
32 <legend>Payment Detailslegend>
33 
34 <label for="cardname">Name on cardlabel>
35 <input name="cardname" placeholder="Name on card" />
36 
37 <label for"cardnumber">Card numberlabel>
38 <input name="cardnumber" placeholder="Card number" />
39 
40 <select name="cardType" id="field_cardType">
41  <option value="" selected="selected">Select Card Typeoption>
42  <option value="1">Visaoption>
43  <option value="2">American Expressoption>
44  <option value="3">MasterCardoption>
45 select>
46 
47 <label for="cardExpiryMonth">Expiry Datelabel>
48 <select id="field_cardExpiryMonth" name="cardExpiryMonth">
49  <option selected="selected" value="mm">MMoption>
50   <option value="01">01option>
51   <option value="02">02option>
52   <option value="03">03option>
53   <option value="04">04option>
54   <option value="05">05option>
55   <option value="06">06option>
56   <option value="07">07option>
57   <option value="08">08option>
58   <option value="09">09option>
59   <option value="10">10option>
60   <option value="11">11option>
61   <option value="12">12option>
62 select> /
63 <select id="field_cardExpiryYear" name="cardExpiryYear">
64   <option value="yyyy">YYYYoption>
65    <option value="2011">11option>
66    <option value="2012">12option>
67    <option value="2013">13option>
68    <option value="2014">14option>
69    <option value="2015">15option>
70    <option value="2016">16option>
71    <option value="2017">17option>
72    <option value="2018">18option>
73    <option value="2019">19option>
74 select>
75 
76 <label for"securitycode">Security codelabel>
77 <input name="securitycode" type="number" placeholder="Security code" size="3" />
78 
79 <p>Would you like Insurance?p>
80 <input type="radio" name="Insurance" id="insuranceYes" />
81  <label for="insuranceYes">Yes Please!label>
82 <input type="radio" name="Insurance" id="insuranceNo" />
83  <label for="insuranceNo">No thankslabel>
84 
85 fieldset>
86 
87 <fieldset id="submit">
88 <button type="submit" name="Submit" disabled>Here I come!button>
89 fieldset>
90form>
Screenshot
Our form, before and after.

1. Structural Pseudo-Classes

According to the W3C, structural pseudo-classes do the following:
… permit selection based on extra information that lies in the document tree but cannot be represented by other simple selectors or combinators.
What this means is that we have selectors that have been turbo-charged to dynamically select content based on its position in the document. So let’s start at the beginning of the document, with :root.
Screenshot
Level 3 selectors on the W3C website.

E:root

The :root pseudo-class selects the root element on the page. Ninety-nine times out of a hundred, this will be the element. For example:
1:root { background-color: #fcfcfc; }
It’s worth noting that you could style the element instead, which is perhaps a little more descriptive:
1html { background-color: #fcfcfc; }
iPhone Form Example
Let’s move over to our sample code and give the document some basic text and background styles:
1:root {
2color: #fff;
3text-shadow: 0 -1px 0 rgba(0,0,0,0.8);
4background: url(…/images/background.png) no-repeat #282826; }

E:nth-child(n)

The :nth-child() selector might require a bit of experimentation to fully understand. The easiest implementation is to use the keywords odd or even, which are useful when displaying data that consists of rows or columns. For example, we could use the following:
1ul li:nth-child(odd) {
2background-color: #666;
3color: #fff; }
This would highlight every other row in an unordered list. You might find this technique extremely handy when using tables. For example:
1table tr:nth-child(even) { … }
The :nth-child selector can be much more specific and flexible, though. You could select only the third element from a list, like so:
1li:nth-child(3) { … }
Note that n does not start at zero, as it might in an array. The first element is :nth-child(1), the second is :nth-child(2) and so on.
We can also use some simple algebra to make things even more exciting. Consider the following:
1li:nth-child(2n) { … }
Whenever we use n in this way, it stands for all positive integers (until the document runs out of elements to select!). In this instance, it would select the following list items:
  • Nothing (2 × 0)
  • 2nd element (2 × 1)
  • 4th element (2 × 2)
  • 6th element (2 × 3)
  • 8th element (2 × 4)
  • etc.
This actually gives us the same thing as nth-child(even). So, let’s mix things up a bit:
1li:nth-child(5n) { … }
This gives us:
  • Nothing (5 × 0)
  • 5th element (5 × 1)
  • 10th element (5 × 2)
  • 15th element (5 × 3)
  • 20th element (5 × 4)
  • etc.
Perhaps this would be useful for long lists or tables, perhaps not. We can also add and subtract numbers in this equation:
1li:nth-child(4n + 1) { … }
This gives us:
  • 1st element ((4 × 0) + 1)
  • 5th element ((4 × 1) + 1)
  • 9th element ((4 × 2) + 1)
  • 13th element ((4 × 3) + 1)
  • 17th element ((4 × 4) + 1)
  • etc.
SitePoint points out an interesting quirk here. If you set n as negative, you’ll be able to select the first x number of items like so:
1li:nth-child(-n + x) { … }
Let’s say you want to select the first five items in a list. Here’s the CSS:
1li:nth-child(-n + 5) { … }
This gives us:
  • 5th element (-0 + 5)
  • 4th element (-1 + 5)
  • 3rd element (-2 + 5)
  • 2nd element (-3 + 5)
  • 1st element (-4 + 5)
  • Nothing (-5 + 5)
  • Nothing (-6 + 5)
  • etc.
If you’re listing data in order of popularity, then highlighting, say, the top 10 entries might be useful.
WebDesign & Such has created a demo of zebra striping, which is a perfect example of how you might use nth-child in practice.
Screenshot
Zebra striping a table with CSS3.
If none of your tables need styling, then you could do what Webvisionary Awards has done and use :nth-child to style alternating sections of its website. Here’s the CSS:
1section > section:nth-child(even) {
2background:rgba(255,255,255,.1)
3url("../images/hr-damaged2.png") 0 bottom no-repeat;
4}
The effect is subtle on the website, but it adds a layer of detail that would be missed in older browsers.
Screenshot
The :nth-child selectors in action on Webvisionary Awards.
iPhone Form Example
We could use :nth-child in a few places in our iPhone form example, but let’s focus on one. We want to hide the labels for the first three fieldsets from view and use the placeholder text instead. Here’s the CSS:
1form:nth-child(-n+3) label { display: none; }
Here, we’re looking for the first three children of the
element (which are all fieldsets in our code) and then selecting the label. We then hide these labels with display: none;.

E:nth-last-child(n)

Not content with confusing us all with the :nth-child() pseudo-class, the clever folks over at the W3C have also given us :nth-last-child(n). It operates much like :nth-child() except in reverse, counting from the last item in the selection.
1li:nth-last-child(1) { … }
The above will select the last element in a list, whereas the following will select the penultimate element:
1li:nth-last-child(2) { … }
Of course, you could create other rules, like this one:
1li:nth-last-child(2n+1) { … }
But you would more likely want to use the following to select the last five elements of a list (based on the logic discussed above):
1li:nth-last-child(-n+5) { … }
If this still doesn’t make much sense, Lea Verou has created a useful CSS3 structural pseudo-class selector tester, which is definitely worth checking out.
Screenshot
CSS3 structural pseudo-class selector tester.
iPhone Form Example
We can use :nth-last-child in our example to add rounded corners to our input for the “Card number.” Here’s our CSS, which is overly specific but gives you an idea of how we can chain pseudo-selectors together:
1fieldset:nth-last-child(2) input:nth-last-of-type(3) {
2border-radius: 10px; }
We first grab the penultimate fieldset and select the input that is third from last (in this case, our “Card number” input). We then add a border-radius.

:nth-of-type(n)

Now we’ll get even more specific and apply styles only to particular types of element. For example, let’s say you wanted to style the first paragraph in an article with a larger font. Here’s the CSS:
1article p:nth-of-type(1) { font-size: 1.5em; }
Perhaps you want to align every other image in an article to the right, and the others to the left. We can use keywords to control this:
1article img:nth-of-type(odd) { float: right; }
2article img:nth-of-type(even) { float: left; }
As with :nth-child() and :nth-last-child(), you can use algebraic expressions:
1article p:nth-of-type(2n+2) { … }
2article p:nth-of-type(-n+1) { … }
It’s worth remembering that if you need to get this specific about targeting elements, then using descriptive class names instead might be more useful.
Simon Foster has created a beautiful infographic about his 45 RPM record collection, and he uses :nth-of-type to style some of the data. Here’s a snippet from the CSS, which assigns a different background to each genre type:
01ul#genre li:nth-of-type(1) {
02  width:32.9%;
03    background:url(images/orangenoise.jpg);
04}
05ul#genre li:nth-of-type(2) {
06  width:15.2%;
07    background:url(images/bluenoise.jpg);
08}
09ul#genre li:nth-of-type(3) {
10  width:13.1%;
11    background:url(images/greennoise.jpg);
12}
And here’s what it looks like on his website:
Screenshot
The :nth-of-type selectors on “For the Record.”
iPhone Form Example
Let’s say we want every second input element to have rounded corners on the bottom. We can achieve this with CSS:
1input:nth-of-type(even) {
2border-bottom-left-radius: 10px;
3border-bottom-right-radius: 10px; }
In our example, we want to apply this only to the fieldset for payment, because the fieldset for personal details has three text inputs. We’ll also get a bit tricky and make sure that we don’t select any of the radio inputs. Here’s the final CSS:
1#payment input:nth-of-type(even):not([type=radio]) {
2border-bottom-left-radius: 10px;
3border-bottom-right-radius: 10px;
4border-bottom: 1px solid #999;
5margin-bottom: 10px; }
We’ll explain :not later in this article.

:nth-last-of-type(n)

Hopefully, by now you see where this is going: :nth-last-of-type() starts at the end of the selected elements and works backwards.
To select the last paragraph in an article, you would use this:
1article p:nth-last-of-type(1) { … }
You might want to choose this selector instead of :last-child if your articles don’t always end with paragraphs.

:first-of-type and :last-of-type

If :nth-of-type() and :nth-last-of-type() are too specific for your purposes, then you could use a couple of simplified selectors. For example, instead of this…
1article p:nth-of-type(1) {
2font-size: 1.5em; }
… we could just use this:
1article p:first-of-type {
2font-size: 1.5em; }
As you’d expect, :last-of-type works in exactly the same way but from the last element selected.
iPhone Form Example
We can use both :first-of-type and :last-of-type in our iPhone example, particularly when styling the rounded corners. Here’s the CSS:
1fieldset input:first-of-type:not([type=radio]) {
2border-top-left-radius: 10px;
3border-top-right-radius: 10px; }
4 
5fieldset input:last-of-type:not([type=radio]) {
6border-bottom-left-radius: 10px;
7border-bottom-right-radius: 10px; }
The first line of CSS adds a top rounded border to all :first-of-type inputs in a fieldset that aren’t radio buttons. The second line adds the bottom rounded border to the last input element in a fieldset.

:only-of-type

There’s one more type selector to look at: :only-of-type(). This is useful for selecting elements that are the only one of their kind in their parent element.
For example, consider the difference between this CSS selector…
1p {
2font-size: 18px; }
… and this one:
1p:only-of-type {
2font-size: 18px; }
The first selector will style every paragraph element on the page. The second element will grab a paragraph that is the only paragraph in its parent.
This could be handy when you are styling content or data that has been dynamically outputted from a database and the query returns only one result.
Devsnippet has created a demo in which single images are styled differently from multiple images.
Screenshot
Devsnippet’s demo for :only-of-type.
iPhone Form Example
In the case of our iPhone example, we can make sure that all inputs that are the only children of a fieldset have rounded corners on both the top and bottom. The CSS would be:
1fieldset input:only-of-type {
2border-radius: 10px; }

:last-child

It’s a little strange that :first-child was part of the CSS2 spec but that its partner in crime, :last-child, didn’t appear until CSS3. It takes no expressions or keywords here; it simply selects the last child of its parent element. For example:
1li {
2border-bottom: 1px solid #ccc; }
3 
4li:last-child {
5border-bottom: none; }
This is a useful way to remove bottom borders from lists. You’ll see this technique quite often in WordPress widgets.
Rachel Andrew looks at :last-child and other CSS pseudo-selectors in her 24 Ways article “Cleaner Code With CSS3 Selectors.” Rachel shows us how to use this selector to create a well-formatted image gallery without additional classes.
:last-child CSS in action from Rachel Andrew
The CSS for :last-child in action, courtesy of Rachel Andrew.

:only-child

If an element is the only child of its parent, then you can select it with :only-child. Unlike with :only-of-type, it doesn’t matter what type of element it is. For example:
1li:only-child { … }
We could use this to select list elements that are the only list elements in their
    or

No comments:

Post a Comment