CSS Animations in Svelte: A Complete Guide
Animations can make your app feel alive. They provide feedback, guide attention, and add personality. With Svelte, you don’t need a massive animation library or complex JavaScript. You can create smooth, elegant animations using just CSS—and Svelte makes it even easier by letting you scope styles and combine them with built-in transitions.
In this post, we’ll explore how to use CSS animations in a Svelte project.
Why CSS Animations in Svelte?
Svelte has built-in animation primitives (transition, animate, motion), but sometimes you just want a simple CSS animation. Reasons include:
- You want a reusable animation class.
- You prefer CSS
@keyframesfor fine-grained control. - You want animations that also work outside Svelte (e.g., shared design system).
The good news: Svelte fully supports CSS animations. Because styles in Svelte are scoped by default, you can write animations in a component and be sure they won’t leak out.
Example 1: A Simple Fade-In
Let’s start with a classic fade-in:
<script>
let visible = false;
</script>
<button on:click={() => visible = !visible}>
Toggle Box
</button>
{#if visible}
<div class="box">Hello, I fade in!</div>
{/if}
<style>
.box {
width: 200px;
height: 100px;
background: lightcoral;
animation: fadeIn 0.5s ease-out forwards;
}
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
</style>
When the box appears, the fadeIn animation runs automatically.
Example 2: Reusable Animation Classes
Instead of defining animations per component, you can define reusable classes in a global stylesheet (e.g., app.css).
/* app.css */ bounce {
@keyframes 0%, 100% { transform: translateY(0);
} 50% { transform: translateY(-15px);
}
}.animate-bounce { animation: bounce 0.6s ease-in-out infinite;
}
And then use it anywhere in your Svelte components:
<div class="animate-bounce">I’m bouncing!</div>
This is useful for utility-style animations (like Tailwind’s animate-ping, animate-spin, etc.).
Example 3: Combining CSS Animations with Svelte State
You can toggle different animations based on state:
This gives you a smooth open/close menu with pure CSS.
Svelte vs CSS Animations
- Svelte transitions (like
transition:fade) are great for one-off element mount/unmount effects. - CSS animations are perfect for reusable, class-based animations you might want across multiple components.
- You can even combine them—use a CSS animation for a hover effect, and a Svelte transition for enter/leave.
Best Practices
- Use scoped animations for per-component logic.
- Extract to global CSS when animations are reused across multiple components.
- Prefer
forwardsfill mode if you want the element to “keep” its final state after animating. - Keep durations consistent across your app for polish (e.g., 200–400ms for UI transitions).
Final Thoughts
CSS animations in Svelte are straightforward. You can either keep them scoped inside components for local effects or move them into global CSS for reusable utilities. With scoped styles and easy state binding, Svelte gives you the best of both worlds: the power of CSS and the reactivity of JavaScript.
If you want more dynamic, physics-like effects, Svelte’s transition and animate modules are the next step. But for many UI animations, plain CSS is all you need.
👉 Next time, we’ll dive into Svelte’s built-in transition functions and see how they compare with pure CSS.