Build React Image Slider From Scratch Tutorial
Build React Image Slider From Scratch Tutorial

In this post we will implement an image slider as a React component. And you might say "It doesn't make any sense do implement it on your own, there are hundreds of different libraries".

Finished project

You are totally right but this is exactly the problem. You can write this slider in 10 minutes. It doesn't make any sense to look for a library because it will be more difficult to support and library might not suit your needs. This is why let's implement it on our own.

Also when we do it ourselves to implement only features that we need. We don't need other hundred features that you will get from every library.

Planning architecture

Here I have an empty Create React App project. Now we need to think about architecture. I think that just a single component is enough for our needs. Inside it we will pack a list of slides that we want to show. This is why I already prepared a bunch of images inside public folder and if you want to get them you can just download a source code at the bottom of the post.

This is how I plan to use this image slider.

import ImageSlider from "./ImageSlider";
const App = () => {
  const slides = [
    { url: "http://localhost:3000/image-1.jpg", title: "beach" },
    { url: "http://localhost:3000/image-2.jpg", title: "boat" },
    { url: "http://localhost:3000/image-3.jpg", title: "forest" },
    { url: "http://localhost:3000/image-4.jpg", title: "city" },
    { url: "http://localhost:3000/image-5.jpg", title: "italy" },
  ];
  return (
    <div>
      <ImageSlider slides={slides} />
    </div>
  );
};

export default App;

Here in App we created an array of sliders. It could be an array of strings but array of objects is better because we can store there additional information like title for example.

The only property that we pass inside our ImageSlider is slides.

Now let's create our ImageSlider component.

ImageSlider component

const ImageSlider = ({ slides }) => {
  return <div>ImageSlider</div>
}

We also need to store state inside our slider. For us it is enough to just store an index of current slide.

const ImageSlider = ({ slides }) => {
  const [currentIndex, setCurrentIndex] = useState(0);
  return <div>ImageSlider</div>
}

It is important that we don't use fixed heights and widths inside our component to keep our component flexible

Let's specify dimensions of the slider outside.

const App = () => {
  ...
  const containerStyles = {
    width: "500px",
    height: "280px",
    margin: "0 auto",
  };
  return (
    <div style={containerStyles}>
      <ImageSlider slides={slides} />
    </div>
  );
};

Now inside we need to set correct slider styles.

const ImageSlider = ({ slides }) => {
  ...
  const slideStyles = {
    width: "100%",
    height: "100%",
    borderRadius: "10px",
    backgroundSize: "cover",
    backgroundPosition: "center",
  };
  const sliderStyles = {
    position: "relative",
    height: "100%",
  };
  const slideStylesWidthBackground = {
    ...slideStyles,
    backgroundImage: `url(${slides[currentIndex].url})`,
  };
  return (
    <div style={sliderStyles}>
      <div style={slideStylesWidthBackground}></div>
    </div>
  );
}

We set our slider to take full width and height and position images inside in center.

Step 1

Slider controls

Now we need to add controls to our slider.

const ImageSlider = ({ slides }) => {
  ...
  const rightArrowStyles = {
    position: "absolute",
    top: "50%",
    transform: "translate(0, -50%)",
    right: "32px",
    fontSize: "45px",
    color: "#fff",
    zIndex: 1,
    cursor: "pointer",
  };

  const leftArrowStyles = {
    position: "absolute",
    top: "50%",
    transform: "translate(0, -50%)",
    left: "32px",
    fontSize: "45px",
    color: "#fff",
    zIndex: 1,
    cursor: "pointer",
  };

  return (
    <div style={sliderStyles}>
      <div>
        <div onClick={goToPrevious} style={leftArrowStyles}></div>
        <div onClick={goToNext} style={rightArrowStyles}></div>
      </div>
      <div style={slideStylesWidthBackground}></div>
    </div>
  );
}

Here we used utf-8 symbols for our arrows and added styles to render them. Now we must add goToNext and goToPrevious methods.

const ImageSlider = ({ slides }) => {
  ...
  const goToPrevious = () => {
    const isFirstSlide = currentIndex === 0;
    const newIndex = isFirstSlide ? slides.length - 1 : currentIndex - 1;
    setCurrentIndex(newIndex);
  };
  const goToNext = () => {
    const isLastSlide = currentIndex === slides.length - 1;
    const newIndex = isLastSlide ? 0 : currentIndex + 1;
    setCurrentIndex(newIndex);
  };
}

This functions just change our index in the state but we applied logic to just from the last slide to the first one and vice versa.

As you can see in browser, we can just between slides now.

Jumping to specific slide

But it is not all. We also want to jump to specific slide by clicking on the dot. So let's render a list of dots under the slider.

const ImageSlider = ({ slides }) => {
  ...
  const goToSlide = (slideIndex) => {
    setCurrentIndex(slideIndex);
  };

  const dotsContainerStyles = {
    display: "flex",
    justifyContent: "center",
  };

  const dotStyle = {
    margin: "0 3px",
    cursor: "pointer",
    fontSize: "20px",
  };

  return (
    <div style={sliderStyles}>
      ...
      <div style={dotsContainerStyles}>
        {slides.map((slide, slideIndex) => (
          <div
            style={dotStyle}
            key={slideIndex}
            onClick={() => goToSlide(slideIndex)}
          ></div>
        ))}
      </div>
    </div>
  );
}

Here we created goToSlide function which simply changes the index inside state. We also added styles for dotContainer and dot. And we rendered a list of dots just by mapping our slides.

As you can see in browser our project is fully implemented.

Finished project

Also if you are interested to learn my 5 tips to become a senior developer make sure to check this post also.

📚 Source code of what we've done