Practical Use of CSS3: Transforms and Transitions


Transforms and Transitions (introduced as part of the CSS3 specification) enable us to create the kind of interaction and experience previously only associated with JavaScript or Flash. You'll likely have read a lot of discussion and tutorials covering these properties, but they tend to be experimental in nature.

In this tutorial we will explore CSS transforms and transitions by creating something more useful. We're going to build a single static HTML page that will utilize transforms and transitions in a slider, plus some interesting hover effects.

Before we continue it's worth noting browser compatibility. This tutorial demonstrates modern techniques, techniques which will be commonplace further down the line, but for the time being suffer incompatibility in older browsers. Take a look at for more detailed analysis of which browsers support the various methods discussed here.


Alright, at this point we already know where we are about to go, so we can decide what we need to prepare.

Before anything else, preparation is the key to success. ~ Alexander G. Bell

Basic Skills

First, we need a basic understanding of HTML and CSS. Assuming you have that, we are ready to go.

If, however, you are really new in this area, I would advise you take some time to get up to date on the topic; fortunately Envato has provided a 30 days course which will teach you all the essential things you need to know about HTML & CSS for free.

Find Images

We'll obviously need some images to make the image slider, as well as the image captions for the website. PhotoDune will serve our purposes very well. The following are the images that we will be using in this tutorial.

We will also need a texture for the background. My favorite place to find textures at the moment is Subtle Patterns and after browsing through all the pages, I finally decided to use this example.

Managing Folders

Although this is optional, I personally like to manage my project folders in the first step, this way it will ensure we remain organized from the get go. So, for this website I have created two main folders psd and html, whereby the html folder comprises two more folders for fonts and images.

The Design

Next, we mockup a website in Photoshop to reference while we're building it in HTML. I won't be going deeper in this step, as the actual design is beyond the scope of this tut. You can already find numerous layout tutorials at Webdesigntuts+, like this one.

Well, the image below is what I came up with; let's keep the file inside our psd folder.


Before doing any coding, I have sliced some requisite graphics to be used in the layout. First the navigation background, the one with the black color on the top and the custom made pattern for the image thumbnails.

If you followed the entire 30 day course on HTML & CSS, Jeffrey went over how to slice a PSD file during day 27.


We'll also utilize new tags from the HTML5 specification, so expect to find <nav>, <header>, <footer> and some other new tags that I (honestly) rarely use like <figure> and <figcaption>.

However, we won't discuss too much about HTML5 here, that's beyond the scope of this tutorial. Instead, you can find loads of HTML5 tutorials on Nettuts+.

Header & Navigation

Alright, let's now open up a text editor and start coding some markup.

As you can see in the final design, we won't separate the menu and the header section, so the primary navigation itself will be wrapped inside the header tag.

Image Slider Section

The Image slider will be wrapped inside a section tag. The section is a new element that is also included in new HTML5 specification to define a section or segment in an HTML document.

This is all the HTML we need to form our Image Slider. Now, let's take a closer look at each part of the markup.

Starting from the <div class="hidden">, we will use this class to hide slides that overflow from the specified dimension; in this case it would be 960 by 380 pixels.

The slides are structured using an unordered list. Each of the slides is wrapped inside a <li> tag with a unique id <li id="slide-3" class="slide"> so that we are able to select specific slide through a Fragment identifier later on.

Notice that we use figure to wrap the slide image and figcaption for the slide caption. These elements describe the roles and relationship they have perfectly (semantically).

The figure is a new tag in the HTML5 specification. This tag is intended to mark up a graphics, photos, diagrams, etc. While the figcaption, according to w3c, represents a caption or legend for the figure. So, these tags are effectively interrelated.

Image Caption Section

The image caption will be wrapped inside a section tag as well.

That's all we need for the Image Caption section, the markup is quite self-explanatory as it is similar with the markup in Image Slider.


We'll simply add copyright text in the footer.

The Styling

In this section we will begin all the styling work. I'll assume you already know how to separate the styles from the HTML document and link it using a css file.

<link href="style.css" rel="stylesheet" type="text/css" />


The styles will utilize many new CSS3 specifications, which unfortunately for each browser will require a vendor prefix to work correctly. Such as -o-for Opera, -moz- for Mozilla Firefox and -webkit- for both Safari and Chrome. Writing bloated CSS this way can be very inefficient.

So, I've decided to add Lea Verou's prefix-free in the document; a JavaScript library to handle all these vendor prefixes automatically, so we will only need to add the official property format. For instance, normally we would need to write the following CSS rule to scale an element:

