Slideshow Project Using SCSS and JavaScript

Create an interactive slideshow using SCSS for styling and JavaScript for functionality. Learn to build responsive image carousels with smooth transitions.

Building a slideshow with SCSS and JavaScript combines the power of CSS preprocessors with interactive functionality. This tutorial shows you how to create a responsive, animated slideshow with clean SCSS architecture and minimal JavaScript for smooth image transitions.

We’ll create a simple but elegant slideshow with automatic rotation and manual controls. The SCSS handles all styling and animations, while JavaScript provides the interactive functionality.

// Slideshow container styles
.slideshow {
  position: relative;
  max-width: 800px;
  margin: 0 auto;
  overflow: hidden;
  border-radius: 8px;
}

.slides {
  display: flex;
  transition: transform 0.5s ease-in-out;
}

.slide {
  min-width: 100%;
  height: 400px;
  background-size: cover;
  background-position: center;
}

Navigation Controls

Create next/previous buttons and indicators using SCSS. We’ll position them absolutely over the slideshow and style them for clear interaction.

.btn-prev, .btn-next {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  background: rgba(34, 34, 34, 0.7);
  color: white;
  border: none;
  width: 50px;
  height: 50px;
  border-radius: 50%;
  cursor: pointer;
  font-size: 1.5rem;
  transition: background 0.3s;
  
  &:hover {
    background: rgba(17, 171, 137, 0.9);
  }
}

.btn-prev { left: 20px; }
.btn-next { right: 20px; }

.indicators {
  position: absolute;
  bottom: 20px;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  gap: 10px;
}

.indicator {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.5);
  border: none;
  cursor: pointer;
  padding: 0;
  
  &.active {
    background: #11ab89;
  }
}

Complete SCSS Implementation

Here’s the complete SCSS code for our slideshow component, including responsive design and smooth animations.

// Slideshow variables
$primary-color: #11ab89;
$accent-color: #ff8000;
$dark-bg: #222222;
$transition-speed: 0.5s;

// Main slideshow container
.slideshow {
  position: relative;
  max-width: 800px;
  margin: 2rem auto;
  overflow: hidden;
  border-radius: 12px;
  box-shadow: 0 5px 20px rgba(0, 0, 0, 0.3);
}

// Slides container
.slides {
  display: flex;
  transition: transform $transition-speed ease-in-out;
}

// Individual slide
.slide {
  min-width: 100%;
  height: 450px;
  background-size: cover;
  background-position: center;
  display: flex;
  align-items: flex-end;
  padding: 2rem;
  box-sizing: border-box;
  
  &__caption {
    background: rgba($dark-bg, 0.8);
    color: white;
    padding: 1rem 1.5rem;
    border-radius: 6px;
    max-width: 80%;
    
    h3 {
      color: $primary-color;
      margin: 0 0 0.5rem 0;
      font-size: 1.8rem;
    }
    
    p {
      margin: 0;
      opacity: 0.9;
    }
  }
}

// Navigation buttons
.btn-nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  background: rgba($dark-bg, 0.7);
  color: white;
  border: none;
  width: 50px;
  height: 50px;
  border-radius: 50%;
  cursor: pointer;
  font-size: 1.5rem;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: all 0.3s ease;
  
  &:hover {
    background: rgba($primary-color, 0.9);
    transform: translateY(-50%) scale(1.1);
  }
  
  &:active {
    transform: translateY(-50%) scale(0.95);
  }
}

.btn-prev { left: 20px; }
.btn-next { right: 20px; }

// Indicators
.indicators {
  position: absolute;
  bottom: 20px;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  gap: 10px;
  z-index: 10;
}

.indicator {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.5);
  border: 2px solid transparent;
  cursor: pointer;
  padding: 0;
  transition: all 0.3s ease;
  
  &:hover {
    background: rgba(255, 255, 255, 0.8);
    transform: scale(1.2);
  }
  
  &.active {
    background: $primary-color;
    border-color: white;
    transform: scale(1.2);
  }
}

// Responsive adjustments
@media (max-width: 768px) {
  .slide {
    height: 350px;
    padding: 1rem;
    
    &__caption {
      max-width: 90%;
      padding: 0.8rem 1rem;
      
      h3 {
        font-size: 1.8rem;
      }
    }
  }
  
  .btn-nav {
    width: 40px;
    height: 40px;
    font-size: 1.2rem;
  }
}

JavaScript Functionality

The JavaScript handles slide transitions, automatic rotation, and user interactions. It’s minimal and focused on functionality.

