Recommended Free Tools
For a simple, swipeable row of cards, start with a horizontally scrolling container and CSS scroll snap. Use a small client-side React component when you need custom controls or state, and choose a library such as Embla when drag behavior, snap navigation, or grouped slides justify the extra dependency. Here are three practical approaches for a Next.js App Router project, with trade-offs and accessibility guidance for each.
Where the carousel belongs in a Next.js app
In the App Router, a route page is a default-exported React component in a page file under app. Keep content that needs no browser interaction in the page, and isolate stateful carousel behavior in a Client Component. This split is an implementation pattern, not a carousel-specific rule in the Next.js documentation. See the Next.js App Router documentation.
For example, a route might render a component from app/products/page.tsx, while an interactive carousel lives in app/components/ProductCarousel.tsx. Add 'use client' at the top of that component when it uses React state or browser interaction.
Choose an approach by the interaction you need
| Need | Start with | What you take on |
|---|---|---|
| A row users can swipe or scroll | Native overflow and CSS scroll snap | Browser scrolling and snap positions; little carousel-specific JavaScript. |
| A deliberately small, tailored interaction | Custom React component | You control markup and state, and own navigation, edge cases, and accessibility behavior. |
| Drag behavior, controlled snap navigation, grouped slides, or a richer gallery | Embla or another evaluated library | A dependency and its integration/version maintenance; accessibility remains your responsibility. |
This is a capabilities-based choice, not a speed or bundle-size ranking. Measure your own application if those factors determine the decision.
#1 Best Overall
- Read Before You Buy — No Video Output: These adapters support charging and USB 2.0 data transfer, but cannot transmit video signals. Except for standard USB webcams (which use USB data only), they are not compatible with HDMI/DisplayPort cables, video-capable USB-C hubs, or docking stations with video output.
- Convert USB-A Ports to USB-C: Designed to connect USB-C earphones, cables, flash drives, card readers, and other USB-C accessories to standard USB-A ports. Plug-and-play with no drivers or software required.
- Aluminum Alloy Housing: Built with a sturdy aluminum alloy shell that aids in heat dissipation and protects against daily wear and scratches. Designed to maintain a stable and secure connection.
- Compact & Travel-Friendly: The ultra-compact design allows the adapter to stay plugged into your device without blocking adjacent ports or adding bulk, reducing wear and tear on your original USB ports.
- 12-Month Warranty: Backed by a 12-month manufacturer warranty for peace of mind. Designed to meet strict quality control standards for reliable everyday performance.
Method 1: Build a custom React carousel
A custom component is appropriate when the interaction is intentionally limited—for example, one visible product image at a time with previous and next buttons. Keep the slide content in data and let React render the selected item. This example does not loop: the buttons are disabled at the first and last items.
1. Add the client component
Create app/components/CustomCarousel.tsx:
'use client';
import { useState } from 'react';
type Slide = {
title: string;
description: string;
};
const slides: Slide[] = [
{ title: 'First item', description: 'Description for the first item.' },
{ title: 'Second item', description: 'Description for the second item.' },
{ title: 'Third item', description: 'Description for the third item.' },
];
export default function CustomCarousel() {
const [selected, setSelected] = useState(0);
function previous() {
setSelected((current) => Math.max(0, current - 1));
}
function next() {
setSelected((current) => Math.min(slides.length - 1, current + 1));
}
const slide = slides[selected];
return (
<section aria-label="Featured items" aria-roledescription="carousel">
<div aria-live="polite" aria-atomic="true">
<article aria-roledescription="slide" aria-label={`${selected + 1} of ${slides.length}`}>
<h2>{slide.title}</h2>
<p>{slide.description}</p>
</article>
</div>
<div>
<button type="button" onClick={previous} disabled={selected === 0}>
Previous
</button>
<button type="button" onClick={next} disabled={selected === slides.length - 1}>
Next
</button>
</div>
</section>
);
}
The live region can announce the changed slide to assistive technology; verify the experience with the screen readers and browsers your users rely on. If the carousel contains essential information, do not make it available only by advancing through slides.
2. Render it from the route
In app/page.tsx, import and render the component:
import CustomCarousel from './components/CustomCarousel';
export default function Page() {
return (
<main>
<h1>Featured items</h1>
<CustomCarousel />
</main>
);
}
The page itself can remain a Server Component; only the component that uses state needs the client boundary. This small example leaves styling, focus policy, and any richer keyboard interaction to the application. Native buttons provide keyboard-operable controls, but test the complete interaction rather than assuming the markup alone makes every carousel accessible.
Method 2: Use native scrolling and CSS scroll snap
For a row of cards that people can swipe on touch devices or scroll with a trackpad, native overflow is often the simplest starting point. The browser handles scrolling; CSS defines where scrolling should settle.
Do these 3 things before closing this tab:
1Fix the driver behind crashes, sound loss and screen glitches2Repair Windows errors before they cause bigger problems3Scan for outdated or missing drivers - takes under a minute1. Render a row of items
This can be rendered in a page or component without React state:
Rank #2
- 5-in-1 USB-C Hub: Experience comprehensive connectivity featuring a Power Delivery input, two USB-A 2.0 ports, a USB-A 3.0 port, and an HDMI port. (Note: The USB-C power delivery input port is only for connecting an external wall charger to power your laptop and cannot power peripheral devices.)
- 90W Pass-Through Charging: Achieve optimal charging with 90W pass-through power to your laptop, supported by a total input of 100W, with the hub reserving 10W for operational efficiency. (Note: Wall charger not included.)
- Quick Data Transfers: Accelerate your productivity with rapid data transfers using a high-speed 5Gbps USB 3.0 port and two 480Mbps USB 2.0 ports.
- 4K HDMI Display: Enhance your visual experience with a hub capable of delivering 4K resolution at 30Hz in both mirror and extend modes. Please note that this hub is compatible with MacBook (macOS 12 and newer), Windows 10 and 11, ChromeOS, and laptops equipped with DP Alt Mode and Power Delivery. Note: This device is not compatible with Linux.
- What You Get: Anker USB-C Hub (5-in-1, 4K HDMI), welcome guide, 18-month warranty, and our friendly customer service.
const items = [
{ title: 'First item', text: 'Details for the first item.' },
{ title: 'Second item', text: 'Details for the second item.' },
{ title: 'Third item', text: 'Details for the third item.' },
];
export default function Page() {
return (
<main>
<h1>Browse items</h1>
<div className="carousel" aria-label="Featured items">
{items.map((item) => (
<article className="carousel__slide" key={item.title}>
<h2>{item.title}</h2>
<p>{item.text}</p>
</article>
))}
</div>
</main>
);
}
If the container is not a landmark or otherwise named by its surrounding structure, use an appropriate semantic wrapper and provide a clear accessible name. Avoid adding carousel semantics to a scrolling row unless it behaves like a carousel and the label helps users understand it.
2. Add scrolling and snap styles
Put this in a global stylesheet or the component’s CSS module, adapting the selectors to your setup:
.carousel {
display: grid;
grid-auto-columns: minmax(16rem, 80%);
grid-auto-flow: column;
gap: 1rem;
overflow-x: auto;
overscroll-behavior-inline: contain;
padding: 0 1rem 1rem;
scroll-snap-type: inline proximity;
}
.carousel__slide {
min-width: 0;
scroll-snap-align: start;
}
scroll-snap-type belongs on the scrolling container, and scroll-snap-align on the items. The example uses proximity, which allows the browser to settle near snap positions without making every stop mandatory. Adjust the card width and spacing to fit the design and test on narrow screens.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Repair Windows errors before they cause bigger problemsFix Now →Use mandatory snapping with care: MDN warns it can prevent users from scrolling overflowing content inside a child fully into view. For variable-size or content-heavy slides, test whether snapping helps or obstructs reading. See MDN’s CSS Scroll Snap documentation.
Know which CSS carousel features you are using
The overflow-plus-scroll-snap pattern is distinct from newer CSS carousel UI features such as generated scroll buttons and markers described in MDN’s CSS carousel guide. Check current support for your target browsers before relying on those newer features; ordinary overflow and scroll snap do not require those controls.
Rank #3
- Sleek 7-in-1 USB-C Hub: Features an HDMI port, two USB-A 3.0 ports, and a USB-C data port, each providing 5Gbps transfer speeds. It also includes a USB-C PD input port for charging up to 100W and dual SD and TF card slots, all in a compact design.
- Flawless 4K@60Hz Video with HDMI: Delivers exceptional clarity and smoothness with its 4K@60Hz HDMI port, making it ideal for high-definition presentations and entertainment. (Note: Only the HDMI port supports video projection; the USB-C port is for data transfer only.)
- Double Up on Efficiency: The two USB-A 3.0 ports and a USB-C port support a fast 5Gbps data rate, significantly boosting your transfer speeds and improving productivity.
- Fast and Reliable 85W Charging: Offers high-capacity, speedy charging for laptops up to 85W, so you spend less time tethered to an outlet and more time being productive.
- What You Get: Anker USB-C Hub (7-in-1), welcome guide, 18-month warranty, and our friendly customer service.
Method 3: Use the Embla React library
A library can be useful when you need controlled snap navigation, drag interactions, or grouped slides rather than a basic scrolling row. Embla’s React integration uses a viewport ref around a container and slide elements, and its documentation recommends placing navigation controls outside the viewport to avoid drag conflicts. Its React wrapper handles cleanup when the component unmounts.
The available Embla React page identifies itself as v9.0.0-rc03 and directs users seeking the latest stable release to the v8 documentation. APIs can differ across versions: choose the version you install, then follow that version’s docs rather than mixing examples. See Embla’s React documentation and its v8 documentation.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
1. Install the React package
For an npm project, install the React package:
npm install embla-carousel-react
Confirm the installed package version and use matching documentation. The following example illustrates the documented React structure and navigation API; check it against the version selected for your project before using it.
2. Create the carousel component
Create app/components/EmblaCarousel.tsx:
'use client';
import useEmblaCarousel from 'embla-carousel-react';
const slides = ['First item', 'Second item', 'Third item'];
export default function EmblaCarousel() {
const [emblaRef, emblaApi] = useEmblaCarousel({ align: 'start' });
return (
<section aria-label="Featured items" aria-roledescription="carousel">
<div className="embla__viewport" ref={emblaRef}>
<div className="embla__container">
{slides.map((slide, index) => (
<article
className="embla__slide"
aria-roledescription="slide"
aria-label={`${index + 1} of ${slides.length}`}
key={slide}
>
<h2>{slide}</h2>
</article>
))}
</div>
</div>
<div className="embla__controls">
<button type="button" onClick={() => emblaApi?.scrollPrev()}>
Previous
</button>
<button type="button" onClick={() => emblaApi?.scrollNext()}>
Next
</button>
</div>
</section>
);
}
Keep controls outside the viewport so they do not compete with pointer dragging. Embla exposes previous/next snap navigation and the selected snap, and documents options for drag behavior and how many slides advance per action; consult the matching version’s API docs before configuring them. See Embla’s API documentation.
3. Add the layout styles
.embla__viewport {
overflow: hidden;
}
.embla__container {
display: flex;
touch-action: pan-y pinch-zoom;
margin-left: -1rem;
}
.embla__slide {
flex: 0 0 80%;
min-width: 0;
padding-left: 1rem;
}
Render <EmblaCarousel /> from a page as in the custom-component example. The library supplies carousel mechanics, not a complete accessibility policy: label the experience, use native controls, make focus behavior understandable, and ensure changes are communicated when content is hidden or replaced.
Rank #4
- Dual Converters, Infinite Potential:Includes 2× USB C male to USB A female adapters and 2× USB A male to USB C female adapters. Perfect for a wide range of uses—tablets with Bluetooth keyboards, expand USB ports on macbook, and more. Two different converters for all your daily needs
- Next-Level 10Gbps & 3A Charging: No more slow 480Mbps, this usb to usb c adapter has a transfer speed of up to 10Gbps, allowing you to do more transferring in less time. This usb adapter fits both USB A and USB C charger, supporting up to 3A fast charging
- Upgraded Exquisite Craftsmanship: With an aluminum alloy housing and metal connector, the usbc to usb adapter is extremely durable and sturdy. Rigorously tested to withstand more than 10,000 times of plugging and unplugging, ensuring long-lasting performance
- Broad Compatible: The usb c to usb adapter widely supports all USB C/ USB A devices like laptops, tablets, cellphones, car chargers, and phone chargers. Such as compatible with MacBook Pro/Air 2023/2022, Thunderbolt 4/3 Devices,Apple MagSafe Watch 9/8/7/SE/Ultra, iPad Pro 2022/2021, Samsung Galaxy S23/S20/S10, and iPhone 17/16/15 Pro. Plug and play
- Please Note: To reach 10Gbps speed, keep the cable under 3.3 ft. For USB A Male to USB C adapters, try flipping the USB C connector. USB C Male to USB A adapters support bidirectional 10Gbps transfer within 3.3 ft
Make the carousel usable with a keyboard and assistive technology
W3C’s Web Accessibility Initiative says, “All functionality, including navigating between carousel items, must be operable by keyboard.” See the W3C WAI Carousels Tutorial for guidance on keyboard operation, pause controls, communicating changes, and focus management.
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →- Give the carousel a clear accessible name and structure the slides meaningfully.
- Use native buttons for previous, next, and other controls; ensure they can be reached and operated with a keyboard.
- Keep focus behavior understandable when a control changes the visible slide. Do not move focus unexpectedly.
- Communicate changes to screen-reader users when navigation hides or replaces content; test whether and how a live announcement should work for your interaction.
- Avoid automatic movement where possible. If slides move automatically, provide a way to pause or stop that movement and ensure it does not disrupt reading or focus.
- Do not put essential information only on slides that advance automatically or that users may not discover.
Or skip the browser setup
If you also need screenshots of your carousel in a page, you can call ScreenshotNeo’s screenshot API instead of setting up a browser capture workflow. One GET request returns an image or PDF. See the ScreenshotNeo API documentation for options and response details.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
ScreenshotNeo accepts cookie/consent banners and removes 60+ known consent platforms, newsletter popups, and chat widgets before capture; each cleanup step can be turned off. Bot checks/CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, and responses report the page verdict and billing status in headers. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients. The Free plan includes 1,000 screenshots a month without a card; paid plans start at $5 for 3,000 shots. See ScreenshotNeo for details and sign up free for 1,000 screenshots a month, with no card required.
Troubleshoot common problems
The client component complains about hooks or browser APIs
React state and browser interaction must run in a Client Component. Put 'use client' at the top of the component file using hooks or browser APIs, rather than converting the entire route to client rendering unnecessarily.
The CSS row does not scroll horizontally
Check that the items form a single row, the container has overflow-x: auto, and the combined item width exceeds the available width. Confirm that the snapping rule is on the scrolling element and each item has scroll-snap-align.
Snap behavior makes some content hard to reach
Mandatory snapping can trap scrolling within oversized slide content. Try proximity, adjust the item sizing, and test with content that is taller or wider than the viewport.
Best Value
- 5-in-1 Connectivity: Equipped with a 4K HDMI port, a 5 Gbps USB-C data port, two 5 Gbps USB-A ports, and a USB C 100W PD-IN port. Note: The USB C 100W PD-IN port supports only charging and does not support data transfer devices such as headphones or speakers.
- Powerful Pass-Through Charging: Supports up to 85W pass-through charging so you can power up your laptop while you use the hub. Note: Pass-through charging requires a charger (not included). Note: To achieve full power for iPad, we recommend using a 45W wall charger.
- Transfer Files in Seconds: Move files to and from your laptop at speeds of up to 5 Gbps via the USB-C and USB-A data ports. Note: The USB C 5Gbps Data port does not support video output.
- HD Display: Connect to the HDMI port to stream or mirror content to an external monitor in resolutions of up to 4K@30Hz. Note: The USB-C ports do not support video output.
- What You Get: Anker 332 USB-C Hub (5-in-1), welcome guide, our worry-free 18-month warranty, and friendly customer service.
Embla controls do nothing or drag feels wrong
Ensure the controls call methods on the initialized API and are outside the draggable viewport. Verify that your code matches the installed Embla version; the cited React docs are for a release candidate and stable users are directed to v8 docs.
Screen readers do not identify the carousel change
A visual slide change is not necessarily communicated to assistive technology. Provide meaningful labels and structure, then test announcements and focus with assistive technology. Avoid adding a live region indiscriminately; frequent or poorly scoped announcements can make navigation harder to follow.
Frequently asked questions
Does a carousel have to auto-play?
No. A user-controlled scroller or previous/next interaction is a carousel without automatic movement. If you do add auto-advance, users need a way to pause it.
Free tools Windows power users keep installed
One-click scans. No signup required.
Which method should I use for a simple card row?
Start with native overflow and CSS scroll snap when users mainly need to swipe or scroll through a row. It uses browser scrolling rather than a dedicated carousel engine.
Does Embla make a carousel accessible automatically?
No. It provides carousel mechanics, but the application still needs accessible naming, keyboard-operable controls, understandable focus behavior, and communication of changes.
Quick Recap
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.

