We got to talking about easing in a recent episode of ShopTalk with Val Head and Sarah Drasner. Easing is important stuff when it comes to animations and transitions. Combined with the duration, it has a huge effect on the feel of change. If you’re taking animation seriously as part of the brand on a project, you should define and consistently use easings.
That said, it’s a balance between:
- Crafting/using easings that match your brand
- Adhering to soft “rules” about what type of easings are appropriate when
Let’s look at one particular best practice, as I understand it. But first, another observation.
The default transition-timing-function
in CSS (the easing) is ease
.
.thing {
/* The default, as in, you get this without defining anything */
transition-timing-function: ease;
/* Also the same as */
transition-timing-function: cubic-bezier(0.25, 0.1, 0.25, 1);
}
It’s a pretty nice one! I’m guilty of hardly ever changing it. I set and tweak the durations and generally leave it to ease
. Too nice, perhaps? I wonder if we would be more proactive about choosing well-fitting easings if CSS defaulted to the more boring/lifeless linear
easing. Although linear
can be quite useful, I’ve found, when the change is very small, like only moving a few pixels or a color changing shade.
The ease
timing function is so nice, perhaps, because it’s a variant of ease-in-out
. That is, the change happens slowly both at the beginning and end, and speeds up only in the middle somewhere. This gives soft edges (metaphorically) to the change and generally feels good.
There are two other built-in CSS timing functions:
ease-in
: slow at the beginning, fast/abrupt at the endease-out
: fast/abrupt at the beginning, slow at the end
While they make a certain intuitive sense looked at that way, the general “rule” (in quotes) is to use them opposite of how they are named:
ease-in
: when things are moving out.ease-out
: when things are moving in.
Think of a knight’s squire. When the knight calls them, they better arrive at a run, and slow down into place. When the knight sends them away, they’d better very quickly get moving out of there.
That feels like a best practice. Like the animation is being courteous and obedient on both sides. Get here in a hurry, but compose yourself. Get out of here even faster and without delay.
Here’s the CSS that goes along with that kind of thinking. This changes the easing function depending on if the element in question is being shown or being hid, as well as the timing.
.container .alert {
/* This timing applies on the way OUT */
transition-timing-function: ease-in;
/* Quick on the way out */
transition: 0.2s;
/* Hide thing by pushing it outside by default */
transform: translateY(130%);
}
.container.alert-is-shown .alert {
/* This timing applies on the way IN */
transition-timing-function: ease-out;
/* A litttttle slower on the way in */
transition: 0.25s;
/* Move into place */
transform: translateY(0);
}
See the Pen Different eases for “in” and “out” by Chris Coyier (@chriscoyier) on CodePen.
I put this CSS-based demo together based on the smart things Val and Sarah were talking about as well as recently seeing Google’s design spec for this exact movement.
The animation timings we’re using here are also in “rule” territory, as Val generally described: 0.1-0.2s for simple interface movements, and up to 0.5s for more complex or larger movements.
In summary:
ease
is pretty nice, but you might want to customize some easings that feel right for your brandease
andease-in-out
have soft edges on both sides, but sometimes it’s more appropriate to use ease-in or ease-out- You don’t have to use a single easing for both directions of an animation, you can switch it up
- You can change duration also
Also, here’s a handy-dandy reference to the defaults and their matching cubic-bezier in case you want to start with one of them and customize from there:
.examples {
transition-timing-function: linear;
transition-timing-function: cubic-bezier(0, 0, 1, 1);
transition-timing-function: ease;
transition-timing-function: cubic-bezier(0.25, 0.1, 0.25, 1);
transition-timing-function: ease-in-out;
transition-timing-function: cubic-bezier(0.42, 0, 0.58, 1);
transition-timing-function: ease-in;
transition-timing-function: cubic-bezier(0.42, 0, 1, 1);
transition-timing-function: ease-out;
transition-timing-function: cubic-bezier(0, 0, 0.58, 1);
}
Great article Chris!
Shameless self promotion: I have a Sass snippet on this very website that puts most of the jQuery bézier curve easings into an easy to use map: https://css-tricks.com/snippets/sass/easing-map-get-function/
I should probably update it to include the base values described here too.
Nice post. A lot of websites don’t pay attention to this sort of thing so we get things like ease-ins for things in the viewport (abrupt stops give me pain ).
A useful package for postcss is postcss-easings (https://github.com/postcss/postcss-easings) which lets you write E.g.
ease-out-quart
(a lovely default if you dont want to spend time thinking about these things) and translates it into the appropriate cubic-bezier function!Long time ago i made an example for easing functions in Adobe Flex, you can see graphically the parameters:
http://www.madeinflex.com/img/entries/2007/05/customeasingexplorer.html