Driver FixRecommendedSound, Wi-Fi or graphics acting up? Check drivers firstFind missing or outdated drivers fast.Check DriversOctober DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsSlow PC?RecommendedPC slow today? Run a repair scan before it gets worseResolve common Windows issues and optimize system performance.Scan Now×
Skip to content
World desk8 min

How to Add a Responsive Image Carousel to a React App

Add a responsive image carousel to a React app with Swiper, practical breakpoints, responsive image handling, keyboard controls, and accessibility guidance.
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Use Swiper’s React components to build a responsive image carousel: install the swiper package, render each image inside a SwiperSlide, and set a mobile-friendly default with wider-screen breakpoints. The example below adds keyboard-operable previous and next buttons, image descriptions, and responsive image-source support. It follows Swiper’s documented React integration; the breakpoint values are examples to tune for your layout.

Install Swiper and add its base styles

From your React app’s project directory, install Swiper:

npm install swiper

Import its React components and base stylesheet in the component file:

import { useRef, useState } from 'react';
import { Swiper, SwiperSlide } from 'swiper/react';
import { Navigation, Pagination } from 'swiper/modules';
import 'swiper/css';
import 'swiper/css/navigation';
import 'swiper/css/pagination';

Swiper’s React documentation describes the adapter and optional modules. Include only modules the carousel uses; this example uses Navigation and Pagination.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Build a responsive carousel from image data

This component starts with one slide visible, then shows two at 640 CSS pixels and three at 1024 CSS pixels. Those are minimum viewport-width thresholds in Swiper’s default breakpoint mode—not universal design recommendations. Choose widths, slide counts, and spacing to fit your content container.

import { useRef, useState } from 'react';
import { Swiper, SwiperSlide } from 'swiper/react';
import { Navigation, Pagination } from 'swiper/modules';
import 'swiper/css';
import 'swiper/css/navigation';
import 'swiper/css/pagination';
import './ImageCarousel.css';

const images = [
  {
    src: '/images/coast-1200.jpg',
    srcSet: '/images/coast-600.jpg 600w, /images/coast-1200.jpg 1200w',
    alt: 'Rocky coast at sunset',
  },
  {
    src: '/images/forest-1200.jpg',
    srcSet: '/images/forest-600.jpg 600w, /images/forest-1200.jpg 1200w',
    alt: 'Sunlight through a forest',
  },
  {
    src: '/images/city-1200.jpg',
    srcSet: '/images/city-600.jpg 600w, /images/city-1200.jpg 1200w',
    alt: 'City buildings at dusk',
  },
];

export function ImageCarousel() {
  const swiperRef = useRef(null);
  const [activeIndex, setActiveIndex] = useState(0);

  return (
    <section className="image-carousel" aria-label="Featured photos">
      <div className="carousel-controls">
        <button
          type="button"
          aria-label="Previous slides"
          onClick={() => swiperRef.current?.slidePrev()}
        >
          Previous
        </button>
        <button
          type="button"
          aria-label="Next slides"
          onClick={() => swiperRef.current?.slideNext()}
        >
          Next
        </button>
      </div>

      <Swiper
        modules={[Navigation, Pagination]}
        slidesPerView={1}
        spaceBetween={12}
        breakpoints={{
          640: { slidesPerView: 2, spaceBetween: 16 },
          1024: { slidesPerView: 3, spaceBetween: 24 },
        }}
        pagination={{ clickable: true }}
        onSwiper={(swiper) => {
          swiperRef.current = swiper;
          setActiveIndex(swiper.realIndex);
        }}
        onSlideChange={(swiper) => setActiveIndex(swiper.realIndex)}
      >
        {images.map((image, index) => (
          <SwiperSlide key={image.src}>
            <figure>
              <img
                src={image.src}
                srcSet={image.srcSet}
                sizes="(min-width: 1024px) 33vw, (min-width: 640px) 50vw, 100vw"
                alt={image.alt}
                width="1200"
                height="800"
                loading={index === 0 ? 'eager' : 'lazy'}
              />
            </figure>
          </SwiperSlide>
        ))}
      </Swiper>
      <p className="slide-status" aria-live="polite">
        Slide {activeIndex + 1} of {images.length}
      </p>
    </section>
  );
}