While using the prefix-free script, we can remove all vendor prefixes.

Download the prefix-free file and put it at the bottom of the document, before the closing body tag.

<script src="prefixfree.js">

CSS Reset

Another problem we'll encounter across the browsers is inconsistency. Practically every browser renders HTML elements to its own default style and these default styles often differ slightly.

To overwrite the default style and ensure we're working from the same starting block in each browser, we will use a CSS reset. There are several options out there; like this one from Eric Mayer, YUI from Yahoo and HTML5 Reset by Richard Clark. But this time I'm interested to try out Normalize.css by Nicolas Gallagher. Download the file, and put the link inside the head tag, before any other css files are referenced.

All right, now we are all set up. Let's begin the styling. Start from the body tag.

The website will have a textured background; we will apply the background on the body, as well as specifying the default font family and the size.


Speaking about the font, we plan to apply a few non-system fonts for the HTML, so we'll tackle that using the @font-face rule. Well, @font-face isn't really anything new in CSS, it was actually included in the CSS2 specification, but unfortunately the method was not widely adopted by web designers at that time.

To include our own font using @font-face is rather simple. In fact, the good people at font squirrel created this handy tool to generate the code you'll need.

In our design, we used ChunkFive for the resto logo and the Titillium for the menu navigation. Let's download all these fonts and apply the @font-face rules to the stylesheet:

Styling the Header and Navigation

The header will have the background that we sliced earlier in this tutorial and we will also apply our new font family, to the home class and nav li.

Notice that we didn't include vendor prefixes to declare the box-shadow rule. I have to thank Lea Verou for creating the prefix-free script - it saves a lot of messing about.

Styling the Content

The #content style is standard. It will have a slightly white background color, a fixed width of 960px, centered in the screen, and a drop shadow.

So far, having applied all the styles above you should see something like this:

Styling the Image Slider

Now, let's apply some styles to the Image Slider. The slider including the navigation will have dimensions of 960 by 425 pixels, while the image slide itself as we mentioned above will only have 960 by 360 pixels.

The image caption will have a slightly transparent background. To achieve this transparency effect we won't use the opacity rule, as it will also affect the text inside the caption. Instead, we will achieve it using the Alpha channel from RGBA color mode.

If you pay careful attention to the image in the slide; there is a white space between the image and the caption. To remove it we add display: block; to the image.

Slide Position

In this section we will work around the slide. The slides will use absolute position so that they will stack.

While the picture in the slide should be invisible, we do this by changing the opacity value to zero.

However, the image in the first slide should be visible. So, we will select it specifically using the :first-child selector and set the opacity to 1.

Alright, the result is still not what we expect from the final design. As you can see from the image above, the slide captions that should be hidden are still visible. So, we need to hide them.

Creating Shining Effect

We should say many thanks to the CSS3 new specifications, as we can now create a shining effect without incorporating any images. We will achieve the effect using the CSS3 Background Gradient.

I am not going into the details on how to apply it, as you can read this tip here comprehensively.

Now, let's add the following styles;

If you have read the tip, then I assume the gradient rule should be obvious for you already. But, let's take a look another rule to figure out what the CSS actually does.

First, the <span class="shine"> will have absolute: position with z-index: 5 to bring it to the very top of other elements in the slide. The shining effect is not appearing correctly, so the element still needs to be rotated by approximately -20 degrees (transform: rotate(-20deg);).

Slider Navigation

The slider style is rather simple. By default, the menu in the navigation will have inline position so that each menu will appear side by side.

Notice that the navigation still shows the numeral text; we should remove it and give it some styles.

First we add inline-block, so the anchor can be added with width and height value, then add text-indent: -9999px to visually remove the text inside.

The Image Thumbnails

Now, we will add styles to the Image Caption section.

We also remove the white space between the image and the caption.

The thumbnail will have pattern overlay that we've sliced before.

As we can see in the picture above, the thumbnail images are huddled. We need some margin to make a gap in between. Rather than defining this margin for each thumbnail, we will dictate that only the middle image has one using nth-child.

nth-child is a css pseudo-class to select specific child elements using a formula. To get more insight on this pseudo-class, you can read this comprehensive explanation.

All right, first we will select the middle images, in this case the image thumbnail number 2, 5 and its multiplication.

After that, we select only the the first three images to have margin-bottom. So, the first and the second row will also have a gap in between.

Thumbnail Captions

