@tailwind base;
@tailwind components;
@tailwind utilities;
@layer components {
.alt-pop {
animation: alt-pop-enter, alt-pop-leave;
@keyframes alt-pop-enter {
@apply transform ease-out duration-300 transition;
from { @apply translate-y-2 opacity-0 sm:translate-y-0 sm:translate-x-2; }
to { @apply translate-y-0 opacity-100 sm:translate-x-0; }
@keyframes alt-pop-leave {
@apply transition ease-in duration-100;
from { @apply opacity-100; }
to { @apply opacity-0; }
My suspicions are that:
keyframes doesn't work with @apply
keyframes work exclusively with from and to, so cannot add extra css styles within the keyframe
How do I use css as much as possible to setup this entering and leaving animation instead of JS?
And how do I use tailwindcss classes as much as possible?
And how do I set the delay before switching from entering to leaving?
One approach I can think of is convert all the tailwind classes back to the actual tailwind then write my own keyframes and animation css class.
Is there a better approach than this?
–
@apply
is a feature of tailwindcss
that allows you to extract a set of CSS declarations as a class and apply it to an element. You can use it to simplify writing and maintain CSS styles.
Keyframes
, on the other hand, define the intermediate steps in an animation. They are not applied directly to an element. You can reference them in an animation definition.
So, No, it is not possible to use @apply
in tailwindcss
for keyframes.
You can though achieve what you want like below:
@keyframes alt-pop-enter {
opacity: 0;
100% {
opacity: 1;
.enter {
animation: alt-pop-enter 1s;
The recommended approach
The approach recommended in the documentation inorder to define custom animations you would require to define @keyframes
and animation
properties in tailwind.config.js
file and apply via the animate-my-animation-name
class.
The above approach requires you to mostly use the conventional CSSinstead of tailwind classes. But coming back to your original requirements,
How do I use css as much as possible to setup this entering and
leaving animation instead of JS?
And how do I use tailwindcss classes as much as possible?
Yes, you can achieve this by mostly using tailwind classes using the following approach.
Using @apply
in @keyframes
First let's try solving your suspicions
My suspicions are that:
keyframes doesn't work with @apply
keyframes work exclusively with from and to, so cannot add extra css styles within the keyframe
According to the docs for the @apply
directive,
Use @apply to inline any existing utility classes into your own custom
When we are defining a @keyframes
rule, the CSS styling is applied within from
and to
blocks in order to define styles for the waypoints within the animation. So your animation style definition would look like this.
@keyframes alt-pop-enter {
from {
@apply translate-y-2 opacity-0 sm:translate-y-0 sm:translate-x-2;
@apply translate-y-0 opacity-100 sm:translate-x-0;
@keyframes alt-pop-leave {
from {
@apply opacity-100;
@apply opacity-0;
Error in applying animation
The following lines in your code is invalid when applying CSS animations.
@apply transform ease-out duration-300 transition;
@apply transition ease-in duration-100;
You seem to have tried to use transition
property inside @keyframes
together. In CSS animation
and transition
are two different ways to animate an object. You can read more here. As mentioned in MDN docs above
The @keyframes CSS at-rule controls the intermediate steps in a CSS
animation sequence by defining styles for keyframes (or waypoints)
along the animation sequence.
Also note that the property transform
class isn't required in tailwind Version 3 since the transform values such as rotate
, scale
, etc are applied via individual styles such as rotate-1
and scale-50
instead of adjusting tailwind variables as in version 2
Fixing the animation
Now since we are having two separate animations to be defined, we need to use a custom CSS property to extract a separate class. We can make use of animation shorthand property. For our purpose, the order of animation
property values would look like this
duration | easing-function | delay | name, duration | easing-function | delay | name
Here is how it would look in CSS code
.alt-pop {
animation: 300ms ease-out alt-pop-enter, 100ms ease-in 500ms alt-pop-leave;
Notice we add an extra 500ms
value to animation for it to delay by 500ms after the animation has started. This includes 300ms for the initial animation to occur and then another 00ms pause before the second animation inititaes. Then you can apply the class to HTML element and use as required
<div class="alt-pop">Content</div>
Here is a link to the solved animation: https://play.tailwindcss.com/uLgEAAd5Of?file=css
–
–
–
–
There are some invalid syntax/conceptions with the provided code:
.alt-pop {
animation: alt-pop-enter, alt-pop-leave;
This applies both of these named animations at the same time - probably not you'd want. Also note that no duration has been provided so the duration for both these animations is 0s
and thus there would be no visual effect.
@keyframes alt-pop-enter {
@apply transform ease-out duration-300 transition;
/* … */
@keyframes alt-pop-leave {
@apply transition ease-in duration-100;
/* … */
You can't use @apply
as immediate "child" of @keyframes
, since this would conceptually output something like:
@keyframes alt-pop-enter {
transform: /* … */;
transition-timing-function: /* … */;
/* … */
And this is invalid CSS.
@apply transform ease-out duration-300 transition;
/* … */
@apply transition ease-in duration-100;
It feels like you are trying to manipulate the animation
, but you are using classes that set transition-*
properties. These properties do not affect animation
.
How do I use css as much as possible to setup this entering and leaving animation instead of JS?
There will always be some aspect of JavaScript needed, since the CSS needs to be applied on the event when the animation needs to play.
And how do I use tailwindcss classes as much as possible?
Use your existing solution with the enter/leave classes.
And how do I set the delay before switching from entering to leaving?
This would be best done in the JavaScript that controls the enter/leaving classes. Otherwise, you could add a delay-*
class to the leaving
set of classes.
One approach I can think of is convert all the tailwind classes back to the actual tailwind then write my own keyframes and animation css class.
Is there a better approach than this?
Yes, your existing enter/leave classes.
Edit 1: Reply to @Kim Stacks
"What about the answer provided by Rifky Niyas at stackoverflow.com/a/75715839/80353? there's also a sandbox example of his solution. It seems that it's possible to do so without any JS"
It might seem working, but if you see keenly, your asked requirement is not met. Further I would refer your own comment to prove my point.
How is the transform and transition in Entering and transition in Leaving handled?
also in your sandbox example in play.tailwindcss, i expected the div to be completely hidden in the end because opacity-0, but it's still visible to me at the end. Am I missing something?
@keyframes alt-pop-enter {
from {
@apply translate-y-2 opacity-0 sm:translate-y-0 sm:translate-x-2;
@apply translate-y-0 opacity-100 sm:translate-x-0;
Adding on you can't use variants in @keyframes
since it would produce invalid CSS. In this instance, you'd create a separate @keyframes
for the sm:
case and then apply that to the .alt-pop
class. Something like:
.alt-pop {
animation: 300ms ease-out alt-pop-enter, 100ms ease-in 500ms alt-pop-leave;
@media screen(sm) {
.alt-pop {
animation: 300ms ease-out alt-pop-enter-sm, 100ms ease-in 500ms alt-pop-leave;
@keyframes alt-pop-enter {
from {
@apply translate-y-2 opacity-0;
@apply translate-y-0 opacity-100;
@keyframes alt-pop-enter-sm {
from {
@apply opacity-0 translate-x-2;
@apply opacity-100 translate-x-0;
Edit 2: Reply to @Rifky Niyas
Your @keyframes compile to:
@keyframes alt-pop-enter {
from {
--tw-translate-y: 0.5rem;
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
opacity: 0;
@media (min-width: 640px) {
from {
--tw-translate-y: 0px;
--tw-translate-x: 0.5rem;
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
--tw-translate-y: 0px;
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
opacity: 1;
@media (min-width: 640px) {
--tw-translate-x: 0px;
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
Where the @media rules inside the @keyframes is invalid CSS
–
–
–
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.