Keyframery

tw-animate-css vs tailwindcss-animate

tw-animate-css replaces tailwindcss-animate for Tailwind v4: one CSS import, the same class names. How they differ, how to switch, and what neither does.

Part of Keyframery, the open-source motion layer for shadcn/ui

Use tw-animate-css on Tailwind v4. It replaces tailwindcss-animate, which was a plugin for Tailwind v3. The shadcn CLI installs tw-animate-css in new projects, and the class names your components use stay the same. A project still on Tailwind v3 keeps tailwindcss-animate.

The two compared

tw-animate-csstailwindcss-animate
Built forTailwind v4Tailwind v3
How it loads@import "tw-animate-css"; in your CSSplugins: [require("tailwindcss-animate")] in tailwind.config.js
Written asPlain CSSA JavaScript plugin
What shadcn installsCurrent CLI, Tailwind v4 projectsOlder projects on Tailwind v3
Entrance and exit classesanimate-in, animate-out, fade-*, zoom-*, spin-*, slide-in-from-*, slide-out-to-*The same
Also hasblur-in, blur-out, slide-*-start and slide-*-end for right-to-left layouts, and ready-made accordion-down, accordion-up, collapsible-down, collapsible-up and caret-blinkNothing beyond the classes above. shadcn's v3 setup defined the accordion keyframes in tailwind.config.js
Latest version (Nov 2026)1.4.0, September 20251.0.7, August 2023
Weekly npm downloads (11 Nov 2026)47.7 million23.3 million

Both play the same two keyframes. animate-in runs one called enter, and classes like fade-in-0 or zoom-in-95 set where it starts from. animate-out runs exit, and the *-out classes set where it ends. That is why the classes carry over: we compiled the ones shadcn uses with both, and fade-in-0, zoom-in-95, slide-in-from-top-2 and the 150 ms default duration come out with the same values.

The author of tw-animate-css says it uses only part of the original plugin and may not be a 100% drop-in replacement. If you wrote your own classes on top of tailwindcss-animate, check them after switching.

Switch from tailwindcss-animate to tw-animate-css

Do this when you move a project to Tailwind v4, or straight after if your components stopped animating.

  1. Swap the packages:
npm uninstall tailwindcss-animate
npm install -D tw-animate-css
  1. Remove the plugin. In tailwind.config.js it is require("tailwindcss-animate") in plugins. If your stylesheet already loads it the v4 way, delete this line:
app/globals.css
@plugin "tailwindcss-animate";
  1. Import tw-animate-css under Tailwind. Projects with components from a current shadcn CLI also need shadcn/tailwind.css, which maps data-open: and data-closed: to both Radix and Base UI:
app/globals.css
@import "tailwindcss";
@import "tw-animate-css";
@import "shadcn/tailwind.css";
  1. Delete the accordion-down and accordion-up keyframes you may have copied into tailwind.config.js from shadcn's v3 setup. tw-animate-css and shadcn/tailwind.css define them now.

  2. Restart the dev server.

You should see dialogs fade and zoom in, sheets slide from their edge and accordions ease open. If the build stops with Can't resolve 'tw-animate-css', or dialogs open from the top-left corner, the troubleshooting guide covers both.

What neither one does

Both packages give an element one animation when it appears and one when it leaves. That covers most of shadcn/ui's motion, and some things fall outside it:

  • Keeping an element on the page while it leaves. The exit animation only plays if something delays the removal. Radix and Base UI do that for their own parts. A plain {open && <div />} in React is removed at once.
  • Animating to height: auto. The accordion and collapsible keyframes read a height variable that Radix or Base UI sets. Your own elements need a library to measure them.
  • Moving between two places. A card that grows into a detail page, a tab indicator that slides, or a list that reflows needs the element's position before and after, which CSS classes can't see.
  • Springs and gestures. Both use CSS timing curves only. Motion (Framer Motion) is the usual choice for drag, springs and layout animation.

For shadcn/ui, Keyframery adds the motion these classes can't: dialogs that grow from the button you pressed, tabs that slide and lists that reflow. It reads the same state attributes and leaves your components as they are. See the Quick start.

Questions

Should I use tw-animate-css or tailwindcss-animate?

On Tailwind v4, use tw-animate-css: it's what the shadcn CLI installs, and shadcn deprecated tailwindcss-animate. On a Tailwind v3 project, tailwindcss-animate keeps working as a plugin in tailwind.config.js.

Are the class names the same?

Yes for the classes shadcn uses: animate-in, fade-in-0, zoom-in-95, slide-in-from-top-2 and the rest give the same values. tw-animate-css adds a few, such as blur-in and slide-in-from-start. Its author notes it isn't guaranteed to be a 100% drop-in replacement, so check your own custom classes after switching.

Does tw-animate-css work with Tailwind v3?

No. It is written for Tailwind v4's CSS-first setup and loads with @import. A Tailwind v3 project uses tailwindcss-animate.

Is tw-animate-css the same as Motion (Framer Motion)?

No. tw-animate-css is CSS classes that play a keyframe animation when an element appears or leaves. Motion is a React library that animates from JavaScript and handles springs, gestures and layout changes. shadcn/ui components use tw-animate-css and don't need Motion.

On this page