webdevpuneet.com

Swiper Multi-Row Grid Carousel — Free JS Snippet

Swiper Multi-Row Grid Carousel · Carousels · Plain HTML, CSS & JS · Live preview

Copy & paste

Source Code

<div class="mg-wrap">
  <div class="mg-head">
    <h3>Browse categories</h3>
    <div class="mg-nav">
      <button type="button" id="mgPrev" aria-label="Previous page">&#8249;</button>
      <button type="button" id="mgNext" aria-label="Next page">&#8250;</button>
    </div>
  </div>
  <div class="swiper mg-swiper" id="mgSwiper">
    <div class="swiper-wrapper" id="mgSlides"></div>
  </div>
  <div class="mg-progress"><div class="swiper-pagination" id="mgPag"></div></div>
</div>

Extend with AI

Take This Snippet Further With AI

The AI prompt for this one is for Patreon supporters ($3 a month, 7 days free), along with a site with no ads. Supporters enter the passcode once and it is remembered in this browser.

· Become a supporter

What's included

Features

Two-row grid using the grid module (rows and fill)
slidesPerGroup so each swipe moves one full page
Responsive column count through breakpoints
Explicit container height and slide height maths that accounts for the gap
Custom previous/next buttons with disabled states
Progress-bar pagination instead of dots
Keyboard control, a11y labels and focusable tile links
Gradient and emoji tiles, no images required

About this UI Snippet

Swiper Multi-Row Grid Carousel — HTML, CSS & JavaScript

Screenshot of the Swiper Multi-Row Grid Carousel snippet rendered live

A single row of cards is the default shape of a carousel, but category pickers, app launchers and icon grids want more than one row: sixteen tiles arranged two-by-eight scroll sideways, showing many options at once without turning into a long page. Swiper handles this with its grid module, which arranges slides into a fixed number of rows and then scrolls the whole grid horizontally, so a multi-row carousel is a single option rather than nested sliders.

grid: { rows: 2, fill: 'row' } is the key setting. rows sets the number of rows, and fill decides the reading order: 'row' fills left to right then moves down, which matches how people read a grid, while 'column' fills top to bottom, which keeps related tiles stacked. Two things must be set up around it or the grid renders wrongly, and both trip people up. First, the container needs a definite height, because rows share it; without one the slides collapse or overlap. Second, slides need a height that is a share of the container — here calc((100% - 16px) / 2), which is half the height minus half the gap — so each row's tiles exactly fit. The gap between rows comes from spaceBetween, so the calculation has to subtract it.

Paging needs consideration too. By default Swiper advances one slide at a time, which in a grid moves the layout by a single column and feels fussy. slidesPerGroup makes each swipe or button press move a whole page, and it should equal slidesPerView — 2, 3 or 4 columns depending on width, set through breakpoints — so the pages align cleanly. Watch that the number of slides divides nicely by rows and columns, or the last page will have gaps.

The controls are separate elements rather than defaults: custom previous and next buttons wired through the navigation module, with a disabledClass so they dim at either end, and a progress-bar pagination that shows how far along the grid you are — more useful than dots for a long list. The tiles are real links with visible focus outlines, keyboard control is enabled, and the a11y module labels the controls. Categories use gradients and emoji so no images are required.

Step by step

How to Use

  1. 1
    Swipe a pageDrag the grid sideways. It moves a whole page of tiles at once rather than one column.
  2. 2
    Use the buttonsPress the arrow buttons. They dim when you reach the first or last page.
  3. 3
    Read the progress barThe bar underneath fills as you move through the grid.
  4. 4
    Resize the frameWiden or narrow the preview to see the column count change from 2 to 3 to 4.
  5. 5
    Tab through tilesUse Tab to focus tiles and see the visible focus outline.

Real-world uses

Common Use Cases

🗂️
Category and department pickers
Offer many categories at once in a two-row sideways grid, with slidesPerGroup moving one full page per swipe.
📱
App-style launchers
Present app-style shortcuts as swipeable pages of icons in a launcher, with responsive column counts defined through Swiper breakpoints.
🧩
Template galleries
Browse a large set of templates or widgets, with custom previous and next buttons and a progress bar showing position.
🔄
Coverflow comparison
Compare with the Swiper coverflow product carousel when a single focused item matters more than many options at once.
🎓
Grid layout in sliders
See how container height and slide height maths must account for the gap when using Swiper's grid module.

Got questions?

Frequently Asked Questions

Use grid: { rows: 2 }, give the container a fixed height, and set each slide's height to its share of that height.

fill: "row" places slides left to right then down, while fill: "column" places them top to bottom then across.

slidesPerGroup defaults to 1. Set it equal to slidesPerView so each swipe moves a full page.

Grid mode needs a definite container height and slide heights that subtract the gap between rows.

Use breakpoints to set slidesPerView and slidesPerGroup for each width.

Set pagination: { type: "progressbar" } and style the .swiper-pagination-progressbar-fill element.

Yes. Use the JSX, Vue, Angular or Tailwind export buttons on this page to convert the markup and styles. The behaviour comes from Swiper, so in a framework project install it with npm install swiper (its React and Vue components take the same options) instead of the CDN tag, use the Swiper and SwiperSlide components, or create it in useEffect / onMounted / ngAfterViewInit, and release it with destroy() when the component unmounts.