Library / SDK
new-data-services/tailwindcss-animated avatar
new-data-services/tailwindcss-animated

tailwindcss-animated adds duration, delay and iteration utilities Tailwind leaves out

Extended animation utilities for Tailwind CSS

993 stars21 forksJavaScriptMIT

At a glance

What is it?
tailwindcss-animated is a Tailwind CSS plugin that extends the built-in spin, ping and pulse animations with ready-made keyframes plus utilities for duration, delay, direction, iteration count, timing function, fill mode, play state and composition. It ships for both Tailwind v3 and v4, and the CSS custom property hooks are the part that makes it more than a class dump.
Who is it for?
tailwindcss-animated fits teams already on Tailwind that want more keyframes than spin, ping and pulse, and that want duration, delay and iteration control without writing custom CSS each time. It does not fit a project that needs scroll-triggered animation, since the plugin's own documentation says that requires JavaScript and an Intersection Observer.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 160 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The plugin fills the gap between the three animations Tailwind ships

Tailwind CSS ships three animation utilities by default. tailwindcss-animated extends those, and the extension is what the plugin is for.

The mechanism is a Tailwind plugin that registers additional utilities. The package exposes a main entry at src/index.js, a type declaration at src/index.d.ts, and a stylesheet at src/index.css, and the published files list is just the src directory, so what ships is the plugin code plus its CSS.

The utility surface is organised by CSS animation property, and each group is a table in the project documentation. Duration covers animate-duration-75 through animate-duration-1000. Delay covers animate-delay-none and the same numeric ladder. Direction offers animate-normal, animate-reverse, animate-alternate and animate-alternate-reverse. Iteration count gives animate-infinite, animate-once, animate-twice and animate-thrice. Timing function covers animate-ease, animate-ease-linear, animate-ease-in, animate-ease-out and animate-ease-in-out. Fill mode offers animate-fill-none, animate-fill-forwards, animate-fill-backwards and animate-fill-both. Play state gives animate-run, animate-play, animate-stop and animate-pause. Composition offers animate-replace, animate-add and animate-accumulate.

This is a different kind of contribution from a keyframe library. Most animation plugins ship named effects and leave the timing to the framework defaults. This one goes after the animation-* properties that Tailwind itself does not expose, which is exactly the part a design system ends up hand-writing in CSS.

Two import paths, and the v4 path drops the config file

Installation is a single npm command:

sh
npm install tailwindcss-animated

The import step differs by Tailwind major version, and this is the first thing to get right.

With Tailwind CSS v4.x, you import the plugin in your CSS file alongside Tailwind itself:

css
/* tailwind css v4.x */
@import "tailwindcss";
@import "tailwindcss-animated";

With Tailwind CSS v3.x, or with the legacy JavaScript configuration file, the plugin goes into the plugins array:

js
// tailwind.config.js
module.exports = {
  // ...
  plugins: [
    require('tailwindcss-animated')
  ],
}

The peer dependency range in package.json is tailwindcss >=3.1.0 || >=4.0.0, so one published version covers both lines. That dual support is also why the repository carries a devDependency aliased as tailwindcss-legacy pointing at tailwindcss@^3.1.0 alongside the current tailwindcss at ^4.3.0. The project tests against both.

A detail worth noting for a plugin that spans two majors: the default branch is 2.x, and the most recent release is v2.1.0, which follows v2.0.0 from 2025-01-28. Both Tailwind v3 and v4 are covered by the same published version.

Duration, delay and iteration are separate classes you compose

A ready-to-use animation is applied with a single animate- class, and the modifiers are added alongside it:

html
<button class="animate-wiggle">
  Hej, look at me!
</button>

<button class="animate-jump-in animate-delay-300 animate-once">
  Wait a bit, then jump right in.
</button>

The second example shows the design of the whole library in one line. animate-jump-in is the effect, animate-delay-300 is the timing, and animate-once is the iteration count. Nothing about the effect and the timing are coupled, so the same keyframe can be reused with a different delay without adding a new class to the plugin.

The set of ready-made animations extends the Spin, Ping and Pulse animations of Tailwind CSS, and a configurator page at tailwindcss-animated.com/configurator.html exists to preview them.

Arbitrary values work in the standard Tailwind fashion, so you are not limited to the fixed ladder:

html
<div class="animate-delay-[85ms] animate-duration-[2s] animate-iteration-[10]">
  <!-- ... -->
</div>

Bare values are also accepted for delay, duration and iteration utilities, and with Tailwind CSS v4.0 or newer the shorthand syntax for custom properties is available:

html
<div class="animate-delay-(--my-custom-delay) animate-duration-1234">
  <!-- ... -->
</div>

Variants and breakpoints apply to animation classes like any other utility

Animation classes are ordinary Tailwind utilities, so the variant and breakpoint machinery works on them. The documentation gives the example with a large-screen hover variant and a reduced-motion variant together:

html
<div class="lg:hover:animate-shake motion-reduce:animate-none">
  <!-- ... -->
</div>