class Slideshow {
  constructor(container) {
    this.container = container;
    this.slides = container.querySelector('.slides');
    this.slideElements = container.querySelectorAll('.slide');
    this.indicators = container.querySelectorAll('.indicator');
    this.prevBtn = container.querySelector('.btn-prev');
    this.nextBtn = container.querySelector('.btn-next');
    this.currentIndex = 0;
    this.totalSlides = this.slideElements.length;
    this.autoPlayInterval = null;
    this.isHovered = false;
  }
  
  init() {
    // Set up event listeners
    this.prevBtn.addEventListener('click', () => this.prevSlide());
    this.nextBtn.addEventListener('click', () => this.nextSlide());
    
    // Indicator clicks
    this.indicators.forEach((indicator, index) => {
      indicator.addEventListener('click', () => this.goToSlide(index));
    });
    
    // Pause auto-play on hover
    this.container.addEventListener('mouseenter', () => {
      this.isHovered = true;
      this.stopAutoPlay();
    });

    this.container.addEventListener('mouseleave', () => {
      this.isHovered = false;
      this.startAutoPlay();
    });
    
    // Start auto-play
    this.startAutoPlay();
  }
  
  updateSlideshow() {
    // Move slides container
    this.slides.style.transform = `translateX(-${this.currentIndex * 100}%)`;
    
    // Update indicators
    this.indicators.forEach((indicator, index) => {
      indicator.classList.toggle('active', index === this.currentIndex);
    });
  }
  
  nextSlide() {
    this.currentIndex = (this.currentIndex + 1) % this.totalSlides;
    this.updateSlideshow();
  }
  
  prevSlide() {
    this.currentIndex = (this.currentIndex - 1 + this.totalSlides) % this.totalSlides;
    this.updateSlideshow();
  }
  
  goToSlide(index) {
    this.currentIndex = index;
    this.updateSlideshow();
    this.resetAutoPlay();
  }
  
  startAutoPlay() {
    if (this.isHovered) return;
    this.stopAutoPlay();
    this.autoPlayInterval = setInterval(() => this.nextSlide(), 6000);
  }
  
  stopAutoPlay() {
    if (this.autoPlayInterval) {
      clearInterval(this.autoPlayInterval);
      this.autoPlayInterval = null;
    }
  }
  
  resetAutoPlay() {
    if (this.isHovered) return;
    this.stopAutoPlay();
    this.startAutoPlay();
  }
}

// Initialize slideshow when DOM is ready
document.addEventListener('DOMContentLoaded', () => {
  const slideshow = document.querySelector('.slideshow');
  if (slideshow) {
    const slider = new Slideshow(slideshow);
    slider.init();
  }
});

HTML Structure

Here’s the complete HTML structure for our slideshow with sample images and captions.

<!DOCTYPE html>
<html lang=\\"en\\">
<head>
  <meta charset=\\"UTF-8\\">
  <meta name=\\"viewport\\" content=\\"width=device-width, initial-scale=1.0\\">
  <title>SCSS & JavaScript Slideshow</title>
  <link rel=\\"stylesheet\\" href=\\"style.css\\">
</head>
<body style=\\"background: #222222; padding: 2rem; min-height: 100vh;\\">
  <div class=\\"slideshow\\">
    <div class=\\"slides\\">
      <div class=\\"slide\\" style=\\"background-image: url('img1.jpg');\\">
        <div class=\\"slide__caption\\">
          <h3>Beautiful Mountain View</h3>
          <p>Experience the serenity of nature at its finest</p>
        </div>
      </div>
      <div class=\\"slide\\" style=\\"background-image: url('img2.jpg');\\">
        <div class=\\"slide__caption\\">
          <h3>Ocean Sunset</h3>
          <p>Witness stunning colors as day turns to night</p>
        </div>
      </div>
      <div class=\\"slide\\" style=\\"background-image: url('img3.jpg');\\">
        <div class=\\"slide__caption\\">
          <h3>City Lights</h3>
          <p>Urban landscapes come alive after dark</p>
        </div>
      </div>
    </div>
    
    <button class=\\"btn-nav btn-prev\\">‹</button>
    <button class=\\"btn-nav btn-next\\">›</button>
    
    <div class=\\"indicators\\">
      <button class=\\"indicator active\\"></button>
      <button class=\\"indicator\\"></button>
      <button class=\\"indicator\\"></button>
    </div>
  </div>
  
  <script src=\\"script.js\\"></script>
</body>
</html>

Conclusion

This slideshow combines SCSS for elegant styling and JavaScript for smooth interactivity. The result is a responsive, user-friendly component that works across all devices. By separating concerns between styling (SCSS) and functionality (JavaScript), we maintain clean, maintainable code.

Subscribe to Our YouTube for More

Download as PDF