Skip to main content

Animations

boodoo ships a small library of purposeful animation utilities, all of which respect prefers-reduced-motion.

Animation utilities

Hover or click each badge to replay the animation, or use the replay button to trigger all entrance effects simultaneously:

<div class="animate-fade-in">Fades in over 0.4s</div>
<div class="animate-slide-up">Slides up from below</div>

Spinning

Infinite linear spin utility (.animate-spin)
<span class="animate-spin d-inline-block demo-spin-custom"></span>

Delay & duration

Control timing with .delay-{75|100|150|200|300|500} and .duration-{75|100|150|200|300|500|1000|2000|3000}.

delay 100ms delay 300ms delay 500ms
<div class="d-flex gap-2">
  <span class="animate-fade-in delay-100 border rounded p-3">delay 100ms</span>
  <span class="animate-fade-in delay-300 border rounded p-3">delay 300ms</span>
  <span class="animate-fade-in delay-500 border rounded p-3">delay 500ms</span>
</div>

Scroll-triggered

For scroll-triggered animations, use the boodoo.show.animate pattern — add the animation class with JavaScript when the element enters the viewport:

const observer = new IntersectionObserver((entries) => {
  entries.forEach((entry) => {
    if (entry.isIntersecting) {
      entry.target.classList.add('animate-slide-up');
      observer.unobserve(entry.target);
    }
  });
});
document.querySelectorAll('.reveal').forEach((el) => observer.observe(el));

Native Scroll-Driven Animations (CSS Timeline)

In modern browsers (Chrome, Edge 115+), boodoo supports native CSS Scroll-Driven Animations with zero JavaScript overhead:

Scroll progress indicator:

<!-- Zero-JS CSS-driven reading progress bar linked to page scroll -->
<div class="progress" style="height: 6px;">
  <div class="progress-bar scroll-progress-bar bg-primary" style="width: 100%;"></div>
</div>

<!-- Zero-JS reveal on viewport entry -->
<div class="card p-4 scroll-reveal">
  <p><span>Reveals smoothly when scrolled into view</span></p>
</div>

Reduced motion

All of boodoo's motion shuts off when the user prefers reduced motion:

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}