How to Add Animation Duration, Delay and Easing Support to Tailwind CSS
Tailwind CSS still doesn't ship dedicated animation duration, delay, and easing utilities. Here's a clean v4 approach.
Live Demo
Tailwind CSS doesn’t include first-class duration and delay utilities for animations.
The demo uses the following classes:
- Duration:
animate-duration-150,animate-duration-300,animate-duration-700,animate-duration-3000 - Delay:
animate-delay-150,animate-delay-300,animate-delay-700,animate-delay-3000 - Easing:
animate-ease-in,animate-ease-out,animate-ease-in-out,animate-ease-[cubic-bezier(0.9,-0.7,0.1,1.7)] - Base animation:
animate-pulse
If you want reusable classes that feel native, use @utility with the animate-* naming style.
Add Classes in Tailwind CSS
Add this to a stylesheet that Tailwind processes (for example, your global CSS):
@utility animate-duration-* {
--animate-duration: --value(integer)ms;
--animate-duration: --value([time]);
animation-duration: var(--animate-duration);
}
@utility animate-delay-* {
--animate-delay: --value(integer)ms;
--animate-delay: --value([time]);
animation-delay: var(--animate-delay);
}
@utility animate-ease-* {
--animate-easing: --value(--ease-*);
--animate-easing: --value([*]);
animation-timing-function: var(--animate-easing);
}
This gives you classes like:
animate-duration-<number>animate-delay-<number>animate-ease-<in, out, in-out>animate-ease-[cubic-bezier(.17,.67,.83,.67)]animate-ease-[cubic-bezier(0.9,-0.7,0.1,1.7)]
Classes extend from the existing transition- classes:
- https://tailwindcss.com/docs/transition-duration
- https://tailwindcss.com/docs/transition-delay
- https://tailwindcss.com/docs/transition-timing-function
Arbitrary values also work:
animate-duration-[1.2s]animate-delay-[250ms]animate-ease-[cubic-bezier(.17,.67,.83,.67)]
The live demo includes this exact custom easing class:
animate-ease-[cubic-bezier(0.9,-0.7,0.1,1.7)]
Why This Works
The custom utilities set both CSS variables and CSS properties:
animate-duration-*maps numeric suffixes like150to150ms, then sets--animate-durationandanimation-durationanimate-delay-*maps numeric suffixes like300to300ms, then sets--animate-delayandanimation-delayanimate-ease-*maps easing tokens likein,out, andin-out, and also accepts arbitrary timing functions likecubic-bezier(...)
Existing classes like animate-spin keep working, but now they can have overrides with the added utility classes.
Quick Example
<div class="animate-duration-700 animate-delay-300 animate-ease-in-out animate-spin">...</div>
This also works:
<div class="animate-delay-700 animate-duration-[1500ms] animate-ease-in-out animate-spin">...</div>
The recommended approach in this post is the @utility setup above because it gives you reusable, consistent classes.
For one-off cases, use arbitrary utility values with the same class names:
animate-duration-[5s]animate-delay-[250ms]animate-ease-[cubic-bezier(.17,.67,.83,.67)]
If needed, you can also use arbitrary properties directly:
[animation-duration:5s][animation-delay:0.25s][animation-timing-function:cubic-bezier(.17,.67,.83,.67)]
For custom easing curves, animate-ease-[...] is usually the clearest option.
Example from the live demo:
animate-ease-[cubic-bezier(0.9,-0.7,0.1,1.7)]
Example variable override:
[--animate-easing:cubic-bezier(.17,.67,.83,.67)]