VImage
Основной компонент. Объединяет ленивую загрузку, плейсхолдер, переключение форматов и переходы в одном элементе.
<VImage
src="/photo.jpg"
alt="Описание"
:width="1200"
:height="600"
blurhash="LEHV6nWB2yk8pyo0adR*.7kCMdnj"
placeholder="data:image/jpeg;base64,..."
:widths="[400, 800, 1200]"
sizes="(max-width: 768px) 100vw, 50vw"
:lazy="true"
root-margin="300px"
fit="cover"
@load="onLoad"
@error="onError"
>
<template #error>
<div class="my-error">Image failed to load</div>
</template>
</VImage>Пропы
src
string | SrcSet, опционален, если задан image. URL или объект с вариантами форматов.
image
ImageMeta, опционален. Метаданные, вычисленные на этапе сборки (запись из манифеста CLI или импорт ?vik) — задаёт src/width/height/hazehash/blurhash/thumbhash/placeholder/sizes. Любой явно указанный проп выше переопределяет соответствующее поле.
Если зарегистрирован манифест плейсхолдеров, его запись для src этого изображения так же заполняет width/height/hazehash/blurhash/thumbhash — после явных пропсов и image.
alt
string, обязателен. Атрибут alt на <img>. В dev-сборках подозрительное значение (пустое, состоящее только из пробелов, или похожее на имя файла вроде "photo.jpg") логирует console.warn — осознанный alt="" для декоративного изображения никогда его не вызывает.
width
number, опционален. Собственная ширина; используется для резервирования пространства под aspect-ratio.
height
number, опционален. Собственная высота; используется для резервирования пространства под aspect-ratio.
hazehash
string, опционален. Строка HazeHash из опционального пакета hazehash; декодируется по требованию в невидимый canvas в памяти и становится CSS-фоном самого элемента. Предпочтительный плейсхолдер: имеет приоритет над blurhash, thumbhash и placeholder. Если пакет не установлен, используется следующий плейсхолдер.
blurhash
string, опционален. Строка BlurHash; декодируется в невидимый canvas в памяти (никогда не попадает в DOM) и становится CSS-фоном самого элемента. Имеет приоритет над placeholder/thumbhash, но уступает hazehash — если blurhash задан и может отрендериться, LQIP/ThumbHash-плейсхолдер вообще не показывается (они взаимоисключающие, а не накладываются друг на друга).
thumbhash
string, опционален. Строка ThumbHash; декодируется в PNG data URL, используется как blur-up плейсхолдер.
placeholder
string, опционален. Base64 LQIP или ThumbHash data URL; переопределяет thumbhash, если заданы оба.
ssrPlaceholder
boolean · по умолчанию: false. Сервер отдаёт дешёвое превью вместо тяжёлой картинки: готовое превью становится CSS-фоном отрендеренного <img>, а ленивая картинка не загружается, пока не приблизится к области просмотра, — после гидрации её подставляет тот же IntersectionObserver (rootMargin), что управляет любой ленивой картинкой. Без пропса сервер отдаёт обычный <img src="…" loading="lazy">, который браузер может начать скачивать задолго до гидрации, а blur появляется только после гидрации.
У ленивой картинки серверный <img> получает прозрачный пиксель 1×1 вместо настоящего src, а настоящий <img> кладётся рядом в <noscript>, поэтому поисковики и посетители без JavaScript всё равно получают полное изображение. У нетерпеливой (lazy="false" или priority) настоящий src остаётся, а превью просто лежит фоном под ней — используйте это для картинки в начале страницы.
Превью должно быть уже готовым data: URL: проп placeholder, image.placeholder или превью, которое Vite-плагин зарегистрировал для этого src (imports: { preview }). BlurHash или ThumbHash сами по себе на сервере не декодируются (там нет canvas), поэтому если задан только хеш, проп ничего не делает. Он также игнорируется вместе с placeholderColor, placeholderMode="color" и placeholderMode="shimmer". После гидрации это же превью остаётся под картинкой, пока она не загрузится. См. Превью в серверном HTML.
placeholderMode
'blur' | 'color' | 'shimmer' · по умолчанию: 'blur'. 'color' показывает сплошной цвет — доминирующий цвет из манифеста плейсхолдеров или средний цвет thumbhash; 'shimmer' показывает анимированный скелетон (хэш не нужен).
placeholderColor
string, опционален. Явный сплошной CSS-цвет плейсхолдера; имеет приоритет и не требует декодирования.
widths
number[], опционален. Ширины в пикселях для автоматической генерации srcset на основе ширины (w).
densities
number[] | Record<number, string>, опционален. Дескрипторы плотности (1x/2x/3x) для изображений фиксированного размера. Список переиспользует src; объект даёт отдельный файл на плотность. Имеет приоритет над widths, игнорирует sizes.
sizes
string, опционален. Атрибут sizes, передаваемый в <img> (только для srcset на основе ширины).
breakpoints
BreakpointMap, опционален. Локальные брейкпоинты (сливаются с глобальными брейкпоинтами плагина).
sources
ResponsiveSrc, опционален. Объект брейкпоинт → URL (или { avif?, webp?, fallback }) для арт-дирекции, опционально комбинируемый с переключением формата на брейкпоинт. Запись может нести и собственные width/height и плейсхолдер (blurhash, thumbhash, placeholder, placeholderColor), которые используются, пока активен её брейкпоинт, — см. Плейсхолдеры на брейкпоинт.
lazy
boolean · по умолчанию: true. Включить ленивую загрузку через IntersectionObserver.
rootMargin
string · по умолчанию: "200px". rootMargin для IO — насколько раньше вьюпорта начинается загрузка.
threshold
number · по умолчанию: 0. threshold для IO — требуемая доля пересечения для срабатывания.
fit
ObjectFit, опционален. Значение CSS object-fit на <img>. Если задан явно, применяется всегда. Если не задан, по умолчанию используется "cover" — но только через переопределяемый CSS-класс, и только когда размер блока изображения действительно ограничен (layout="fill"/"fixed", либо заданы одновременно width и height); в остальных случаях ничего не применяется, так как object-fit не имеет эффекта без ограниченного блока.
focal
FocalPoint, опционален. Фокальная точка { x, y } (доли 0–1) → object-position; сохраняет объект в кадре, когда fit="cover" обрезает изображение.
maxRetries
number · по умолчанию: 0. Максимум попыток повтора при неудаче загрузки.
retryDelay
number · по умолчанию: 1000. Начальная задержка в мс; удваивается на каждом повторе (экспоненциальная задержка).
fetchpriority
'high' | 'low' | 'auto', опционален. Подсказка браузеру о приоритете загрузки.
decoding
'async' | 'sync' | 'auto' · по умолчанию: 'async'. Режим декодирования изображения.
priority
boolean · по умолчанию: false. Сокращение для LCP/hero-изображения — форсирует lazy=false, fetchpriority='high', decoding='sync'. Не автоматическое определение LCP (это ненадёжно до отрисовки) — отметьте именно то изображение, которое важно, вместо ручной установки трёх пропов.
respectSaveData
boolean · по умолчанию: false. На соединении с экономией трафика: нейтрализует priority (остаётся lazy) и понижает src до наименьшего доступного URL из densities/image.srcset. См. Адаптация к сети.
layout
'fixed' | 'responsive' | 'fill', опционален. Пресет размещения — применяется напрямую к элементу, который сейчас показывает картинку (никакой обёртки нет, см. Компоновка без обёртки). Если не задан, поведение полностью идентично 'responsive' — включая автогенерацию sizes. См. Пресеты раскладки.
cdn
boolean | AutoLoaderConfig, опционален. Опционально: пропускает строковый src через autoLoader() — определяет CDN по URL и переписывает его, без ручной настройки адаптера. См. CDN-адаптеры → Автоопределение CDN с VImage.
loader
'server', опционален. Опционально: пропускает строковый src через обработчик самостоятельного сервера по запросу, используя buildImageUrl(). См. Самостоятельный сервер по запросу → Подключение VImage к нему.
loaderRoute
string · по умолчанию: /_vik/image. Переопределение маршрута для loader="server" — имеет приоритет над значением по умолчанию serverRoute плагина/модуля Nuxt.
fadeIn
boolean · по умолчанию: false. Плавное появление блока целиком (opacity 0→1, ~0.3с) вскоре после монтирования — не привязано конкретно к моменту загрузки фото. Плейсхолдер и фото рисуются на одном и том же элементе (фон + содержимое), поэтому fadeIn плавно проявляет весь блок целиком, а не «блюр сквозь проступающее резкое фото» — как только фото готово, оно мгновенно перекрывает фон-плейсхолдер под собой. По умолчанию выключен: переключение плейсхолдер → фото происходит мгновенно.
События
@load
Event. Срабатывает при завершении загрузки изображения.
@error
Event. Срабатывает при неудаче загрузки изображения.
Слоты
#error
Кастомный UI, показываемый при неудаче загрузки. Если не задан, показывается серый прямоугольник с иконкой битого изображения.
Примеры
Простое изображение с ленивой загрузкой:
<VImage src="/photo.jpg" alt="Landscape" />С blurhash и размерами для резервирования aspect-ratio:
<VImage
src="/photo.jpg"
alt="Landscape"
:width="1200"
:height="800"
blurhash="LEHV6nWB2yk8pyo0adR*.7kCMdnj"
/>WebP/AVIF с srcset и blur-up:
<VImage
:src="{ avif: '/photo.avif', webp: '/photo.webp', fallback: '/photo.jpg' }"
alt="Product"
:width="800"
:height="600"
placeholder="data:image/jpeg;base64,/9j/4AAQSkZJRgAB..."
:widths="[400, 800]"
sizes="(max-width: 640px) 100vw, 800px"
/>Отключение ленивой загрузки для изображений над первым экраном:
<VImage src="/hero.jpg" alt="Hero" :lazy="false" />LCP/hero-изображение — priority вместо трёх отдельных пропов:
<VImage src="/hero.jpg" alt="Hero" :width="1600" :height="900" priority />Из вывода CLI/манифеста — без ручной настройки пропов:
<script setup lang="ts">
import meta from './photo.jpg?vik' // или: import { images } from './assets/images'
</script>
<template>
<!-- src/width/height/hazehash/blurhash/thumbhash/placeholder/sizes — всё из meta -->
<VImage :image="meta" alt="Product photo" />
</template>Фокальная точка — сохранить объект в кадре при обрезке:
<!-- При fit="cover" изображение обрезается под рамку; focal определяет,
какая часть выживает. { x: 0.5, y: 0.3 } отдаёт приоритет верхней середине (например, лицу). -->
<VImage
src="/portrait.jpg"
alt="Team member"
:width="400"
:height="400"
fit="cover"
:focal="{ x: 0.5, y: 0.3 }"
/>Самый дешёвый плейсхолдер — сплошной средний цвет (без декодирования, 0 байт):
<!-- Режим 'color' берёт средний RGBA прямо из заголовка ThumbHash. -->
<VImage
src="/photo.jpg"
alt="Gallery item"
:width="600"
:height="400"
thumbhash="3OcRJYB4d3h/iIeHeEh3eIhw+j5n"
placeholder-mode="color"
/>
<!-- Или явный цвет, который вы уже знаете — ThumbHash вообще не нужен. -->
<VImage src="/photo.jpg" alt="Banner" placeholder-color="#1e3a8a" />Анимированный скелетон — когда хэша нет вообще:
<!-- CSS shimmer-переход до загрузки изображения. Учитывает prefers-reduced-motion. -->
<VImage src="/photo.jpg" alt="Card" :width="400" :height="300" placeholder-mode="shimmer" />Плавное появление блока при монтировании:
<!-- По умолчанию переключение плейсхолдер → фото мгновенное. fadeIn
добавляет лёгкое opacity-появление всего блока целиком. -->
<VImage
src="/photo.jpg"
alt="Gallery item"
:width="600"
:height="400"
blurhash="LEHV6nWB2yk8pyo0adR*.7kCMdnj"
fade-in
/>Кастомный слот ошибки:
<VImage src="/missing.jpg" alt="Missing">
<template #error>
<div class="placeholder">
<span>📷</span>
<p>Image unavailable</p>
</div>
</template>
</VImage>Обработка событий:
<script setup lang="ts">
function onLoad(e: Event) {
console.log('Image loaded', e)
}
function onError(e: Event) {
console.warn('Image failed', e)
}
</script>
<template>
<VImage src="/photo.jpg" alt="Photo" @load="onLoad" @error="onError" />
</template>