React image slider using only CSS

Image sliders are a ubiquitous feature in modern web design, offering an engaging way to showcase content. While there are many libraries and plugins available for creating image sliders in React, sometimes you may prefer a lightweight solution that doesn't require additional dependencies. In this post, I'll explore how to build a sleek and responsive image slider using only CSS in a React application.

Setting Up the Project: Before we dive into the code, let's set up a new React project. Assuming you have Node.js and npm installed, you can create a new project using Create React App by running the following command in your terminal:

npx create-next-app react-img-slider
cd react-img-slider

Once the project is set up, navigate into the project directory and open it in your preferred code editor.

Creating the Image Slider Component: Now, let's create a new file called Slider.jsx in the src/app/components directory. This file will contain our image slider component. Here's the initial structure of the component:

Slider.jsx
'use client'

import { useEffect, useState } from 'react'
import { ChevronLeftIcon, ChevronRightIcon } from '@heroicons/react/20/solid'
import clsx from 'clsx'
import '@/styles/slider.css'

function Slider({ slides, showControls = true, showDots = false, speed = 3000, className }) {
  const [current, setCurrent] = useState(0)

  useEffect(() => {
    const lastSlide = slides.length - 1

    if (current < 0) {
      setCurrent(lastSlide)
    } else if (current > lastSlide) {
      setCurrent(0)
    }

    const slider = setInterval(() => {
      setCurrent(current === slides.length - 1 ? 0 : current + 1)
    }, speed)

    return () => {
      clearInterval(slider)
    }
  }, [slides, current, speed])

  return (
    <>
      <div className={clsx('relative', className)} id="slider">
        {slides.map((slide, index) => {
          let position = 'nextSlide'

          if (index === current) {
            position = 'activeSlide'
          }
          if (index === current - 1 || (current === 0 && index === slides.length - 1)) {
            position = 'lastSlide'
          }

          return (
            <div className={clsx(position, 'slide')} key={index}>
              {index === current && slide}
            </div>
          )
        })}
        {showControls && (
          <div id="slide-controller">
            <button
              onClick={() => setCurrent(current - 1)}
              className="absolute left-0 top-1/2 -translate-y-1/2 transform rounded bg-slate-300/50 p-1.5 hover:bg-slate-400/50"
            >
              <ChevronLeftIcon className="h-10 w-10 text-slate-500/60" />
            </button>
            <button
              onClick={() => setCurrent(current + 1)}
              className="absolute right-0 top-1/2 -translate-y-1/2 transform rounded bg-slate-300/50 p-1.5 hover:bg-slate-400/50"
            >
              <ChevronRightIcon className="h-10 w-10 text-slate-500/60" />
            </button>
          </div>
        )}

        {showDots && (
          <div id="dot-control" className="absolute -bottom-16 left-1/2 hidden -translate-x-1/2 transform md:flex">
            {slides.map((_, index) => {
              return (
                <button
                  key={index}
                  className={clsx(
                    'mx-1 h-3 w-3 rounded-full focus:outline-none',
                    index === current ? 'bg-slate-500/60' : 'bg-slate-300/50',
                  )}
                  onClick={() => setCurrent(index)}
                />
              )
            })}
          </div>
        )}
      </div>
    </>
  )
}

export default Slider

In this component, we'll pass an array of image URLs as props (images). We'll define the styles for our image slider in a separate CSS file.

Styling the Image Slider: Create a new file called slider.css in the src/styles directory. We'll define the styles for our image slider here. Below is a basic example to get started:

slider.css
.slide {
    --slide-transition: all 0.75s linear;
    transition: var(--slide-transition);
}

.slide.activeSlide {
    opacity: 1;
    transform: translateX(0);
}

.slide.lastSlide {
    transform: translateX(-100%);
}

.slide.nextSlide {
    transform: translateX(100%);
}

This CSS code sets up a basic layout for our image slider. Each image slide will occupy the full width of the slider container. We're using CSS transitions for smooth slide transitions, and object-fit: cover ensures that the images maintain their aspect ratio and cover the entire slide.

In this, we've explored how to create a simple yet elegant image slider in React using only CSS. By leveraging CSS flexbox, transitions, and animations, we've built a responsive and visually appealing component without relying on external libraries. You can further enhance this slider by adding navigation controls, autoplay functionality, or custom animations to suit your project requirements. Experiment with different CSS properties and animations to create unique and eye-catching image sliders for your React applications.