The CSS3 :target pseudo-class and CSS animations

11 January 2010, in CSS, Project 52 | 28 comments »

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

There are 28 comments:

  1. Great article.

    I think your ending comment stating that you are teaching how to enhance the experience, without damaging users of lesser browsers is an important one.

    Some people (yes, you Andy Clarke) could learn from your example.

  2. Stanton says:

    Great article, I’m having a blast at the moment playing with some of the new CSS3 properties but haven’t found an excuse to play with animation… yet :)

  3. “This animation is only visible on Safari”

    Don’t forget about Chrome. It works fine in Chrome for all us non-mac users. I’m sure you know this as they are both webkit but some of your readers may not.

    • inayaili says:

      Oops! You’re right! I tend to forget about Chrome… I’ve updated the post, thanks! :)

    • Alcmene says:

      …and I’m sure you also know that you don’t have to be a Mac user to install Safari, then ;)

      Doesn’t change that Chrome works fine too of course :)

    • Kathy Edwards says:

      Works on my Foxfire (now :)… and I am running Linux too.

      Wonder if I could get :target to have text appear and disappear??? In effect, have different text/images show up in a box, when I mouse over the link… Sort of like the old target with frames… I bet there is a way to do it – even if it isn’t :target.

    • Maurits says:

      It works on ALL webkitbased browsers, so too on Opera. With prefixes you can get it to work on
      -Firefox (-moz-)
      -IE 9 (or later) (-ms-)
      -Chrome, Safari, Opera (-webkit-)

  4. Paul says:

    It’s great that these things are coming in CSS3. I have to say, though, that I struggle with some of it from a commercial perspective.

    At the moment we’re forced (and I guess will be for some time) to avoid IE because it simply doesn’t support these behaviours. Even when IE9 comes along, the uptake is likely to be relatively slow. The difficulty of course is either educating clients that their site will behave differently in different browsers, or we have to go with the common denominator. I know that a lot of clients I deal with would struggle with the former, which is a shame.

    All that said, I love the direction the web is going in and I love reading about new ways to do things, particularly when they don’t involve (as the author said) convoluted chunks of code :]

  5. Kayzah says:

    Puh, I really like this and wouldn’t have any problems with it if only the IE-Browsers aren’t supported. But when even Firefox and Opera don’t support this pseudo-class selector it’s near to useless U__U

    • Stanton says:

      While it’s true that they don’t support it, you missed a crucial suffix to the end of your sentence. The word “yet”.

      Opera and Firefox don’t support this pseudo-class selector, yet.

      If you start using it now, your users are in for a pleasant surprise when their browser upgrades itself to add in the support for this selector. There’s absolutely no need to wait for all browsers to support something before you use it, that’s the whole point of progressive enhancement!

    • inayaili says:

      Firefox and Opera do support the pseudo-class selector. They don’t support the animation only.

  6. Henaway says:

    Sadly, this still only works on about 2% of the world’s web browsers. While it’s cool and all, I seriously have to question the value of the CSS animations while such a tiny, tiny number of people can even see it.

    Yes, it’s cool and shiny, but how much developer time will be wasted on stuff like this that could be spent getting things working for the other 98% of the web?

    I’m with Kayzah on this one … nearly useless at the moment. Hopefully in the next few months/years, there will be wide enough adoption to really make this something to cheer about.

  7. Craig Rowe says:

    As much as I can see the viewpoint re: browser support I can’t help but get somewhat frustrated with peoples refusal to learn/try/use things until everything and everyone in the world can see it.. but anyway before I turn into Andy Clarke…

    I like the use of CSS animation in this example. One of my big concerns with the animation aspects of CSS was the boundary between behaviour and presentation. The above is a very good example of presentational use that, in my opinion, doesn’t cross over into the sort of behaviour that I would prefer was the realm of javascript.

    Nice article Yaili

  8. Andy Walpole says:

    It’s more than 2% Henaway – Safari and Chrome have about 10% of the market between them now, and have you noticed the amount of money that Google is spending on Chrome advertising! Wow.

    I think it all depends on the purpose of the website and it’s not something to spend copious amounts of time on, but they are nice additions on the right kind of site.

  9. I rely on Google Chromium, however most of the people visiting my clients website are still stuck on IE. I wonder if there is a way to force the use of a web kit like you did with the behavior element to get a hover to work in IE 6.

  10. Jack Osborne says:

    This is excellent, I didn’t know anything about this and shamefully I’ve never even heard of the :target pseudo element before.

    Great read :)

  11. Jason says:

    I had no idea about the :target element, thanks for this.

    Until most browsers support this, jQuery animate could be used to produce the same effect. Think I’ll put together a demonstration..

  12. Some great points made there, thanks for the good read!

  13. Ryan says:

    Don’t forget Firefox 3.7 and Opera 10.5 also support CSS transitions, Firefox requires the -moz prefix and Opera doesn’t require any prefix. I did an article myself on practical uses of the :target pseudo-class http://www.thecssninja.com/css/accordian-effect-using-css

  14. Codesquid says:

    I can’t wait for all modern browsers to start implementing these features fully. Firefox is lagging and IE8 doesn’t even try. Even Opera needs to catch up. Only webkit browsers are really performing at the moment.

  15. jeremy says:

    While its true that most corporate and general users will stick to IE for now, more and more I am having to tell people they need to use a modern browser… stuff just doesn’t work for IE anymore (especially when its a big company using IE6!!).

    That said, something no-one so far has commented on is that CSS 3 is supported on the iPhone. So if you are thinking of developing with JS for iPhone then you can use this stuff to do some really cool stuff!! (as i found out today, this has saved my project’s timeline in a big way)

    Jez

  16. Caramby says:

    Many people think anything goes when it comes to grammar, but grammatical errors are confusing, especially when you’re having to pay careful attention in order to read code accurately. So I’ll risk being called names, & hope I’m being helpful in pointing out that the sentence “also, I don’t have to give these div’s a class or target them by their id’s” shouldn’t contain apostrophes. Unless it’s a neologism I haven’t previously encountered. But I liked the content, & your handwriting is very neat.

  17. “…Just because I can.”

    lol! Love it! :)

  18. Joe says:

    nice tutorial and there are some interesting effects that can be achieved with :target and css3… it opens up a large amount of more intricate (yet subtle) transitions/animations.

    Although css3 is only available on a small section of the world’s browsers, i think its our responsibility to use css3 that adds visual treats to visitors with up-to-date browsers. Essentially, navigation and usability of the site should not rely on the css3 effects and they should degrade well. This is possible! It also creates a situation where people with old browsers are missing out which could slowly increase browser upgrades.

    I think designers are being lazy to use browser insufficiencies as an excuse as to why they aren’t trying to implement css3 no into commercial projects.

  19. tnx for article, nice way to do it with css!

  20. Sanjay Gupta says:

    Nice tutorial, but it’s not successful because of it’s not working on IE. All Pseudo classes is not working on IE, if you have tutorial for IE please let me know. I will very thankful to yo if you provide me Pseudo classes tutorial for IE.

    Thanks
    Sanjay Gupta

  21. Awesome post! It really helped me a lot! Thanks for sharing it.

  22. Great post. I loved it. However, click on the anchor links multiple times creates multiple pages. It this case, hitting the browser’s back button simply takes me to the same page with the previous highlighted

    This is a bad Ux since the intention of the user is to go to the previous page and not the previous selection of the same page.

    Any hacks for this? :)

Leave a comment: