Skip to content

Image ​

Neo-brutalist image display component with IntersectionObserver lazy loading, fallback image support, and a full-screen preview modal featuring zoom, rotate, flip, and drag interactions — all wrapped in bold borders, hard shadows, and diagonal stripe placeholder backgrounds.

Demo ​

Preview

基础用法

基础图片示例
加载中...

大图预览(点击放大)

点击预览图片
加载中...

多图预览(左右切换)

多图预览
加载中...

懒加载

加载中...

加载失败 + Fallback

Fallback 图片
加载中...

Installation ​

pnpm dlx brutx-vue@latest add image

Usage ​

Basic Usage ​

Pass src and alt to render an image. Use fit to control how the image fills its container:

vue
<script setup>
import { Image } from 'brutx-ui-vue'
</script>

<template>
    <Image src="/photo.jpg" alt="Sample image" fit="cover" class="w-64 h-48" />
</template>

Lazy Loading ​

Set loading="lazy" to defer image loading until the element enters the viewport via IntersectionObserver:

vue
<template>
    <Image src="/large-photo.jpg" alt="Lazy loaded image" loading="lazy" class="w-full h-64" />
</template>

Fallback Image ​

When the primary image fails to load, the component automatically switches to the fallback URL:

vue
<template>
    <Image
        src="/broken-url.jpg"
        alt="Fallback demo"
        fallback="/fallback.jpg"
        class="w-64 h-48"
    />
</template>

Image Preview ​

Enable preview and provide a previewSrcList to open a full-screen preview modal when clicking the image:

vue
<script setup>
import { Image } from 'brutx-ui-vue'

const images = ['/photo1.jpg', '/photo2.jpg', '/photo3.jpg']
</script>

<template>
    <div class="flex gap-4">
        <Image
            v-for="img in images"
            :key="img"
            :src="img"
            :alt="img"
            :preview="true"
            :preview-src-list="images"
            class="w-32 h-32"
        />
    </div>
</template>

The preview modal supports the following interactions:

  • Zoom in / zoom out (via toolbar buttons, step controlled by zoomRate)
  • Rotate left / right by 90°
  • Horizontal flip
  • Mouse drag to pan the image
  • ArrowLeft / ArrowRight to navigate between images
  • Escape to close the preview
  • Set hideOnClickModal to true to close by clicking the backdrop

Custom Placeholder and Error Slots ​

Use the placeholder and error slots to customize loading and failure states:

vue
<template>
    <Image src="/photo.jpg" alt="Custom slots example" class="w-64 h-48">
        <template #placeholder>
            <div class="absolute inset-0 flex items-center justify-center bg-brutal-muted">
                <span class="font-bold">Loading...</span>
            </div>
        </template>
        <template #error>
            <div class="absolute inset-0 flex items-center justify-center bg-brutal-destructive/10">
                <span class="text-brutal-destructive font-bold">Failed to load</span>
            </div>
        </template>
    </Image>
</template>

Data Types ​

ts
type ImageFit = 'fill' | 'contain' | 'cover' | 'none' | 'scale-down'
ValueDescription
'fill'Stretches to fill the container without preserving aspect ratio
'contain'Scales to fit within the container while preserving aspect ratio
'cover'Scales to fill the container while preserving aspect ratio (may crop)
'none'Preserves the original size
'scale-down'Like contain, but never scales up beyond the original size

API Reference ​

Image — Props
NameTypeDefaultDescription
src
Required
string
—
The required primary image URL. It is also the preview viewer’s only image when previewSrcList is empty.
Details

Declared type

string

Default value details

Not declared
—

Source

Image.vue:14

packages/ui/src/components/image/Image.vue

alt
string | undefined
""
Alternative text passed to the native img element; describe the image for assistive technology.
Details

Declared type

string | undefined

Default value details

Resolved value
""

Source

Image.vue:15

packages/ui/src/components/image/Image.vue

fit
"fill" | "none" | "cover" | "contain" | "scale-down" | undefined
"cover"
Sets the image’s CSS object-fit mode.
Details

Declared type

"fill" | "none" | "cover" | "contain" | "scale-down" | undefined

Literal values

  • "contain"
  • "cover"
  • "fill"
  • "none"
  • "scale-down"

Default value details

Resolved value
"cover"

Source

Image.vue:16

packages/ui/src/components/image/Image.vue

previewSrcList
string[] | undefined
[]

Factory evaluated per instance

Provides the image URLs navigable in the preview viewer. Previous and next controls appear when the list has multiple entries.
Details

