The pseudo class is a way for you to select elements in various states. You may be familiar with this in the form of links, when you can set a set of styles for when someone hovers over a link like so:
a:hover {
color: #e3e3e3;
}
This serves two purposes: It lets your users know that they can click on this as it has reacted to their hover (Usability) and it makes your links prettier (Aesthetics).
Of course, the pseudo class doesn’t stop at links, and you can use :hover with any other html tag. For instance, you could use it with an input to let users know that they can interact with it:
input:hover {
border: 3px solid #eee;
}
The above just adds a nice gray border around an input when a user hovers over it. That’s just a basic example, of course. We’ll get to more complicated stuff later.
Syntax
As you would imagine, all pseudo classes in CSS follow this syntax:
element:pseudo {
}
Where element is whatever you’re targeting, and pseudo is the pseudo class you’re applying. Some pseudo classes use brackets as well. For instance, the pseudo class :not() decides what not to apply CSS to. This is useful when you want to apply somethign to everything except maybe a certain class. Example:
.class:not(div) {
}
Which will apply to all .class elements assuming they aren’t divs.
Browser Compatibility
Ah the joys of being a web developer. As usual, pseudo classes aren’t going to work in all browsers, so watch out. Where it says No the feature isn’t currently supported in any released stable version of the engine, or it is supported incorrectly. For instance, although IE does support the :active pseudo class, its implementation of it is incorrect. Also note that IE6 supports :hover, however it only supports it for anchors.
The number is the version it’s supported from (in green, of course). Last updated on January 21st 2010.
| Gecko (Firefox) |
Trident (IE) |
Webkit (Chrome/Safari) |
Presto (Opera) |
|
| :link | 1.0 | 3.0 | 85 | 7.0 |
| :visited | 1.0 | 3.0 | 85 | 7.0 |
| :active | 1.0 | No | 85 | 7.0 |
| :hover | 1.0 | 7.0 | 419.3 | 7.0 |
| :focus | 1.0 | 8.0 | Yes | 7.0 |
| :first-child | 1.0 | 7.0 | 85 | 7.0 |
| :lang() | 1.2 | 8.0 | 525 | 7.5 |
| :root | 1.0 | No | 85 | 9.5 |
| :not() | 1.0 | No | 85 | 9.5 |
| :empty | 1.8 | No | 412 | 9.5 |
| :first-of-type | 1.9.1 | No | 525 | 9.5 |
| :last-child | 1.0 | No | 525 | 9.5 |
| :last-of-type | 1.9.1 | No | 525 | 9.5 |
| :only-child | 1.8 | No | 525 | 9.5 |
| :only-of-type | 1.9.1 | No | 525 | 9.5 |
| :nth-child | 1.9.1 | No | 525 | 9.5 |
| :nth-last-of-type | 1.9.1 | No | 525 | 9.5 |
| :nth-last-child | 1.9.1 | No | 525 | 9.5 |
| :nth-of-type | 1.9.1 | No | 525 | 9.5 |
| :target | 1.3 | No | 525 | Partial |
| :enabled | 1.8 | No | 525 | 9.0 |
| :disabled | 1.8 | No | 525 | 9.0 |
| :checked | 1.0 | No | 525 | 9.0 |
| :indeterminate | 1.9.2 | No | 522 | No |
| :default | 1.9 | No | No | 9.0 |
| :valid | 1.8 | No | No | 9.0 |
| :invalid | 1.8 | No | No | 9.0 |
| :in-range | 1.8 | No | No | 9.0 |
| :out-of-range | 1.8 | No | No | 9.0 |
| :required | No | No | No | 9.0 |
| :optional | No | No | No | 9.0 |
| :read-only | No | No | No | No |
| :read-write | No | No | No | No |
Using the Pseudo Class
Most of the pseudo class elements are pretty straight forward and do exactly what they say they do. Pseudo classes target elements in different situations and states. Some of them are a little trickier, so in the table below is a list of the pseudo elements and their intended usage.
| Intended Usage | |
| :link | Apply something to an unvisited link |
| :visited | Apply something to a visited link |
| :active | Apply something to something that’s active, for instance a link is active from when you click it until you release. |
| :hover | Apply something to what the users hovering over |
| :focus | When something is focused it’s being used, for instance when a user is typing something into a input field its being focused on |
| :first-child | Apply something to the first child of an element |
| :lang() | Apply something to an element using a specific language, for instance lang(en) for English. You can then put lang=”en” in an html tag. |
| :root | Applies CSS to the root element, i.e. the <html> tag in an html document. |
| :not() | Apply CSS to something while not applying it to something else. |
| :empty | Apply CSS to the element when it has no data in it. |
| :first-of-type | Apply CSS to the first element of it’s type. For instance if you have two divs, it’ll only be applied to the first |
| :last-child | Apply if the element is the last element in its parent holder. So p:last-child will only be applied if there is a paragraph which is the last child of a parent. |
| :last-of-type | Apply CSS to the last element of it’s type. Similar to first-of-type |
| :only-child | Apply CSS to an element if it’s the only child of an element. |
| :only-of-type | Apply CSS to an element if it’s the only element of its type in its parent holder |
| :nth-child | Allows you to select a numbered child. For instance, p:nth-child(2) will target p elements which are the second child. You can also add rules, such as p:nth-child(2n+1) where n is a number starting at 0 and increasing. So 2n+1 will target every other (odd) element. Alternatively you can write nth-child(odd). All nth pseudo classes allow for rules like this, |
| :nth-last-of-type | Allows you to select a numbered last-of-type element, for instance nth-last-of-type(4). |
| :nth-last-child | Allows you to select an element from the end of the parent container, for instance nth-last-child(1) would pick the last child, nth-last-child(2) would pick the second last, etc. |
| :nth-of-type | Apply CSS to a numbered element of a certain type. Similar to first-of-type and last-of-type except you can pick a number. For instance :nth-of-type(2) will pick the second of that type. |
| :target | For instance, if you have a URL like index.html#header, this will allow you to apply CSS to the element with id=”header” |
| :enabled | Apply to all currently enabled inputs |
| :disabled | Apply to all currently disabled inputs |
| :checked | Apply to checked input boxes |
| :indeterminate | For radio and check box elements, when they are neither selected or unselected |
| :default | Apply to the default element, for instance the default submit button in a form |
| :valid | Apply to valid input field data (when setting a certain data type for an input in HTML5) |
| :invalid | Apply to invalid input field data |
| :in-range | Apply to elements that are in a range (when using input type=”range” with HTML5) |
| :out-of-range | Apply to elements out of range |
| :required | Apply to all required input fields |
| :optional | Apply to optional input fields |
| :read-only | Apply to read only elements |
| :read-write | Apply to editable content in an element |
The Many Benefits
Usability
Usability can make or break a website. After all, you want your users to be able to use your website in an easy way, don’t you? Pseudo classes can come in handy when trying to increase usability. Hover effects can make things react to a users hover, letting them know they can do things with it.
Breakdown of CSS
The above is a pretty basic example of what pseudo classes can do for you, and show how they can make things a heck of a lot easier to use. The CSS looks something like this:
#s {
border: 3px solid #c5c5c5;
color: #5e5e5e;
font-size: 16px;
font-family: Tahoma, sans-serif;
padding: 15px;
width: 240px;
margin: 0px;
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
}
#s:hover {
border: 3px solid #a1a1a1;
}
#s:focus {
border: 3px solid #8d3737;
outline: none;
background: url('images/search.gif') repeat-x;
}
This allows users to see that they can interact with the search box. Of course, not all browsers support :focus or even :hover properly, which leads us onto our next point.
Graceful Degradation

