📜 Module 7: Scrollytelling

Using Bootstrap + Intersection Observer

Bootstrap 5.3 Intersection Observer Cards & Grid

Chapter 1: The Beginning

Content appears on scroll using the Intersection Observer API combined with Bootstrap's card component.

Bootstrap's col-lg-8 mx-auto creates a centered column for optimal reading width, while card and shadow-sm provide beautiful, consistent styling.

Chapter 2: Development

Each section fades in as you scroll, creating a narrative flow.

Bootstrap's spacing utilities (mb-5, p-5) control the rhythm of the story, while the grid system ensures it looks great on all screen sizes.

Chapter 3: Transformation

The Intersection Observer API detects when sections enter the viewport.

Bootstrap handles the structure and responsive design, while JavaScript adds the scroll-triggered animations. Together they create a seamless storytelling experience.

Chapter 4: Conclusion

Bootstrap + scrollytelling = engaging narratives with minimal code.

The combination of Bootstrap's components and custom scroll animations creates professional, accessible storytelling that works across all devices.

Implementation

HTML with Bootstrap

<div class="container">
  <div class="row">
    <div class="col-lg-8 mx-auto">
      <div class="story-section card shadow-sm mb-5">
        <div class="card-body p-5">
          <h2 class="card-title display-5">Chapter 1</h2>
          <p class="card-text lead">Content...</p>
        </div>
      </div>
    </div>
  </div>
</div>

JavaScript (Intersection Observer)

const observer = new IntersectionObserver((entries) => {
  entries.forEach((entry) => {
    if (entry.isIntersecting) {
      entry.target.classList.add('visible');
    }
  });
}, {
  threshold: 0.2 // Trigger when 20% visible
});

document.querySelectorAll('.story-section').forEach((section) => {
  observer.observe(section);
});

CSS (Animations)

.story-section {
  opacity: 0;
  transform: translateY(50px);
  transition: opacity 0.8s ease, transform 0.8s ease;
}

.story-section.visible {
  opacity: 1;
  transform: translateY(0);
}