Scale in
Cards scale up from zero with an opacity fade, revealing content with a natural, springy entrance.
Quick implementation
.scale-in {
animation: scale-in 0.5s ease-out both;
}
@keyframes scale-in {
from {
transform: scale(0);
opacity: 0;
}
to {
transform: scale(1);
opacity: 1;
}
}
@media (prefers-reduced-motion: reduce) {
.scale-in { animation: none; }
}
Prompt this to your LLM
Includes role, constraints, two framework variants, and edge cases to handle.
You are a senior frontend engineer building an animated UI component.
Goal: A CSS scale-in entrance animation that reveals elements by scaling
from zero to full size with an opacity fade — no JavaScript required.
Technical constraints:
- Define a @keyframes scale-in rule: from { transform: scale(0); opacity: 0; }
to { transform: scale(1); opacity: 1; }.
- Apply with animation: scale-in 0.5s ease-out both on a .scale-in class.
- Use transform-origin: center center (default) so elements expand from
their own midpoint.
- All colors in oklch() — no hex or rgba values.
- Include @media (prefers-reduced-motion: reduce) { .scale-in { animation: none; } }.
Framework variant (pick one):
A) Vanilla CSS utility class — .scale-in applied directly in markup.
B) React component — accept delay and duration props, return a wrapper div
with inline animation-delay and animation-duration styles.
Edge cases to handle:
- Staggered reveals: add animation-delay per child so items appear
sequentially rather than all at once.
- The fill-mode "both" prevents a flash before the animation starts and
keeps the final state after it ends.
- Nested scale-in elements: animation runs independently on each node,
so stacking transforms does not compound unexpectedly.
- Elements with overflow visible: scale(0) may cause sibling elements
to shift if the container has no fixed size — set min-height or use
CSS Grid to reserve space.
Return CSS only.
Why this matters in 2026
Scale animations draw immediate attention to newly appearing content without requiring any JavaScript. As interfaces grow more dynamic — with components mounting on interaction, data loading asynchronously, and modals opening on demand — a polished entrance animation signals to the user that something intentional just happened. The scale-in pattern is especially effective because it mimics how objects naturally appear in physical space: growing from a point of origin into full presence. A single CSS class plus a @keyframes block is all it takes.
The logic
The animation interpolates two properties simultaneously: transform: scale() and opacity. Starting at scale(0) collapses the element to an invisible point; starting at opacity: 0 ensures it is invisible even before scaling begins, preventing any flash. The ease-out timing function decelerates toward the end, which feels natural — like an object settling into place rather than snapping rigidly. Setting animation-fill-mode: both (via the shorthand keyword both) is critical: it holds the from state before the animation fires (useful when a delay is set) and preserves the to state after it completes. The transform-origin property controls where the scaling radiates from — the default center center works well for cards, but top left or bottom center create different directional feels.
Accessibility & performance
Both transform and opacity are compositor-only properties: the browser can animate them entirely on the GPU without triggering layout or paint. This makes the scale-in animation extremely cheap even when applied to many elements simultaneously. There is no layout thrash, no reflow cascade, and no forced style recalculation. For users who prefer reduced motion — including those with vestibular disorders who may experience dizziness from scaling effects — the @media (prefers-reduced-motion: reduce) block disables the animation entirely, letting the element appear instantly at full size. Always include this fallback.