If you haven’t yet used CSS3 transitions extensively, here’s something you may not have picked up on.
As I’ve outlined before, transitions can be triggered in a number of ways, and even via JavaScript. The reason for this is because the actual transition is not dependent on any particular event. Although it is the event that triggers the transition, the transition itself is completely separate from the event (as it should be).
Because of this, you’ll notice a slightly quirky behaviour if you place the transition on the part of your CSS that triggers the event.
To illustrate this, here’s some simple transition code using the :hover
pseudo-class:
a:link, a:visited { font-size: 40px; -webkit-transition: font-size 1s ease; -moz-transition: font-size 1s ease; -o-transition: font-size 1s ease; transition: font-size 1s ease; } a:hover { font-size: 100px; }
And here’s a JSBin demo:
It’s pretty simple, right? You hover over the link, and the font-size
animates (or transitions) from 40px to 100px. You hover off the link, and it transitions from 100px down to 40px.
Now let’s try it like this:
a:link, a:visited { font-size: 40px; } a:hover { font-size: 100px; -webkit-transition: font-size 1s ease; -moz-transition: font-size 1s ease; -o-transition: font-size 1s ease; transition: font-size 1s ease; }
What’s different? Well, instead of placing the transition property on the natural link state, I’ve placed the transition on the hover state. And the result?
Maybe you’ve figured it out, but here’s the demo:
Since the transition is put directly on the hover state, now the transition only occurs on that state (that is, when the hover occurs). When you roll back off the link (which means the normal state is now occurring), the property changes instantly from 100px to 40px (as would normally happen, without a transition).
It’s a pretty small thing, but something to keep in mind if you’re placing your transitions on the event states rather than on the natural state of the element. I suppose there could be some isolated cases where you desire this behaviour so it might be good to know this subtle difference in transition behaviour.
A Possible Use Case
After the first comment posted by Jono below, I realized there’s a very good use for this difference. You can have the hover transition occur over a longer time than the hover off. Here’s the code:
a:link, a:visited { font-size: 40px; -webkit-transition: font-size 1s ease; -moz-transition: font-size 1s ease; -o-transition: font-size 1s ease; transition: font-size 1s ease; } a:hover { font-size: 100px; -webkit-transition: font-size 3s ease; -moz-transition: font-size 3s ease; -o-transition: font-size 3s ease; transition: font-size 3s ease; }
And here’s the demo:
In that example, the hover-on transition would take 3 seconds, but the hover-off transition would take only 1 second (by changing the transition duration part of the shorthand code). There are probably tons of ways this could come in handy, because often it’s the user-enabled part of the transition you want to occur more obviously, whereas the “back to normal” transition would be fine if it occurred less obviously (i.e. in less time).
What it Means
This is why transitions work in conjunction with media queries (something I incorporated into my recent redesign). The transition has nothing to do with any media query; the transition properties are declared on the static states of the elements being transitioned. But when the media query changes the state of those properties, they animate rather than occur instantly.
This (at least for me) drives home the point of how transitions work. The transition, when placed on the static element state (as in the first example above), is telling the browser to animate the properties in question anytime that state is reached. Whenever the value of the assigned properties changes (no matter how they’ve changed), when they come back down (or up) to their original state, they should do so in an animated (not instantaneous) manner.
What happens when the transition is added to both the element and the element’s state? Does the cascade honor the state’s transition (overriding the element’s transition), or apply the element’s transition on :hover and the the state’s transition on mouse out?
It would be nice to be able to set different transitions for :hover and deHover (mouseOut), without JavaScript.
Well, it basically applies both, but it doesn’t look like there’s anything different than just doing it on the element itself without the hover state.
And actually, this comment helped me see a very good use case for this — different timing for hover-on vs. hover-off — so I’ve added that as an example. You could also change the ease part to linear or some other function for the style of transition. So yes, there is a way to change the hover/dehover states: just declare them both.
Cool, exactly what I was thinking.
I got inspired and played around a bit: CSS:hover Transitions Experiment.
Definitely the thing to know here is changing the transition for hover on / hover off (see also). Changing the duration can be a really nice effect, and in fact, I think it’s really common that having the transition occur quickly on the hover and slowly on the hover off looks better than having them the same duration. I almost wish we could do that without so much repetition, like just an additional property. transistion-duration-on / transition-duration-off (or something)
Thanks for the link. I had forgotten about (or else didn’t even see) that post of yours.
Thanks for the post. I haven’t used transitions yet, so this saved me some time figuring out what elements they need to be added to and how. The comments are thought provoking too.
Hi, thanks for this. Seems like a really simple bit of CSS. Great demos to to show how to get to grips with transitions. Can’t wait to have a play with this.
The vendor prefix for Opera also needs the dash in front, btw… so -o-transition throughout all your examples ;)
Patrick, good catch. That was just a copy-paste typo on my part. Had to fix the demo pages too.
Thank you. :)
Thanks for the explanation of CSS3 Transitions. it very useful for me.
In my normalize.css (from h5bp) I apply a 100ms transition for colour on all my links – similar to how you’ve set them up on your current design.
What I then do is remove the transition on all :active’s, that way ensuring that the UX when clicking is consistent with the on / off state of a mouse click. I get an unsettling feeling of, “OMG why is the link taking so long to react,” when the transition on the active is not removed.
I was happy to discover transitions can be made specific to different states, it helps with the user experience just that extra bit.
Cool post :)
Elegant and useful CSS snippet, will be trying this and letting you know how I get on