Back to components
Components

Gallery

A responsive grid of images that opens in a shared lightbox.

Component

Props

Props Required Default Type
imagestrue — GalleryImage[]
cols — 3number
tabletCols — 2number
mobileCols — 1number
gapClass — 'gap-4'string
aspectRatio — AspectRatio.AR_1_1AspectRatio
fit — ImageFit.COVERImageFit
hoverEffect — ImageHoverEffect.ZOOM_INImageHoverEffect
hoverSplitDirection — ImageHoverSplitDirection.DIAGONALImageHoverSplitDirection
captionPlacement — ImageCaptionPlacement.NONEImageCaptionPlacement
paginationMode — GalleryPaginationMode.NONEGalleryPaginationMode
itemsPerPage — 12number
page — — number
loadMoreText — useDSConfig().gallery.loadMoreText()string
paginationProps — — Record<string, unknown>
useLightbox — trueboolean
useLightboxLoop — trueboolean
showLightboxCaption — trueboolean
useNuxtImg — falseboolean
sizes — — string
densities — — string
loading — ImageLoading.LAZYImageLoading
containerClass — — string
imageClass — — string
captionClass — — string
paginationClass — — string

Usage

images

Sets the images to display. Each one becomes an Image in the grid and a slide in the lightbox.

 <template>
    <Gallery :images />
</template>
<script setup lang="ts">
const images: GalleryImage[] = [
    { id: '1', src: '/images/river.jpg', alt: 'River between mountains', caption: 'River valley' },
    { id: '2', src: '/images/lake.jpg', alt: 'Quiet lake', caption: 'Quiet lake' },
]
</script>
 
  • Type: GalleryImage[]

TypeScript Interface

 interface GalleryImage {
    id: string
    src: string
    alt: string // Redundant wording such as "Image of" is removed with cleanImageAlt
    caption?: string | null
    width?: number
    height?: number
}
 

cols

Sets the number of columns on desktop.

 <template>
    <Gallery :images :cols="4" />
</template>
 
  • Type: number
  • Default: 3

tabletCols

Sets the number of columns on tablet.

 <template>
    <Gallery :images :tabletCols="3" />
</template>
 
  • Type: number
  • Default: 2

mobileCols

Sets the number of columns on mobile.

 <template>
    <Gallery :images :mobileCols="2" />
</template>
 
  • Type: number
  • Default: 1

gapClass

Sets the gap between images with a Tailwind class.

 <template>
    <Gallery :images gapClass="gap-8" />
</template>
 
  • Type: string
  • Default: 'gap-4'

aspectRatio

Crops every image to the same ratio via the AspectRatio enum, which keeps the grid aligned even when the sources have different sizes.

 <template>
    <Gallery :images :aspectRatio="AspectRatio.AR_4_3" />
</template>
 
  • Type: AspectRatio
  • Default: AspectRatio.AR_1_1

Options

Value Description
AR_1_1

1:1

AR_4_3

4:3

AR_3_2

3:2

AR_16_9

16:9

AR_3_4

3:4

AR_4_5

4:5

AR_2_3

2:3

fit

Sets how each image fills its box via the ImageFit enum.

 <template>
    <Gallery :images :fit="ImageFit.CONTAIN" />
</template>
 
  • Type: ImageFit
  • Default: ImageFit.COVER

Options

Value Description
COVER

cover

CONTAIN

contain

hoverEffect

Sets the hover effect of every image via the ImageHoverEffect enum.

 <template>
    <Gallery :images :hoverEffect="ImageHoverEffect.GRAYSCALE" />
</template>
 
  • Type: ImageHoverEffect
  • Default: ImageHoverEffect.ZOOM_IN

Options

Value Description
NONE

none

ZOOM_IN

zoomIn

ZOOM_OUT

zoomOut

OVERLAY

overlay

BLUR

blur

GRAYSCALE

grayscale

SPLIT_ZOOM

splitZoom

hoverSplitDirection

Sets the separation direction of the SPLIT_ZOOM effect.

 <template>
    <Gallery
        :images
        :hoverEffect="ImageHoverEffect.SPLIT_ZOOM"
        :hoverSplitDirection="ImageHoverSplitDirection.VERTICAL"
    />
</template>
 
  • Type: ImageHoverSplitDirection
  • Default: ImageHoverSplitDirection.DIAGONAL

Options

Value Description
DIAGONAL

diagonal

HORIZONTAL

horizontal

VERTICAL

vertical

captionPlacement

Sets where the image captions are displayed on the grid. They are hidden by default and are still shown in the lightbox.

 <template>
    <Gallery :images :captionPlacement="ImageCaptionPlacement.BELOW" />
</template>
 
  • Type: ImageCaptionPlacement
  • Default: ImageCaptionPlacement.NONE

Options

Value Description
NONE

none

BELOW

below

OVERLAY_BOTTOM

overlayBottom

HOVER

hover

paginationMode

Sets how the images are split via the GalleryPaginationMode enum. The lightbox always navigates through the whole list, whatever the page.

 <template>
    <Gallery
        :images
        :paginationMode="GalleryPaginationMode.LOAD_MORE"
        :itemsPerPage="9"
    />
</template>
 
  • Type: GalleryPaginationMode
  • Default: GalleryPaginationMode.NONE

Options

Value Description
NONE

Shows every image.

BUTTONS