The srcSet and sizes values assume that corresponding image variants exist at those paths. Generate and substitute your own files, or omit those attributes if you have no alternate sizes. The width and height attributes should reflect each image’s actual intrinsic dimensions; the 1200-by-800 values here are illustrative. See React’s image reference for responsive image sources, dimensions, alternative text, and native loading behavior.

Choose an image fit and reserve its space

For a gallery where every tile should have the same shape, set a consistent aspect ratio and use object-fit: cover when cropping is acceptable. Use contain if the full image must remain visible. True image dimensions or a reserved aspect ratio also help avoid layout shifts while images load.

.image-carousel figure {
  aspect-ratio: 3 / 2;
  margin: 0;
  overflow: hidden;
}

.image-carousel img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.carousel-controls {
  display: flex;
  gap: 0.75rem;
  margin-bottom: 0.75rem;
}

.carousel-controls button:focus-visible {
  outline: 3px solid currentColor;
  outline-offset: 3px;
}

Use object-fit: contain instead if cropping would remove important image content. Ensure control text and focus outlines remain visible against the surrounding design.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Understand what breakpoints can change

Swiper’s breakpoint keys are minimum widths by default: at 640 CSS pixels the 640 settings apply, and at 1024 CSS pixels the 1024 settings apply. The Swiper API documents which parameters can be adjusted at breakpoints. It cautions that options which change layout or logic, including loop and effect, do not work there. Set those options at the Swiper level instead of trying to switch them by width. Container-based breakpoints are documented as beta; consider them only when the component’s own container width, rather than viewport width, should determine its layout.

Make the carousel usable without swiping

Touch gestures are not a substitute for controls. Provide keyboard-operable previous and next buttons, visible focus, and an understandable name for the carousel. The example uses ordinary buttons and shows the current slide number in a polite live region; keep focus on the button after activation rather than moving it into the slide.

Swiper’s optional Navigation and Pagination modules provide library controls and pagination, but visible controls still need to be understandable and usable in your finished interface. The example’s previous/next buttons call the Swiper instance directly. Pagination is enabled with clickable bullets; keep a non-color-only indication of the active slide, and verify contrast and focus styling in your design.

W3C’s carousel tutorial calls for controls that let people display and understand items, and for a way to stop and resume movement. Its ARIA Authoring Practices carousel pattern recommends previous and next controls and, for an auto-rotating carousel, a rotation control. If you add autoplay, stop rotation when keyboard focus enters or the pointer hovers, and do not restart after focus leaves unless the user explicitly starts it again. Provide a way to pause or stop motion and handle announcements without moving focus unexpectedly. Check the behavior of the assembled component; an accessibility module alone does not establish that a carousel is accessible.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

WAI’s styling tutorial associates a 44 × 44 CSS-pixel target size with WCAG 2.5.5 Target Size (Enhanced), Level AAA guidance for buttons and links that are not inline in a block of text. Treat this as that AAA guidance, not as a universal minimum for every WCAG conformance context. Keep controls available on small screens for people who cannot or do not use swipe.

Load images without slowing the first view unnecessarily

Native loading="lazy" is suitable for offscreen images, but do not blindly lazy-load the likely largest or initial above-the-fold image. The example loads the first image eagerly and lazy-loads the remaining slides; adjust this if the carousel starts offscreen or its initial image is not the page’s primary visual. React documents native lazy loading and its interaction with server-rendered preload hints in the image reference.

Swiper’s current API describes native browser lazy loading from version 9 onward and notes limitations for its own lazy-preload option in React and Vue. Prefer image attributes such as loading and verify the behavior against the Swiper version installed in your project rather than assuming the library’s separate lazy-loading option behaves identically. No runtime or performance test is claimed for this example.