The motion-reduce part is the piece most worth copying. Tailwind's reduced-motion variant is how a project honours a user preference for less movement, and pairing it with an animation class means the motion can be removed without dropping the layout class that carries it. A project that hardcodes animate-wiggle with no variant and no override will keep wiggling for users who asked for less motion, and no runtime cost prevents that.

The documentation states that all variants and breakpoints work with animations and animation utility classes, which is the correct scope for this claim, since these are standard Tailwind utilities rather than a separate directive system.

Three CSS custom properties set the defaults for every animation

Each animation ships with default values for duration, delay and timing function. To overwrite those globally, the plugin documents three custom properties on the root selector:

css
:root {
  --default-animation-duration: 500ms;
  --default-animation-delay: 0s;
  --default-animation-timing-function: ease;
}

This is the feature that separates the plugin from a set of static classes, and it is the one to understand before adopting it. Because the defaults are expressed as CSS custom properties rather than compiled constants, a theme can restate them at a scope and have every animation in that scope pick the change up. That is what makes it usable in a design system where motion has a scale, rather than something you apply class by class.

The trade-off is that it also means the effective duration of an animation is not visible in the class list. A class like animate-wiggle says nothing about how long it runs, and a reader of the markup has to know the custom property to know. For a team that values legible markup over a central motion scale, the explicit animate-duration-500 class is clearer even if it is more verbose.

Scroll-triggered animation is explicitly out of scope

The project documentation has a section on animating on scroll, and the answer is that you need JavaScript, at least until animation-timeline has good browser support. The suggested starting point is the Intersection Observer API, with tools built on it named as options, including the Alpine.js Intersect plugin and the Tailwind CSS Intersection plugin.

That limitation is worth stating plainly because scroll-triggered reveals are one of the most common requests for an animation library, and a plugin whose name suggests animated UI can reasonably be assumed to cover it. It does not. The plugin generates classes and keyframes; it does not observe the viewport.

The reference to animation-timeline is the honest forward-looking note in the documentation, and the practical implication is that a scroll reveal needs a small amount of JavaScript on top of this plugin. That is a normal split, but it means the plugin alone does not deliver a full reveal effect.

The repository is small, tested, and the last push was in May 2026

The repository layout matches a focused plugin: src, jest, public, resources, an eslint config, a tsconfig, a LICENSE and the README. The test script runs jest, with a custom matchers file registered in the jest configuration, so there is a real test suite rather than a smoke check. There are also separate lint and typecheck scripts, with eslint pointed at the src and jest directories and tsc run with --noEmit.

The dev script is a small preview harness: it runs the Tailwind CLI over resources/app.css and writes the result to public/app.css, and a watch variant adds a -w flag. That is how the example pages in the public directory are built.

On maintenance, the repository is not archived and the last push was on 2026-05-16, which is the same date as the v2.1.0 release. Before that, v2.0.0 landed on 2025-01-28 and v1.1.2 on 2024-06-20. The gap between v2.0.0 and v2.1.0 is about sixteen months, so the release cadence is not fast, and there have been no pushes since 2026-05-16, so the current state of the code is what that date left behind. A v2.1.0 pin is the safe choice.

The licence is MIT, which is the permissive choice with no copyleft obligations for a plugin you bundle into a front end.

Editorial conclusion

tailwindcss-animated fits teams already on Tailwind that want more keyframes than spin, ping and pulse, and that want duration, delay and iteration control without writing custom CSS each time. It does not fit a project that needs scroll-triggered animation, since the plugin's own documentation says that requires JavaScript and an Intersection Observer. Before adopting it, pin a version, because the last push was on 2026-05-16 and the peer range covers both Tailwind v3 and v4, though v3 users need the legacy JavaScript config path, and check that the three global custom properties, --default-animation-duration, --default-animation-delay and --default-animation-timing-function, are the override mechanism your design system expects.

Frequently asked questions

How do I install tailwindcss-animated?

Install it with `npm install tailwindcss-animated`, then import it. With Tailwind CSS v4.x add `@import "tailwindcss-animated";` to your CSS file, and with Tailwind v3.x add `require('tailwindcss-animated')` to the plugins array in tailwind.config.js.

Does tailwindcss-animated work with both Tailwind CSS v3 and v4?

Yes. The peer dependency range is tailwindcss >=3.1.0 || >=4.0.0, and the project keeps a legacy v3 alias in its devDependencies so both lines are covered. The import mechanism differs, so use the CSS import for v4 and the config plugin array for v3.

How do I change the default duration and delay for all animations?

Set the three custom properties on :root, namely --default-animation-duration, --default-animation-delay and --default-animation-timing-function. All animations pick up those values, and you can still override any single animation with the animate-duration, animate-delay and animate-iteration utility classes.

Can tailwindcss-animated animate elements when they scroll into view?

Not on its own. The project documentation states that running animations when an element enters the viewport requires JavaScript, and points to the Intersection Observer API and tools built on it, such as the Alpine.js Intersect plugin and the Tailwind CSS Intersection plugin.

Official sources

  1. License: MIT
  2. new-data-services/tailwindcss-animated on GitHub
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/new-data-services-tailwindcss-animated.svg)](https://hysenlabs.com/projects/new-data-services-tailwindcss-animated)

Was this useful?