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".
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.
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.
Want to conquer your next JavaScript interview? Download my FREE PDF - Pass Your JS Interview with Confidence and start preparing for success today!
📚 Source code of what we've done