Gesso
Layout

Gallery

Rows, an even grid, or a masonry, for a list of cards that are not all the same height.

Gallery arranges a list of children. rows gives each child the full width, grid gives them equal columns and stretches a short card to its row, and masonry lets each child keep its own height. It does not draw the children. Interactive card is the usual one: vertical and horizontal, short and long, in the same list.

Switch the layout. The same six cards reflow. In the grid, the meta lines up across a row. In masonry, a short card sits higher than its neighbor. In rows, each card spans the list, and the horizontal one keeps its media beside the text.

Usage

import { Gallery } from '@/components/ui/gallery';
import {
  InteractiveCard,
  InteractiveCardContent,
  InteractiveCardMedia,
  InteractiveCardTitle,
} from '@/components/ui/interactive-card';

<Gallery layout="masonry" columns={3}>
  <InteractiveCard asChild>
    <a href="/notes/north-shore">
      <InteractiveCardMedia>
        <img src="/notes/north-shore.jpg" alt="" />
      </InteractiveCardMedia>
      <InteractiveCardContent>
        <InteractiveCardTitle>North shore survey</InteractiveCardTitle>
      </InteractiveCardContent>
    </a>
  </InteractiveCard>
</Gallery>

Each child is one item. Pass the cards you already build. Gallery does not clone them or read their slots.

Rows, grid, and masonry

rows is one column. A horizontal card stays side by side, because the row is wide. A vertical card's media spans that width.

grid is equal columns: one on a narrow screen, two from sm, and the columns count from lg when that count is 3 or 4. A vertical card stretches to the height of its row, so a footer sits on the same line as the footer beside it. A horizontal card keeps its picture as tall as its text.

masonry uses the same column counts and lets each card be as tall as its content. The items paint down the columns. A horizontal card in a narrow column wraps its text under the media, because the card is narrower than 20rem.

columns is 2, 3, or 4, and 3 is the default. Rows ignore it.

Props

Gallery takes every <ul> attribute, plus these.

PropTypeDefaultWhat it does
layout"rows" | "grid" | "masonry""grid"rows stacks full-width items. grid makes equal columns and stretches each item to its row. masonry packs items at their own height.
columns2 | 3 | 43How many columns the grid or masonry uses from lg. Two columns arrive at sm. Rows stay one column.

galleryVariants({ layout, columns }) returns the classes, for styling a list that is not a Gallery.

Accessibility

  • Gallery is a <ul>, and each child is an <li>, so a screen reader announces the count. The child keeps its own role. An interactive card rendered as a link is still a link, inside the list item.
  • Tab order follows the source. A grid and a row of cards match that order on screen. Masonry paints down the columns, so focus can move to a card that is not the next one you see.
  • Gallery adds no keys of its own. A card keeps its inset focus ring, and a reveal card's action still sits above the stretched title link.
  • The list does not clip its children, so a card can lift and draw its shadow without the row cutting them off.
  • Gallery has no motion of its own. A card inside it still follows motion-safe.
  • Forced colors keep each card's border. The list draws none of its own.

When to use something else

  • One Interactive card, or a Card, when there is nothing to arrange.
  • Item for a list of rows that are not framed cards. ItemGroup stacks them and does not make columns.
  • Table when the cells line up in columns a reader compares.

Install

shadcn add @gesso/gallery

On this page