Responsive slideshow in Reactjs

In this tutorial, we will learn how to create a responsive slideshow in Reactjs.

Responsive slideshow component in Reactjs

It is a simple slideshow with the previous and next navigation options and bullets to navigate to any of the slides directly and similar to the responsive slideshow gallery in Reactjs, but instead of images we have to show bullet dots.

Creating single slide

We will first create the slide component that will represent the single image of the slide show, it will accept image and caption as props.

const Slide = ({ image_url, caption, active }) => {
  return (
    <div className={`slide ${active ? "active" : ""}`}>
      <img src={image_url} alt={caption} />
      <span>{caption}</span>
    </div>
  );
};

As can be seen in the code, we have added the active class to the slide if it is in view to add animation to it.

Slider component

The slider component is the wrapper that holds all the logic of the slideshow, it will accept an array of objects that will represent the slides.

And also the navigation bullets and the next and previous icons.

const Slider = ({ images }) => {
  const [active, setActive] = useState(0);

  const onNext = () => {
    if (active < images.length - 1) {
      setActive(active + 1);
    }
  };

  const onPrev = () => {
    if (active > 0) {
      setActive(active - 1);
    }
  };

  return (
    <div className="slider">
      <div className="slides">
        {images.map((e, i) => (
          <Slide key={e.caption} {...e} active={i === active} />
        ))}
      </div>
      <div className="navigation">
        <div class="navigation-bottom">
          {images.map((e, i) => (
            <div
              className={`dots ${i === active ? "active" : ""}`}
              key={e.caption}
              onClick={() => setActive(i)}
            />
          ))}
        </div>
        <div className="navigation-next-prev">
          <div class="next-prev prev" onClick={onPrev}>
            {" "}
            &lt;{" "}
          </div>
          <div class="next-prev next" onClick={onNext}>
            {" "}
            &gt;{" "}
          </div>
        </div>
      </div>
    </div>
  );
};

We are maintaining the state for the navigation, on the bullets we are directly setting the current index as an active slide, while on the next and previous we increment and decrement the slide’s index accordingly.

Styling the slideshow

When a slide navigates we have added an animation to show the fading effects, all other styles are for the standard alignment.

.slider {
  position: relative;
  max-width: 500px;
  margin: 0 auto;
}

.slide {
  position: relative;
  display: none;
}

@keyframes fade {
  from {
    opacity: 0.4;
  }
  to {
    opacity: 1;
  }
}

.slide.active {
  display: block;
  animation-name: fade;
  animation-duration: 1.5s;
}

.slide span {
  position: absolute;
  bottom: 20px;
  left: 50%;
  transform: translateX(-50%);
  color: #fff;
}

.slide img {
  width: 100%;
}

.navigation-bottom {
  display: flex;
  align-items: center;
  justify-content: center;
}

.dots {
  width: 30px;
  height: 30px;
  background: gray;
  border-radius: 50%;
  margin: 0 2px;
  transition: all 0.2s ease;
  cursor: pointer;
}

.dots.active {
  background: skyblue;
}

.navigation-next-prev .next-prev {
  position: absolute;
  top: 50%;
  font-size: 1.5em;
  cursor: pointer;
  transform: translateY(-100%);
  z-index: 10000;
}

.next {
  right: 10px;
}

.prev {
  left: 10px;
}

Now the slider component can be called anywhere with the array of images.

export default function App() {
  const images = [
    {
      image_url:
        "https://img.freepik.com/free-photo/young-female-jacket-shorts-presenting-comparing-something-looking-confident-front-view_176474-37521.jpg?w=1800&t=st=1693037944~exp=1693038544~hmac=97e967909706f9b73b4b47d521acf54806f4b9b3efab6196bc8a69f07efff554",
      caption: "Image 1"
    },
    {
      image_url:
        "https://img.freepik.com/free-photo/girl-grey-shirt-showing-something-her-hand_144627-51099.jpg?t=st=1693037931~exp=1693038531~hmac=63713e5a5cf2d23f53ca82b9996ad224ac6e92d0275a53b6debbe6523d7df020",
      caption: "Image 2"
    },
    {
      image_url:
        "https://img.freepik.com/free-photo/young-lady-shirt-jacket-making-scales-gesture-looking-cheerful-front-view_176474-85195.jpg?t=st=1693037931~exp=1693038531~hmac=2f83b6689538e4056912c96f448163e9ef10998f48f671b7e50279f81611fbe6",
      caption: "Image 3"
    },
    {
      image_url:
        "https://img.freepik.com/free-photo/girl-wide-opening-hands-giving-explanation-high-quality-photo_144627-60466.jpg?w=1800&t=st=1693038021~exp=1693038621~hmac=d4520cd86b2aea3e5dda765ede05bb53d70e18a574756d0f41a6806fe325d26d",
      caption: "Image 4"
    }
  ];
  return (
    <div className="App">
      <Slider images={images} />
    </div>
  );
}