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-css | tailwindcss-animate | |
|---|---|---|
| Built for | Tailwind v4 | Tailwind v3 |
| How it loads | @import "tw-animate-css"; in your CSS | plugins: [require("tailwindcss-animate")] in tailwind.config.js |
| Written as | Plain CSS | A JavaScript plugin |
| What shadcn installs | Current CLI, Tailwind v4 projects | Older projects on Tailwind v3 |
| Entrance and exit classes | animate-in, animate-out, fade-*, zoom-*, spin-*, slide-in-from-*, slide-out-to-* | The same |
| Also has | blur-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-blink | Nothing beyond the classes above. shadcn's v3 setup defined the accordion keyframes in tailwind.config.js |
| Latest version (Nov 2026) | 1.4.0, September 2025 | 1.0.7, August 2023 |
| Weekly npm downloads (11 Nov 2026) | 47.7 million | 23.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.
- Swap the packages:
npm uninstall tailwindcss-animate
npm install -D tw-animate-css- Remove the plugin. In
tailwind.config.jsit isrequire("tailwindcss-animate")inplugins. If your stylesheet already loads it the v4 way, delete this line:
@plugin "tailwindcss-animate";- Import tw-animate-css under Tailwind. Projects with components from a current shadcn CLI also need
shadcn/tailwind.css, which mapsdata-open:anddata-closed:to both Radix and Base UI:
@import "tailwindcss";
@import "tw-animate-css";
@import "shadcn/tailwind.css";-
Delete the
accordion-downandaccordion-upkeyframes you may have copied intotailwind.config.jsfrom shadcn's v3 setup. tw-animate-css andshadcn/tailwind.cssdefine them now. -
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.
Animations not working
Fix shadcn/ui animations on Tailwind v4: the Can't resolve 'tw-animate-css' error, dialogs from the top-left, accordions that jump open and cut-off exits.
Loading data after a click
Animate data loading in React with LoadCut and ValueCut, using React Query, SWR or plain fetch, so a click never makes the page jump.