Page Transitions with CSS3

In the last few years, we’ve seen a lot of single page websites lying around the internet, most of them using JavaScript for some transitions effect. Well, now I’m gonna teach you how you can have your own, but instead I’ll be using CSS Transitions and the :target property to do all the magic.


In the last few years, we’ve seen a lot of single page websites lying around the internet, most of them using JavaScript for some transitions effect. Well, now I’m gonna teach you how you can have your own, but instead I’ll be using CSS Transitions and the :target property to do all the magic.

The Dribbble shots used in the demos are by Matt Kaufenberg. Check out his Dribbble profile or visit his An Illustration-a-Day Blog.


The HTML will contain five main divisions: a header and the four content sections. Each of the content sections is going to have an ID and the class panel. Moreover, we will add another division inside which will have the class content. The first content section which is #home will only have the content class and will not require an extra division:

<!-- Home -->
<div id="home" class="content">
	<p>Some content</p>
	<!-- ... -->
<!-- /Home -->

<!-- Portfolio -->
<div id="portfolio" class="panel">
	<div class="content">
		<p>Some content</p>
		<!-- ... -->
<!-- /Portfolio -->

<!-- About -->
<div id="about" class="panel">
	<div class="content">
		<p>Some content</p>
		<!-- ... -->
<!-- /About -->

<!-- Contact -->
<div id="contact" class="panel">
	<div class="content">
		<p>Some content</p>
		<!-- ... -->
<!-- /Contact -->

In the header we will have the main heading and the navigation:

<!-- Header with Navigation -->
<div id="header">
	<h1>Page Transitions with CSS3</h1>
	<ul id="navigation">
		<li><a id="link-home" href="#home">Home</a></li>
		<li><a id="link-portfolio" href="#portfolio">Portfolio</a></li>
		<li><a id="link-about" href="#about">About Me</a></li>
		<li><a id="link-contact" href="#contact">Contact</a></li>

The reason for having such an “unordered” structure by adding the header to the end, is that we make the navigation “reachable” using the general sibling selector (~), so that we can color the respective items differently.

Now, the main idea is to use the pseudo-class :target in order to add a transition to the current section. In this example, we will be sliding up and down our sections.


First we will give style to our header and the navigation. We want to keep these on the same spot at all the time, even though everything else will be moving.

	position: absolute;
	z-index: 2000;
	width: 235px;
	top: 50px;
#header h1{
	font-size: 30px;
	font-weight: 400;
	text-transform: uppercase;
	color: rgba(255,255,255,0.9);
	text-shadow: 0px 1px 1px rgba(0,0,0,0.3);
	padding: 20px;
	background: #000;
#navigation {
	margin-top: 20px;
	width: 235px;
#navigation a{
	color: #444;
	display: block;
	background: #fff;
	background: rgba(255,255,255,0.9);
	line-height: 50px;
	padding: 0px 20px;
	text-transform: uppercase;
	margin-bottom: 6px;
	box-shadow: 1px 1px 2px rgba(0,0,0,0.2);
	font-size: 14px;
#navigation a:hover {
	background: #ddd;

All the sections except #home have the panel class. Here we will be using the transition whenever an element with this class gets “targeted”. The trick is to use a negative margin in the “normal” class and no margin at all in the :target pseudo-class. Adding a transitions will make the panel slide from the top whenever one is “selected”:

	min-width: 100%;
	height: 98%;
	overflow-y: auto;
	overflow-x: hidden;
	margin-top: -150%;
	position: absolute;
	background: #000;
	box-shadow: 0px 4px 7px rgba(0,0,0,0.6);
	z-index: 2;
	-webkit-transition: all .8s ease-in-out;
	-moz-transition: all .8s ease-in-out;
	-o-transition: all .8s ease-in-out;
	transition: all .8s ease-in-out;
	margin-top: 0%;
	background-color: #ffcb00;

Next, let’s style the content class that all our sections have:

	right: 40px;
	left: 280px;
	top: 0px;
	position: absolute;
	padding-bottom: 30px;
.content h2{
	font-size: 110px;
	padding: 10px 0px 20px 0px;
	margin-top: 52px;
	color: #fff;
	color: rgba(255,255,255,0.9);
	text-shadow: 0px 1px 1px rgba(0,0,0,0.3);
.content p{
	font-size: 18px;
	padding: 10px;
	line-height: 24px;
	color: #fff;
	display: inline-block;
	background: black;
	padding: 10px;
	margin: 3px 0px;

In order to change the color of the current item in the navigation, we’ll use the :target pseudo-class with the general sibling selector to “get to” the respective navigation item:

#home:target ~ #header #navigation #link-home,
#portfolio:target ~ #header #navigation #link-portfolio,
#about:target ~ #header #navigation #link-about,
#contact:target ~ #header #navigation #link-contact{
	background: #000;
	color: #fff;

And that’s all you need. Check out the demos and you’ll see other examples of how you can do this.

Hope you liked this tutorial and maybe you can experiment with your own effects.

¡Hasta la próxima!

Tagged with:

Sergio Camalich

Sergio Camalich is a mexican graphic designer, specialized in web design and front-end development, working at Element Studios and freelancing. He loves camping and is addicted to root beer.

Stay in the loop: Get your dose of frontend twice a week

👾 Hey! Looking for the latest in frontend? Twice a week, we'll deliver the freshest frontend news, website inspo, cool code demos, videos and UI animations right to your inbox.

Zero fluff, all quality, to make your Mondays and Thursdays more creative!

Feedback 89

Comments are closed.
  1. That looks impressive! I have been looking for something like that and tried several times to implement it myself with failure. Good job!

  2. Truly amazing!
    My only problem what to do with browsers that do not support :target?

    • It is a very nice tool, just like ie9.js, though I wouldn’t recommend to rely on it that much, since they might not always work.

  3. hi! Looks awesome! but it doesnt work on my iphone. iPad is okay. is this normal?

    also a newbie- question: is there somewhere a tutorial in general how to implement all these cool codrops effects into a WordPress-site? I tried it a few times but I am never sure what would be the best way…

  4. Orgulloso saber que eres Mexicano que …. Gracias… (pero hay cosas básicas que no sé; ¿Cómo enlazo la forma de contacto para recibir la retroalimentación?… ya sé, de párbulos, ¿Algún tutorial para principiantes? ¡Felicidades por tu trabajo!

  5. I used this with Animate.css to utilize the existing library of animations. I had an issue with the rotate effects, but the rest worked fine. It’s really simple to set this up, actually. Put animate.css in the css directory, add a link to it in the head of the document, then just remove the transition from the panel class and add this to the style.css:

    #home:target,#portfolio:target,#about:target,#contact:target{ -webkit-animation-delay:1s; -moz-animation-delay:1s; -o-animation-delay:1s; animation-delay:1s; -webkit-animation: 1s ease; -moz-animation: 1s ease; -ms-animation: 1s ease; -o-animation: 1s ease; animation: 1s ease; -webkit-animation-fill-mode: both; -moz-animation-fill-mode: both; -ms-animation-fill-mode: both; -o-animation-fill-mode: both; animation-fill-mode: both; -webkit-animation-name: bounceInDown; -moz-animation-name: bounceInDown; -ms-animation-name: bounceInDown; -o-animation-name: bounceInDown; animation-name: bounceInDown; }

    Change the animation name to whatever you’d like to use and voila! 50+ more examples.

  6. This is great! I love all the things that css3 can do but I’m still a bit hesitant to use it because it doesn’t work 100% on all browsers. When do you think it will be safe to really start implementing this without browser issues?

    • Because it’s not a feature that exists in IE7-9, it’s never going to be “safe” to use css transitions to transition content. That is, unless IE7-9 falls out of favor or we are given a polyfill that is simple/straight forward to use. Even so, a transition or animation should never be used to navigate/hide/show content. If that animation (or javascript) is not supported, your site will break, or content will be inaccessible.

      Right now, use css3 to enhance presentational elements and polyfill where you need to. So, it’s cool to round the borders on a button, but if you’re using it heavily throughout the site, unless you have a polyfill to support IE (Like CSSPie) then you shouldn’t use it.

  7. Interesting idea – would it work with different pages though rather than just an ID?

  8. I agree with kevin, I found out about your website a few days ago, and I’ve been reading a lot of tutorials, I can’t believe some things that can be made only with css, there are some kind of animations that I believed that only could be made in flash, but it’s a shame that f’ing internet explorer (version 8, I don’t know if version 9 does) doesn’t support many things that chrome, firefox and opera (and I’m guessing safari too) show perfectly, it’s a pity.

  9. This is great, thanks so much! I tried it in IE7, and of course, without CSS3 support the links didn’t do anything. If I was to use this for a live site right now, how would you make it degrade gracefully? Thanks!

  10. I saw this tutorial today, and I’ve been wonder if I could use it with WordPress. Maybe if I put some AJAX to get the post page?

  11. excelente , definitivamente gracias por compartirlo.
    seria bueno qui hicieran uno para Mobile 😉 gracias!!!!!!

  12. Neat tutorial. I wonder if this would be like web slideshows in the end, neat at first but eventually visually distracting. As well, Android will crawl with this, not that this is the target user.


  13. Wow, this is really awesome…. I am still wondering that how this is possible with CSS only… CSS3 rocks!

  14. oww i just love it 😀 but IE is main problem anyone know how to solve it ?? ,plz let me know

  15. Really great work! So much better than the ole jquery fade! Come on IE support this stuff so it can really become the standard!

  16. Quite promising. It would need some work to achieve a basic minimum standard of keyboard accessibility, and this would be strictly enhanced CSS only (including this as your default or base CSS would be very unwise). But it could be done.

  17. Looks & works perfect in Firefox, actually i do NOT recommend to use as body background any larger image in Chrome, it terribly lags :/ …

  18. Thanks for the tut, finnaly i find the way to creat amazing pages.
    viva css3 :p

  19. How would you have the fade effect from example 2 to display when closing the panel? Example: Display a fade-out effect when you navigate from index2.html#home to index2.html.

    Great code here, thank you so much!

  20. first of all, love this tutorial. excellent work. i have one question, it maybe a dumb one but I am new to css3, in the demo, whenever you load it up, the home div, by default is shown and selected. how do you get the home div to be the default div?