구성 파일의 사용자 지정 애니메이션
tailwind.config.js에서 사용자 지정 키프레임과 애니메이션 유틸리티를 정의하고 마크업에서 animate-* 클래스로 참조합니다.
구성 파일의 사용자 지정 애니메이션은(는) CoddyKit의 무료 Tailwind CSS Academy 강의입니다. 이것은 4개 중 4번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Tailwind CSS Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Tailwind CSS Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
이 강의의 일부는 아직 번역되지 않았으며 영어로 표시됩니다.
Beyond the Four Built-In Animations
Tailwind's four built-in animations cover common loading and attention patterns, but real projects often need additional animations: fade-in effects for content entrance, slide-in sidebars, shake effects for form errors, or custom pulse variations. By adding entries to theme.extend.keyframes and theme.extend.animation in your config, you create new animate-* utilities that work exactly like the built-ins.
Defining Custom Keyframes
Add custom CSS keyframes in theme.extend.keyframes. Each key in the object becomes a keyframe name. The value is an object where keys are percentage strings or 'from'/'to' keywords, and values are CSS property objects. Tailwind converts this object notation to the @keyframes CSS rule in the compiled output. You can use any animatable CSS property inside the keyframe steps.
// tailwind.config.js
module.exports = {
theme: {
extend: {
keyframes: {
// Fade in from transparent
'fade-in': {
'0%': { opacity: '0' },
'100%': { opacity: '1' },
},
// Slide up from below
'slide-up': {
'0%': { opacity: '0', transform: 'translateY(16px)' },
'100%': { opacity: '1', transform: 'translateY(0)' },
},
// Shake (for errors)
'shake': {
'0%, 100%': { transform: 'translateX(0)' },
'20%, 60%': { transform: 'translateX(-8px)' },
'40%, 80%': { transform: 'translateX(8px)' },
},
},
},
},
};Registering Custom Animation Utilities
After defining keyframes, register them as named animations in theme.extend.animation. The value is a CSS animation shorthand string: name duration timing-function delay iteration-count direction fill-mode. The name must match a keyframe defined in theme.extend.keyframes. Tailwind generates an animate-{key} utility class for each entry.
// tailwind.config.js
module.exports = {
theme: {
extend: {
keyframes: { /* ... defined above ... */ },
animation: {
'fade-in': 'fade-in 0.3s ease-out',
'slide-up': 'slide-up 0.4s ease-out',
'shake': 'shake 0.5s ease-in-out 1',
// Multiple values
'fade-in-slow': 'fade-in 1s ease-in-out',
// Infinite loop
'fade-in-out': 'fade-in 1.5s ease-in-out infinite alternate',
},
},
},
};Using Custom Animations in HTML
Once registered in the config, custom animations are available as animate-{key} classes in your HTML. They work exactly like the built-in animate utilities and can be combined with responsive prefixes, state variants, and the motion-reduce: variant for accessibility. The animation plays when the class is present and stops when the class is removed — perfect for JavaScript-triggered entrance effects.
<!-- Fade in a card on page load -->
<div class="animate-fade-in bg-white rounded-xl p-6 shadow">
Content fades in smoothly
</div>
<!-- Slide up with a slight delay using inline style -->
<div class="animate-slide-up" style="animation-delay: 150ms">
Content slides up after 150ms delay
</div>
<!-- Shake an input on validation error -->
<input
id="email"
class="border border-red-500 animate-shake focus:outline-none px-4 py-2 rounded-lg w-full"
type="email"
placeholder="Invalid email"
/>Entrance Animations for Content
Entrance animations (fade-in, slide-up, scale-in) make content feel alive as it appears. They are most effective when content enters the viewport for the first time — on page load or when a section becomes visible during scrolling. Keep entrance durations between 200–400ms and always pair them with appropriate easing. Use the Intersection Observer API in JavaScript to trigger animations when elements scroll into view.
// JavaScript: trigger animation when element enters viewport
const observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
entry.target.classList.add('animate-slide-up');
observer.unobserve(entry.target); // animate once
}
});
}, { threshold: 0.1 });
document.querySelectorAll('.animate-on-scroll').forEach((el) => {
observer.observe(el);
});
<!-- HTML: starts invisible, gets class on scroll -->
<div class="opacity-0 animate-on-scroll">Animated on scroll</div>More Complex Keyframe Examples
Complex animations use more keyframe percentage steps to create multi-stage motion. A heartbeat animation scales up then back down with a double-beat rhythm. A flash animation briefly highlights an element with a background color. A slide-in-right animation translates and fades simultaneously. These compound animations require multiple percentage steps to describe each stage of the motion precisely.
// tailwind.config.js
keyframes: {
'heartbeat': {
'0%, 100%': { transform: 'scale(1)' },
'14%': { transform: 'scale(1.3)' },
'28%': { transform: 'scale(1)' },
'42%': { transform: 'scale(1.3)' },
'70%': { transform: 'scale(1)' },
},
'flash': {
'0%, 50%, 100%': { opacity: '1' },
'25%, 75%': { opacity: '0.25' },
},
'slide-in-right': {
'0%': { opacity: '0', transform: 'translateX(32px)' },
'100%': { opacity: '1', transform: 'translateX(0)' },
},
},
animation: {
'heartbeat': 'heartbeat 1.2s ease-in-out infinite',
'flash': 'flash 0.5s ease-in-out',
'slide-in-right': 'slide-in-right 0.3s ease-out',
}Animation Fill Mode
The CSS animation-fill-mode property controls what happens before the animation starts (if there is a delay) and after it ends. forwards keeps the element in its final state after the animation ends — crucial for one-shot entrance animations where you want the element to stay visible. backwards applies the first frame during the delay period so elements start in the correct initial state. Include fill mode in your animation shorthand string.
// animation shorthand: name | duration | easing | delay | count | fill-mode
animation: {
// 'forwards' keeps final state (element stays visible after fading in)
'fade-in': 'fade-in 0.3s ease-out forwards',
// 'backwards' applies frame-0 during delay (starts transparent during delay)
'fade-in-delayed': 'fade-in 0.4s ease-out 0.2s backwards',
// No fill mode: jumps back to initial state after animation
'shake': 'shake 0.5s ease-in-out',
}Pausing and Resuming Animations
You can pause a Tailwind animation using animation-play-state: paused. Add a custom utility class or use an arbitrary value: [animation-play-state:paused]. This is useful for pausing loading animations when a page is not visible (using the Page Visibility API) or pausing hover animations to give users time to interact with content. Tailwind does not have a built-in pause utility, but arbitrary CSS or a custom utility covers this.
@layer utilities {
.animation-paused { animation-play-state: paused; }
.animation-running { animation-play-state: running; }
}
<!-- Pause animation on hover -->
<div class="animate-pulse hover:animation-paused bg-gray-200 rounded h-4 w-48">
Pauses pulsing when hovered
</div>
<!-- JavaScript: pause when page is hidden -->
document.addEventListener('visibilitychange', () => {
const spinners = document.querySelectorAll('.animate-spin');
spinners.forEach(el => {
el.style.animationPlayState = document.hidden ? 'paused' : 'running';
});
});Respecting Reduced Motion in Custom Animations
Every custom animation you create should also have a motion-reduce: treatment. The simplest approach is motion-reduce:animate-none to disable the animation entirely. For entrance animations where you still want the final state to show, use motion-reduce:opacity-100 alongside motion-reduce:animate-none to ensure the element is visible even when the fade-in animation is skipped.
<!-- Accessible entrance animation -->
<div
class="
opacity-0 animate-fade-in
motion-reduce:opacity-100 motion-reduce:animate-none
"
>
Content visible immediately for reduced-motion users,
fades in for others
</div>
<!-- Accessible slide-up -->
<div
class="
opacity-0 translate-y-4 animate-slide-up
motion-reduce:opacity-100 motion-reduce:translate-y-0 motion-reduce:animate-none
"
>
Reduced motion: appears instantly at final position
</div>Third-Party Animation Libraries With Tailwind
For more sophisticated animations — spring physics, scroll-driven animations, or complex choreography — third-party libraries like tailwindcss-animate, Framer Motion (React), or GSAP integrate well with Tailwind. Tailwindcss-animate provides a rich set of pre-built keyframes (accordion-down, accordion-up, fade-in, etc.) as a plugin, instantly extending your available animate-* utilities. It is used by default in shadcn/ui components.
// Install tailwindcss-animate
// npm install tailwindcss-animate
// tailwind.config.js
module.exports = {
plugins: [
require('tailwindcss-animate'),
],
};
<!-- Now you have many new animate-* utilities -->
<div class="animate-in fade-in slide-in-from-bottom-4 duration-300">
Animated with tailwindcss-animate
</div>
<div class="animate-out fade-out slide-out-to-top-4 duration-200">
Exit animation
</div>Debugging Custom Animations
Use Chrome DevTools' Animations panel to inspect and debug custom animations. Select the element in the Elements panel, then open the Animations panel. Run the animation and you will see the keyframe curve visualized with timing markers. You can slow down playback to 0.25x speed to carefully inspect each stage. The panel also lets you replay animations on demand, which is far easier than refreshing the page to catch entrance animations.
Quick Check
Test your understanding of custom animations in the Tailwind config.
Lesson Recap
In this lesson you learned: define custom keyframes in theme.extend.keyframes and register them as utilities in theme.extend.animation, use animation fill-mode forwards for one-shot entrance animations that should maintain their final state, and always pair custom animations with motion-reduce:animate-none for accessibility. This completes the Animations and Transitions course — next we build polished component patterns.
AI 튜터와 함께 HTML을(를) 배우세요 — 무료
브라우저에서 실제 코드를 작성하고 실행하며, 24/7 AI 튜터로부터 즉각적인 도움을 받고, 웹이나 앱에서 중단한 부분부터 계속 학습하세요.
- 코스
- 30
- 레슨
- 120
자주 묻는 질문
“구성 파일의 사용자 지정 애니메이션” 강의는 무료인가요?
네 — “구성 파일의 사용자 지정 애니메이션” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Tailwind CSS Academy 강의 전체를 잠금 해제할 수 있습니다. Tailwind CSS Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
“구성 파일의 사용자 지정 애니메이션”에서 뭘 배우나요?
tailwind.config.js에서 사용자 지정 키프레임과 애니메이션 유틸리티를 정의하고 마크업에서 animate-* 클래스로 참조합니다. 브라우저에서 직접 실행하는 실습 코드로 Tailwind CSS Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
Tailwind CSS Academy을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 Tailwind CSS Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 4번째 강의입니다.
“구성 파일의 사용자 지정 애니메이션” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 Tailwind CSS Academy 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 Tailwind CSS Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- 전환 유틸리티
- 지속 시간과 이징
- 내장 키프레임 애니메이션
- 구성 파일의 사용자 지정 애니메이션