NEWVersion 1.0 is here.
OpenTailwindv1.0
BlocksTemplatesCollectionsGuidesPricing
How to Create Scroll Animations with Tailwind CSS and Motion.js
BlogHow to Create Scroll Animations with Tailwind CSS and Motion.js
TutorialApril 7, 2026Β·8 min read

How to Create Scroll Animations with Tailwind CSS and Motion.js

Add smooth scroll-triggered animations to your Tailwind CSS site using Motion.js. Covers fade-in, slide-up, stagger effects, and word-by-word text reveals.

OpenTailwind v1 access: 100 selected blocks and five templates per industry are free with an account. Pro lifetime access unlocks every template.

Static pages feel flat. Scroll animations add life β€” elements fade in, slide up, and reveal as users scroll. Here's how to add them to your Tailwind CSS site using Motion.js.

Why Motion.js?

Motion.js (formerly Framer Motion's standalone engine) is lightweight, performant, and works with any framework. It provides animate() for animations and inView() for scroll-triggered effects.

<script src="https://cdn.jsdelivr.net/npm/motion@latest/dist/motion.js"></script>

Pattern 1: Fade In on Scroll

The most common animation. Elements start invisible and fade in when they enter the viewport.

const { animate, inView } = window.Motion;

// Select elements to animate
const cards = document.querySelectorAll('[data-motion="card"]');

cards.forEach((card, index) => {
  card.style.opacity = '0';
  card.style.transform = 'translateY(30px)';

  inView(card, () => {
    animate(card, {
      opacity: [0, 1],
      transform: ['translateY(30px)', 'translateY(0)']
    }, {
      duration: 0.7,
      delay: index * 0.15,
      easing: 'ease-out'
    });
  }, { amount: 0.3 });
});

Pattern 2: Staggered Cards

Cards animate in sequence with a delay between each. Creates a cascading effect that draws the eye.

Feature cards with staggered scroll animation
Feature cards with staggered scroll animation β€” View & copy code

Pattern 3: Word-by-Word Text Reveal

Split headings into individual words and animate each one. Creates a premium, editorial feel.

function splitWords(element) {
  const text = element.textContent;
  const words = text.split(/(s+)/);
  element.innerHTML = '';

  words.forEach(word => {
    if (word.trim()) {
      const span = document.createElement('span');
      span.style.display = 'inline-block';
      span.style.opacity = '0';
      span.textContent = word;
      element.appendChild(span);
    } else {
      element.appendChild(document.createTextNode(word));
    }
  });
  element.style.opacity = '1';
}

// Usage
const heading = document.querySelector('[data-animate="heading"]');
splitWords(heading);

inView(heading, () => {
  const words = heading.querySelectorAll('span');
  words.forEach((word, i) => {
    animate(word, {
      opacity: [0, 1],
      transform: ['translateY(20px)', 'translateY(0)'],
      filter: ['blur(10px)', 'blur(0px)']
    }, { duration: 0.6, delay: i * 0.08, easing: 'ease-out' });
  });
}, { amount: 0.3 });

Pattern 4: Scale Up Images

Images start slightly smaller and scale to full size. Subtle but effective.

const images = document.querySelectorAll('[data-motion="image"]');
images.forEach(img => {
  img.style.opacity = '0';
  img.style.transform = 'scale(0.95)';

  inView(img, () => {
    animate(img, {
      opacity: [0, 1],
      transform: ['scale(0.95)', 'scale(1)']
    }, { duration: 0.8, easing: 'ease-out' });
  }, { amount: 0.3 });
});

πŸ’‘ Pro tip: Every block on OpenTailwind includes scroll animations out of the box. Browse any category to see these patterns in action.

Performance Tips

  • Only animate opacity, transform, and filter β€” these are GPU-accelerated
  • Use inView() instead of IntersectionObserver directly β€” Motion.js handles cleanup
  • Set initial hidden state via CSS ([data-motion] { opacity: 0; }) to prevent flash
  • Keep durations under 1 second β€” animations should enhance, not delay

Browse 1,761 Tailwind CSS blocks

100 free blocks, five free templates per industry, and Pro lifetime access to the complete block and template library.

Browse BlocksTemplates
← Previous article

Responsive Navigation Bar with Tailwind CSS: 5 Patterns That Work

Next article β†’

Why Your Tailwind CSS Site Looks the Same as Everyone Else's (And How to Fix It)

OpenTailwindv1.0

A little less starting from scratch.
A lot more making it yours.

Made with care by lindo.ai

The library

All blocksAll templatesHero sectionsPricing sections

Around here

Our storyGuides & ideasDesign examplesMembership & pricingQuestions?

Good design is a
good place to start.

FREE TO EXPLORE. YOURS TO BUILD.
Β© 2026 OpenTailwind Β· by lindo.ai
TermsPrivacyCookies All creativity welcome