Posted on by & filed under css, design, programming.

CSS3 has given us a lot of goodies that help front-end devs eliminate the use of images to achieve the stylistic effects that so many designers love to use. These include gradients and drop shadows on both text and DOM elements (and soon we’ll have blend modes!). There are also transitions and animations which, in many simple cases, can eliminate the need to use JavaScript to animate, though we still need JS to add or remove classes to trigger those effects.

I was recently reading Alex MacCaw’s great post on CSS Transitions and I learned a lot; you should check it out. I was surprised, though, that he left out mention of the transition-delay property. I’ve found it to be useful for doing some more complex transitions without building out a full JS framework like he does in his post. Let’s walk through how transition-delay can help with this.

The Setup

I’m just going to show the pertinent snippets; obviously you should use whole HTML documents! If you want to play with the examples or even fork them, they’re up on codepen.io. For our example, I’m going to build a drawer that slides out when you click on an anchor link.

The HTML

<div class="drawer">
  <div class="drawer-content">
    Some content here
  </div>
</div>

The CSS

* {
  box-sizing: border-box;
}

body {
  background: #ccc;
}

.toggle-thumb {
  display: block;
  width: 45px;
  position: absolute;
  top: 0;
  bottom: 0;
  right: 0;
  transition: all .2s ease-in;
}
.toggle-thumb:hover {
  background: rgba(255,0,0,.5);
}
.drawer {
  position: fixed;
  top: 0;
  bottom: 0;
  width: 275px;
  left: -235px;
  padding: 40px 45px;
  margin: 0;
  z-index: 20;
  background: rgba(255,255,255, .98);
}

.open.drawer {
  left: 0;
}

Nothing crazy here, just a few divs and our anchor to get everything in place. If you click through, the button is the white bar on the left side of the page. We’re going to open the drawer by adding a class open to the drawer container. In the example, this moves the drawer over so that you can read the contents. Currently there are no transitions, so at this point we’re seeing what a browser that doesn’t support transitions will look like.

The white bar on the left will be the clickable area for the sliding drawer.

The white bar on the left will be the clickable area for the sliding drawer.

View on Codepen.io

Adding a Transition

This one’s easy, we just add a transition. In the example I’m just using the transition shortcut, but chances are you’ll have to add a variety of vendor-prefixes as well.


.drawer {
  position: fixed;
  top: 0;
  bottom: 0;
  width: 275px;
  left: -235px;
  padding: 40px 45px;
  margin: 0;
  z-index: 20;
  background: rgba(255,255,255, .98);
  /* trigger HW acceleration */
  transform: translate3d(0,0,0);
  transition: left .15s ease-in-out .3s;
 }

.open.drawer {
  left: 0;
 }

You’ll notice that we added the transition on the base class, not on the class that we’re adding. This makes sure that the transition happens both when adding and when removing the class. If it were just on the class that was being added, the element would snap back without the transition.

View on Codepen.io

Chaining Transitions

Here’s where transition-delay comes in handy. If you need to transition in a certain order, you can actually delay them. Couple this with the fact that each element can have multiple transitions and you can start to chain transitions. To get our transitions to chain we’re going to use a delay for second transition that’s equal to the duration of the first, that way we’ll get a two transitons back to back just by adding a single class.

.drawer {
 position: fixed;
 top: 0;
 bottom: 0;
 width: 275px;
 left: -235px;
 padding: 40px 45px;
 margin: 0;
 z-index: 20;
 background: rgba(255,255,255, .98);
 /* trigger HW acceleration */
 transform: translate3d(0,0,0);
 transition: box-shadow .2s ease-in-out, left .15s ease-in-out .3s;
}
.open.drawer {
 left: 0;
 box-shadow: 10px 0 15px rgba(0,0,0, .3);
}

Here, we’ve added a second transition for the box-shadow property and we added the styling for the box shadow on the open class because we want to add the shadow as it opens to give the illusion of it coming off of the page.

Clicking on the white bar (pink when hovered) will slide the drawer out using the animation

Clicking on the white bar (pink when hovered) will slide the drawer out using the animation

View on Codepen.io

Getting It to Reverse

You might have noticed in the last example that the reverse case doesn’t exactly work properly. It still transitions the box-shadow first when removing the class. We can fix this by moving our current transition declaration to .open and then adding one to .drawer that swaps the order of the transitions.

.drawer {
 position: fixed;
 top: 0;
 bottom: 0;
 width: 275px;
 left: -235px;
 padding: 40px 45px;
 margin: 0;
 z-index: 20;
 background: rgba(255,255,255, .98);
 /* trigger HW acceleration */
 transform: translate3d(0,0,0);
 transition: left .15s ease-in-out, box-shadow .2s ease-in-out .3s;
}
.open.drawer {
 left: 0;
 box-shadow: 10px 0 15px rgba(0,0,0, .3);
 transition: box-shadow .2s ease-in-out, left .15s ease-in-out .3s;
}

View on Codepen.io

Wrap up

So that’s it! You might ask, “Why use this over animations which (now) have animation-direction built in?” I find transitions a bit more concise and manageable. This technique does lose its advantage over animations, though, when you start having to do more than two transitons. It simply becomes cumbersome, and manually re-ordering transition definitions doesn’t scale well.

Thanks for reading and I hope someone will find this trick as useful as we have.

Tags:

Comments are closed.