Referring to our design, the caption will commonly have a green color with a slight transparency and rounded border.

Some of the captions will have heading level 3 (H3) and here we specify the h3 style.

The text inside the caption is wrapped inside paragraph tag (p). so we also specify the spaces between the heading and the paragraph using a margin.

And for the footer style, we simply center the text.

Alright, we have completed all the necessary styles and so far you can expect the result to look something like this:

The Effects

In this section we will begin to apply some effects to the website using transforms and transition properties.

How Do These Properties Work?

I assume you'll have come across some posts that have already discussed these properties (transforms & transitions), especially if you are a regular reader of the Tuts+ blogs network. Let me just explain a little bit about these properties for a quick recap.

Transform is a new CSS property included in CSS3 specification. Using this property we can apply various transformations such as translating (movement), rotating, skewing and scaling to elements.

Transformations can be achieved using the following css function; transform: transform-method(value). For the transform-method we can use translate, scale, rotate and skew. For demonstrative purposes we'll apply each of these methods to our image captions.

While transition is also part of CSS3 specification, this property will allow us to create gradual effect to the animation instead of instant changes. In short hand format, the effect can be applied using the following function:

transition: <property> <duration> <timing-function> <delay>

Let's apply them to our image captions for better understanding.

Color Transition

In the navigation section we will demonstrate a simple example of the transition effect. We will change the menu color from white (#FFFFFF) to orange (#FFB400) smoothly by specifying the transition-property when we hover over the menu.

Let's take a look at the following CSS rule;

The CSS rule above will specify only the color property that will be transitioned with 500ms as the duration. And notice that I didn't add a specific timing-function. If we do not specify it, the browser will use ease by default.

Now we will step up to the next, more challenging section.

Image Caption Effects

In this section we will apply various transformations and transition effects to the image captions. To begin with, we specify common rule for the image thumbnail transition.

We didn't add a specific property in the rule, instead, we used "all" for it. This means the transition effect will be applied to all the properties around the image.

In this case, the image will be 30% transparent when we hover over it.

In the next step we will define each of the caption transition behaviors.

Caption 1: Moving Upwards

The first image caption will have a linear timing-function, so the movement is steady from the start to the end.

Then, when we hover over the thumbnail, the caption will move to the top. We can achieve the movement using the translate method. The translate method will make the element move from one point to another point specified in the translate value.

We used a percentage for translation rather than giving specific value in pixel unit. This way, the caption will move relative to the image height, regardless of the actual value of the height. Also, notice that we added margin-top.

Caption 2: Moving Downwards & Transition Delay

The second caption will have full height and width so that it will cover up the image thumbnail. We will use ease-in for the caption so expect the caption to start slowly. We also add transition-delay for about 350ms, which means the effect will start right after the image transition completes.

Then, when we hover over the thumbnail, the caption will eventually move down.

Caption 3: Zoom-in Effect

For the third caption, we will use ease-out. Using this will make the caption transition end slowly. We plan for the caption zoom-in when we hover over the respective thumbnail, so we specify the caption scale as zero for its starting point.

And below is the CSS set of rules for the hover state. When we hover over the third thumbnail the caption will scale up, back to its original dimension.

Caption 4: Multiple Transformations

The fourth caption will have rotating transformation and in order that the text is not reversed we will rotate the caption first for -180 degree.

Both the caption and text inside will have transition property and this time we will use ease-in-out. Judging from the function name, as you can guess, it will make the transition effect start and end slowly.

Since, we plan to make a zoom-out effect for the text, we first transform the text to scale up by 300% and hide it visually by decreasing the opacity.

Then, when we hover over the thumbnail, the caption will eventually move to the top from its initial position and rotate at the same time. This is a simple, practical example of how we can apply multiple transformations in one element.

For the text transformation, it will be zooming-out as we've mentioned before.

Caption 5: Playing with Cubic-bezier

Speaking about transition timing-function, we already used ease, linear, ease-in, ease-out as well as ease-in-out. These keywords are actually representations of specific values from bezier curves. Such as:

  • linear is equal to cubic-bezier(0,0,1,1)
  • ease is equal to cubic-bezier(0.25,0.1,0.25,1)
  • ease-in is equal to cubic-bezier(0.42,0,1,1)
  • ease-out is equal to cubic-bezier(0,0,0.58,1)
  • ease-in-out is equal tocubic-bezier(0.42,0,0.58,1)

This time, for this caption, we will try to use a cubic-bezier with a custom value. It's actually very difficult to predict how the changes work if we are not seeing the actual act. Fortunately, there is a handy and very helpful tool to play with cubic-bezier, so we can see the instant result of the changes.

Visit where you can play around with bezier curves, created by Lea Verou, the same person behind the prefix-free.

In the following CSS, I've set the cubic-bezier values to run the transition quite fast at the start and significantly more slowly at the end.

Then, when the thumbnail is being hovered over, we want the image and the caption to move upward correspondingly.

Caption 6: Transform Origin.

We have applied scaling and rotating method for the previous captions. You may have noticed that the rotation and the scale began from the center point of the element. This was because the transform-origin is 50% 50% by default .

transform-origin is a property that allows us to specify the transform starting point in the element. It can be achieved using the following syntax transform-origin: x y.

In the sixth caption we will change the origin to 0 0(x y).

And both the caption and the image will have transition effect.

Then, when we hover over the thumbnail, the image and the caption will be transformed at the same time.

Image Slider Effects

We've played around with transforms and transition properties quite a lot. In this step we will apply them in our Image Slider.

First, we set up the image and caption. Here we set the image to have a fade-in transition effect.

As well as specifying the slider navigation transition.

Brief Introduction to :target pseudo-class

The Image Slider will be driven by a click. When we click on the slider menu the respective slide/image will eventually show up, usually with slide-in or fade-in effects. These sorts of navigations and slider effects are generally built upon JavaScript or Flash technology.

However, in this tutorial, we will try to achieve it using CSS exclusively, that is by using the :target pseudo-class.

The :target is one of the distinctive features in CSS3 that will allow us to select an element within an HTML document with a specific id that matches with the fragment identifier in the URI.

For instance, a URI; will select an element with id="section-1" on the page. Thus, similarly with the :hover, any styles around the :target would be applied.

All right, let's take a look at the following CSS rules:

The CSS rule below will turn the image opacity into 1 when the respective li is acting as the :target. Remember that we marked up the slide/image using unordered list tags.

The caption inside it should slide up by 100% of the width; please, do not omit the !important declaration. This is !important.

Okay, try out the result in your browser.

Slider Navigation Effects

The transition property can be applied specifically in selectors, such as :hover and :active.

We have defined the transition for .nav-slider li a above, but we will also specify a different timing-function under certain conditions in user behavior.

When we hover over the slider navigation, the menu will change color to green by 300ms ease-in.

When we click on it, the menu changse into dark green very fast by about 50ms.

And when the menu has no user activity, it will revert back to its original condition very slowly, by about 1s as we have specified in the .nav-slider li aabove.

The Limit

Such as with any another technology, CSS is no different. It still has some limitations.

If you refresh your browser (I assume you are still on your practice page of this tutorial), you will notice that the caption in the first slide did not show up upon the first page load. Well, this is because we only stated in the CSS to show up the caption once a li is targeted. So, here we need to add specific translation to the caption.

We select the first slide using :first-child selector and translating the caption to move upwards for 100% of its height.

Refresh your browser, now the first caption should show up in the first load. Remember that we have added 300ms delay transition in the previous step, so the caption will start showing up after that specific amount of time.

There is one problem though, the CSS statement above will make the caption remain in place, although we have navigated to the other slide. So, we need to create a counteraction rule for it.

We will add a .hide class for the caption (in the first slide) and define it to go back to its initial position.

Wait, Didn't we add a hide class in the caption?

No, we did not.

We will add it conditionally from jQuery instead (sadly). The hide class would be applied, if the users navigate to other slides.

Put the following jQuery link from Google Library at the bottom of the page before the body close tag. The current jQuery version is 1.7.1.

<script src=""></script>

We firstly create variables for the selected elements.

And then create a function to add the hide class when the users click on the menu to navigate to the other slides.

Don't forget to wrap all the code above inside <script> tag.

Wrap Up

Alright, we've written a fair amount of code in this tutorial, so let's recap.

HTML Markup


We separate the styles into two files. First, style.css file will store all the CSS rules that influence the look of the website.

And then effects.css for all the CSS rules which perform the transition and transformation effects in the website.

Final Thoughts

We're done! It's been useful seeing how we can accomplish so many effects today only using CSS rules with the bare minimum of JavaScript.

Don't forget the lack of support from older browsers, especially IE. But used conservatively these kinds of effects can enhance websites in a gracefully degrading manner.

Thanks for reading this tutorial; I hope you learned something!