The CSS3 :target pseudo-class and CSS animations

It’s no secret that I’m always looking for an easy way out using CSS instead of trying to replicate things with convoluted code — there are so many underused techniques that we could be applying to our designs as an enhancement layer! In this experience, I take a brief look into the :target pseudo-class and a very simple CSS animation.

The :target pseudo-class

We often use fragment identifiers in our code — usually to point to a specific element on a page, represented by a “#” and an anchor. When we click on a link that ends with a fragment identifier (for example, this one), that element we are pointing to becomes the target (hence :target).

This :target pseudo-class can be styled, just like we style the :hover or :active pseudo-classes on links.

To see an example in the wild, go to Wikipedia and click on a reference link (for example, this one). If you are using a good browser, you will see it has a light blue background; and if you look at the CSS, you will see this:

ol.references > li:target, sup.reference:target, span.citation:target, cite:target  {
background-color:#DDEEFF;
}

Pretty easy, right?

Our example

If you’re impatient, you can take a look at the final example now (use Safari):

View example

I’m going to create a simple list of links (using fragment identifiers) to blocks of text bellow them. Here’s the markup:

<div id="content">

<ul>
	<li><a href="#b1">Block 1</a></li>
	<li><a href="#b2">Block 2</a></li>
	<li><a href="#b3">Block 3</a></li>
	<li><a href="#b4">Block 4</a></li>
</ul>
		
<div id="b1">
	<p>One morning, when Gregor Samsa woke from troubled dreams, he found himself transformed in his bed into a horrible vermin. He lay on his armour-like back, and if he lifted his head a little he could see his brown belly, slightly domed and divided by arches into stiff sections. The bedding was hardly able to cover it and seemed ready to slide off any moment. His many legs, pitifully thin compared with the size of the rest of him, waved about helplessly as he looked. "What's happened to me? " he thought.</p>
</div>
		
<div id="b2">
	<p>The quick, brown fox jumps over a lazy dog. DJs flock by when MTV ax quiz prog. Junk MTV quiz graced by fox whelps. Bawds jog, flick quartz, vex nymphs. Waltz, bad nymph, for quick jigs vex! Fox nymphs grab quick-jived waltz. Brick quiz whangs jumpy veldt fox. Bright vixens jump; dozy fowl quack.</p>
</div>
		
<div id="b3">
	<p>Far far away, behind the word mountains, far from the countries Vokalia and Consonantia, there live the blind texts. Separated they live in Bookmarksgrove right at the coast of the Semantics, a large language ocean.</p>
</div>
		
<div id="b4">
	<p>Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.</p>
</div>

</div>

The basic CSS

First, we need to cover the basics. I’ll use a very simple reset for this example, but you should use a proper one in your projects. I’ll just set the font-size, line-height, font-family and reset padding and margin for the elements we are using:

body {
	font:62.5%/1.5 Cambria,Georgia,"Times New Roman",Times,serif;
	}
div, ul, li, a, p {
	padding:0; margin:0;
	}

Second, I will quickly style the container divcontent“:

#content {
	width:500px;
	margin:auto;
	font-size:1.4em;
	}

Third, the rest of the elements. I will:

  1. Add a small bottom margin to the list and to each block of text.
  2. Remove the bullets from our list — we don’t need them for the example.
  3. Add some padding and a light border to the blocks of text.
  4. Make the first line of each paragraph in small caps. Just because I can.

Notice I’m using the child combinator (or selector) to make sure the div‘s I’m targeting are the ones that are direct descendants of the main “contentdiv. So if, for some reason, I were to have div‘s inside the blocks of text, they wouldn’t be affected. Also, I don’t have to give these div‘s a class or target them by their id‘s.

ul, div > div {
	margin-bottom:1em;
	}
li {
	list-style:none;
	}
div > div {
	padding:1em;
	border:1px solid #ffffd3;
	}
div > div p:first-line {
	font-variant:small-caps;
	font-size:1.2em;
	}

The juicy bit

Now I’m going to style the :target pseudo-class. First, I’ll add a slightly darker border than the non-targeted div‘s:

div > div:target {
	border:1px solid #dac89d;	
	}

Enters the CSS animation. To create an animation you need two things: a definition of what effect the animation produces and a call to the animation from the element you want to animate.

Let’s define the animation first.

I’ll define the animation by setting up keyframes at certain points. In this case, I want the background to start as white, then fade to a light yellow, then back to white — I will need 3 different steps (or keyframes).

Imagine each step is a simple selector, but instead of having for example this:

div {
	background: red;
	}

we need to specify a moment in time (using percentages, or just “to” and “from” if we only need “0%” and “100%“):

10% {
	background: red;
	}

Also, here I will name my animation. I will call it “target“:

@-webkit-keyframes target {
	from { background:#ffffff; }
	50% { background:#ffffd3; }
	to { background:#ffffff; }
	}

So, the animation is defined, now we need to call it from the :target selector. We can either set each property separately, or use the shorthand version. Let’s see the full code:

div > div:target {
	border:1px solid #dac89d;		
	-webkit-animation-name:target;
	-webkit-animation-duration:.5s;
	-webkit-animation-iteration-count:1;
	-webkit-animation-direction:linear;
	}

The -webkit- bits should be self-explanatory. We need to specify the animation’s name (“target“), its duration (“.5s“, half a second), how many times it should be repeated (“1“) and its direction (“linear“).

The shorthand version looks like this instead:

div > div:target {
	border:1px solid #dac89d;		
	-webkit-animation:target .5s linear;
	}

Much simpler! Because we only want the animation to repeat once, we can even not specify the “1” in this case (if you wanted to, you could have it right after the “.5s“). Let’s say you want the animation to repeat twice, you would specify it like this:

div > div:target {
	border:1px solid #dac89d;		
	-webkit-animation:target .5s 2 linear;
	}

The end

I hope you enjoyed this brief tutorial. There are endless possibilities for CSS animation and for more advanced CSS selectors, but I feel that the ones I’m showing here can actually be used on real projects with no damage for users browsing the web with less friendly browsers.

Do you agree? Have you used the :target pseudo-class on your projects? How about CSS animation?

Note: This animation is only visible on Safari (and Chrome, like Dougal kindly pointed out!). The :target pseudo-class is not yet supported by Internet Explorer. Firefox and Opera will just show the darker border when you click on the links, but that is a good compromise.

Resouces

Update, 10 December 2011: Romanian translation of this web page