Shows one page at a time with numbered buttons (`ButtonPagination`).

SIMPLE

Shows one page at a time with previous and next buttons (`SimplePagination`).

LOAD_MORE

Shows a button that adds the next batch below the current images.

INFINITE

Adds the next batch automatically when you scroll to the end of the grid.

itemsPerPage

Sets how many images are shown per page, or per batch with LOAD_MORE and INFINITE.

 <template>
    <Gallery
        :images
        :paginationMode="GalleryPaginationMode.BUTTONS"
        :itemsPerPage="6"
    />
</template>
 
  • Type: number
  • Default: 12

page

Sets the current page. Bind it with v-model:page to control or read it from outside. Without it, the gallery keeps its own page state. With LOAD_MORE and INFINITE it is the number of batches shown. Out of range values are clamped.

 <template>
    <Gallery
        v-model:page="page"
        :images
        :paginationMode="GalleryPaginationMode.BUTTONS"
    />
</template>
<script setup lang="ts">
const page = ref(1)
</script>
 
  • Type: number

loadMoreText

Sets the text of the button shown with LOAD_MORE. Falls back to useDSConfig().gallery.loadMoreText().

 <template>
    <Gallery
        :images
        :paginationMode="GalleryPaginationMode.LOAD_MORE"
        loadMoreText="Show more photos"
    />
</template>
 
  • Type: string
  • Default: useDSConfig().gallery.loadMoreText()

paginationProps

Passes extra props to the pagination component, either ButtonPagination or SimplePagination. Use it to translate the result texts and aria labels for this gallery only. To translate them everywhere, set useDSConfig().pagination once instead. The pagination props the gallery controls itself, such as the page and the total, can't be overridden.

 <template>
    <Gallery
        :images
        :paginationMode="GalleryPaginationMode.BUTTONS"
        :paginationProps="{
            resultTextMultiplePages: 'Mostrando {from} a {to} de {total} imágenes',
            ariaLabelPrevious: 'Página anterior',
            ariaLabelNext: 'Página siguiente',
        }"
    />
</template>
 
  • Type: Record<string, unknown>

useLightbox

Opens a single Lightbox on the clicked image, so you can navigate through the whole gallery. Set it to false for a static grid.

 <template>
    <Gallery :images :useLightbox="false" />
</template>
 
  • Type: boolean
  • Default: true

useLightboxLoop

Wraps the lightbox navigation around at both ends.

 <template>
    <Gallery :images :useLightboxLoop="false" />
</template>
 
  • Type: boolean
  • Default: true

showLightboxCaption

Shows the image caption inside the lightbox.

 <template>
    <Gallery :images :showLightboxCaption="false" />
</template>
 
  • Type: boolean
  • Default: true

useNuxtImg

Renders every image with NuxtImg from @nuxt/image. It requires the @nuxt/image module in your app.

 <template>
    <Gallery :images useNuxtImg sizes="100vw md:50vw lg:33vw" />
</template>
 
  • Type: boolean
  • Default: false

sizes

Sets the sizes attribute passed to NuxtImg. It only applies with useNuxtImg.

 <template>
    <Gallery :images useNuxtImg sizes="100vw md:50vw" />
</template>
 
  • Type: string

densities

Sets the densities attribute passed to NuxtImg. It only applies with useNuxtImg.

 <template>
    <Gallery :images useNuxtImg densities="x1 x2" />
</template>
 
  • Type: string

loading

Sets how the browser loads every image via the ImageLoading enum. Images are lazy by default. Use EAGER when the gallery is above the fold.

 <template>
    <Gallery :images :loading="ImageLoading.EAGER" />
</template>
 
  • Type: ImageLoading
  • Default: ImageLoading.LAZY

Options

Value Description
LAZY

lazy

EAGER

eager

containerClass

Adds custom classes to the root element.

 <template>
    <Gallery :images containerClass="max-w-4xl mx-auto" />
</template>
 
  • Type: string

imageClass

Adds custom classes to every img element.

 <template>
    <Gallery :images imageClass="object-top" />
</template>
 
  • Type: string

captionClass

Adds custom classes to every caption.

 <template>
    <Gallery :images captionClass="text-center" />
</template>
 
  • Type: string

paginationClass

Adds custom classes to the element that wraps the pagination or the load more button.

 <template>
    <Gallery
        :images
        :paginationMode="GalleryPaginationMode.BUTTONS"
        paginationClass="mt-10"
    />
</template>
 
  • Type: string

Accessibility

Each image is a native button when the lightbox is on, so the gallery works with Tab, Enter and Space. Alt text comes from each GalleryImage. The pagination components are native navigation with labelled buttons. With INFINITE, the sentinel that triggers loading is hidden from assistive technology, so prefer LOAD_MORE when keyboard and screen reader users need to control when more images appear. Inside the lightbox you can use the arrow keys to navigate and Escape to close it. See the Lightbox accessibility notes.

Emits

Value Description
@click

Emits the clicked `GalleryImage` and its index in the full list when an image is clicked with `useLightbox` on.

@update:page

Emits the new page number when the page changes, from the pagination, the load more button or infinite scroll.

Example

 <template>
    <Gallery :images @click="handleClick" />
</template>
<script setup lang="ts">
const handleClick = (image: GalleryImage, index: number) => {
    console.log('Clicked', image.id, index)
}
</script>