Declared type

string[] | undefined

Default value details

Resolved value
[]

Source

Image.vue:17

packages/ui/src/components/image/Image.vue

initialIndex
number | undefined
0
Sets the list index selected when the preview viewer opens.
Details

Declared type

number | undefined

Default value details

Resolved value
0

Source

Image.vue:18

packages/ui/src/components/image/Image.vue

hideOnClickModal
boolean | undefined
false
When enabled, clicking the preview backdrop closes the viewer and returns focus to the element that opened it.
Details

Declared type

boolean | undefined

Literal values

  • false
  • true

Default value details

Resolved value
false

Source

Image.vue:19

packages/ui/src/components/image/Image.vue

zoomRate
number | undefined
1.2
Sets the multiplier applied by each zoom-in or zoom-out action.
Details

Declared type

number | undefined

Default value details

Resolved value
1.2

Source

Image.vue:20

packages/ui/src/components/image/Image.vue

preview
boolean | undefined
false
Enables the image preview viewer with zoom, drag, and multi-image navigation.
Details

Declared type

boolean | undefined

Literal values

  • false
  • true

Default value details

Resolved value
false

Source

Image.vue:21

packages/ui/src/components/image/Image.vue

fallback
string | undefined
undefined
A fallback image URL tried after the primary image fails. The component enters its error state and emits error only if the fallback also fails.
Details

Declared type

string | undefined

Default value details

Declaration
undefined

Source: packages/ui/src/components/image/Image.vue

Resolved value
undefined

Source

Image.vue:22

packages/ui/src/components/image/Image.vue

loading
"eager" | "lazy" | undefined
"eager"
Selects eager loading or lazy loading, which uses IntersectionObserver to defer loading until the image approaches the viewport.
Details

Declared type

"eager" | "lazy" | undefined

Literal values

  • "eager"
  • "lazy"

Default value details

Resolved value
"eager"

Source

Image.vue:23

packages/ui/src/components/image/Image.vue

Image — Events
NameSignature or typeDescription
@close
[]
Emitted when the preview viewer closes; the component then attempts to restore focus to the previously active element.
Details

Declared type

[]

Source

Image.vue

packages/ui/src/components/image/Image.vue

@error
[event: Event]
Emitted with the final native image error event when both the primary and fallback images fail to load.
Details

Declared type

[event: Event]

Source

Image.vue

packages/ui/src/components/image/Image.vue

@load
[event: Event]
Emitted with the native image event when an image loads successfully, including a successful fallback image.
Details

Declared type

[event: Event]

Source

Image.vue

packages/ui/src/components/image/Image.vue

@show
[]
Emitted when the preview viewer opens.
Details

Declared type

[]

Source

Image.vue

packages/ui/src/components/image/Image.vue

@switch
[index: number]
Emitted with the new image-list index after the preview viewer switches images.
Details

Declared type

[index: number]

Source

Image.vue

packages/ui/src/components/image/Image.vue

Image — Slots
NameSignature or typeDescription
#placeholder
{}
Renders custom content while the image is loading; the built-in loading placeholder is used when omitted.
Details

Declared type

{}

Source

Image.vue

packages/ui/src/components/image/Image.vue

#error
{}
Renders custom error content after the image and fallback fail; the built-in failure placeholder is used when omitted.
Details

Declared type

{}

Source

Image.vue

packages/ui/src/components/image/Image.vue

Accessibility ​

  • Keyboard Navigation: The preview modal supports Escape to close and ArrowLeft / ArrowRight to navigate between images
  • ARIA Attributes: Close, previous, and next buttons in the preview modal all include aria-label attributes. Always provide meaningful alt text for screen readers and when images fail to load
  • Focus Management: The preview modal uses reka-ui's FocusScope component with trapped and loop modes, preventing focus from escaping the modal

FAQ ​

Q: The image doesn't appear when loading="lazy" is set?

A: Lazy loading relies on IntersectionObserver, which requires the component container to have definite dimensions (set via class or a parent container). If the container has zero dimensions, the IntersectionObserver callback will never fire.

Q: How do I navigate between images in the preview?

A: You need to pass a previewSrcList array. Inside the preview modal, you can navigate using the arrow buttons or keyboard arrow keys. If the list contains one or zero items, the navigation buttons are hidden.

Q: What happens if the fallback image also fails to load?

A: When the fallback image also fails, the component enters its error state, displays the error slot content (or the default error placeholder), and emits the error event.

Brute force builds.