Decide between Swiper and a custom carousel

Swiper gives you a documented React adapter and built-in carousel behavior, including optional modules. It can be a quicker path when the design needs familiar sliding, pagination, or navigation. A custom component can give you tighter control over markup and interaction and avoid adding this dependency, but you must implement sizing, touch behavior, keyboard controls, focus handling, and announcements yourself. Choose based on required interactions, dependency and bundle constraints, and maintenance needs; there is no universal winner or performance comparison established here. A CSS-only approach is also possible for simpler presentation needs, but it does not by itself provide all carousel interaction and accessibility behavior.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Troubleshoot common implementation problems

  • Styles or spacing are missing: confirm import 'swiper/css'; is present. If using Navigation or Pagination module UI, also import swiper/css/navigation and swiper/css/pagination.
  • A module does not work: import it from swiper/modules, include it in the modules array, and enable its corresponding option, such as pagination. Follow the React docs for the installed Swiper version.
  • Slides do not change at the expected width: breakpoint keys are minimum widths by default. Check the viewport width, ensure the relevant threshold is reached, and tune the settings for the actual content area. Do not put unsupported logic-changing options such as loop or effect in a breakpoint.
  • Images fail or appear blurry: check that each src and every URL in srcSet resolves, and that sizes matches the rendered layout. Use the correct intrinsic dimensions and generated variants.
  • The page jumps as images load: give each image accurate width and height values or reserve its display space with CSS, such as a fixed aspect ratio.
  • Controls are hard to use on a phone or with a keyboard: keep visible previous/next buttons, verify keyboard operation and a visible focus indicator, and do not rely on swipe or color alone to identify the active slide.

Or skip the browser setup

If you need a clean screenshot of the carousel page to review it, ScreenshotNeo provides a website screenshot API and MCP server. One GET request can return an image or PDF; for example, this cURL request saves a WebP screenshot of the page. Replace the URL with a deployed or locally reachable page URL; the API must be able to access it.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://your-site.example/gallery -o carousel.webp

See the ScreenshotNeo API documentation for request options. ScreenshotNeo accepts cookie or consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; those steps can be turned off. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers indicate the page verdict and billing status. Its MCP server offers take_screenshot, get_page_info, and capture_pdf for AI agents and MCP clients. The Free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 screenshots. Sign up for ScreenshotNeo’s free plan.

Frequently Asked Questions

Can I use a React image carousel without installing Swiper?

Yes. A custom or CSS-only implementation is possible. The trade-off is that a custom interactive carousel makes you responsible for behavior such as keyboard controls, touch interaction, focus handling, and announcements.

Should every slide image use lazy loading?

No. Lazy loading is generally appropriate for offscreen slides, while an initial above-the-fold image may warrant eager loading so it is discovered promptly.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Can I switch to loop mode only on wider screens with a breakpoint?

Swiper’s API says logic-changing options such as `loop` do not work in breakpoints. Configure `loop` at the Swiper level instead.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More from the Wire

  1. World desk4 min
    How to Spot an AI Voice Scam Before Sending MoneyDon’t rely on how a caller sounds. Pause, call back through a known number, and verify the emergency with another trusted person before sending money.
  2. Mountain View desk4 min
    Google’s SynthID Detector: How to Check AI-Generated Images, Video and AudioGoogle’s SynthID Detector looks for an embedded watermark in supported images, video and audio. Here is what its results do—and do not—show.
  3. Redmond desk20 min
    How to create a link to File or Folder in Windows 11Windows 11 gives you several ways to point to a file or folder without moving or duplicating it. You can create a desktop shortcut,…
Recommended PC Tool
Recommended PC Tool
Outdated Drivers Are Slowing You DownFree scan - exact matches
PC Slower Than It Used to Be?Free scan - under a minute

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.