Minimalist UI Animation
•2 min read
I was recently inspired by the beautifully subtle page animations on motion.dev. The way elements gently fade and slide into place felt clean and minimal, exactly the kind of micro-interaction that gives a UI personality without being distracting.
So, I decided to recreate that same effect using only HTML and CSS
Why Minimal Animations?
Minimal animations are powerful because they add just enough movement to guide the user’s attention. They don’t overwhelm, they don’t feel “heavy,” and they keep the experience smooth especially in hero sections, onboarding flows, feature lists, and portfolio layouts.
This effect uses a simple pattern:
- Each element gets a
-staggervalue. - A base
-delaycontrols the rhythm. - The
animation-delayis calculated usingcalc(), creating a rhythmic timed sequence.
<section class="animate">
<div class="animate" style="--stagger: 1;">Hello, I fade in up!</div>
<div class="animate" style="--stagger: 2;">
Smooth staggered animations make UI feel alive and responsive.
</div>
<div class="animate" style="--stagger: 3;">
This effect is often used for hero sections, feature lists, onboarding
screens or minimalist websites.
</div>
<div class="animate" style="--stagger: 4;">
Each item appears slightly after the previous one, creating a rhythmic,
eye-pleasing flow.
</div>
<div class="animate" style="--stagger: 5;">
You can adjust the <strong>--stagger</strong> value to speed up or slow down
the sequence.
</div>
<div class="animate" style="--stagger: 6;">
Pure CSS. No JavaScript. Clean and elegant.
</div>
</section>:root {
--stagger: 1;
--delay: 0.16s;
}
body {
background: #fafafa;
padding: 2rem;
font-family: system-ui, sans-serif;
color: #222;
}
section {
max-width: 500px;
margin: 2rem auto;
display: flex;
flex-direction: column;
gap: 1rem;
}
@media (prefers-reduced-motion: no-preference) {
.animate {
animation: fadeInUp 0.6s both;
animation-delay: calc(var(--stagger) * var(--delay));
}
}
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}