Graceful Degradation is when a browser doesn’t support a pseudo class (or any CSS for that matter), it’ll fall back on something else. For instance, the fact that older browser don’t support rounded corners doesn’t mean you can’t implement it. It just means users wont see the rounded corners in those older browsers. It won’t affect your users in any site-crippling way.
The same goes for pseudo classes. If you’re using an older browser which doesn’t support :focus and the user clicks on an input with a focus CSS class, it just means those users wont get the focus effect. It doesn’t alter the usability of the input field. This means you can implement most pseudo classes on a basic level (as long as they’re not being implemented in a way that’ll effect the layout of a website) without worrying about altering user experience in older browsers.
Aesthetics
Pseudo classes give you the opportunity to make everything on your website look prettier. Websites are no longer two dimensional, and most websites implement hover effects and things like that to let users know they can interact with it. It’s no longer just about the static design you have in Photoshop, but also about how everything is going to mesh together and react to a user.
Not only that but things that were once hard will be simplified by pseudo classes, such as having the last div be a footer with :last-of-type, or having custom CSS when something is :empty.
Where do I go from here?
- Code a Layout in HTML5
- How to Handle IE6: Aggressive Graceful Degradation
- CSS3 Pseudo in IE5-8
- 8 Awesome Things CSS3 Will Do





twitter
subscribe to our rss feed
like us on facebook
Most Popular