Адаптивные изображения
srcset + sizes
Передайте widths, чтобы автоматически сгенерировать атрибут srcset:
<VImage
src="/photo.jpg"
alt="Photo"
:widths="[400, 800, 1200]"
sizes="(max-width: 768px) 100vw, 50vw"
/>Рендерит:
<img
src="/photo.jpg"
srcset="/photo.jpg 400w, /photo.jpg 800w, /photo.jpg 1200w"
sizes="(max-width: 768px) 100vw, 50vw"
alt="Photo"
/>Если widths не задан, srcset не добавляется — используется обычный src. Если widths задан, а sizes — нет, sizes по умолчанию становится "100vw".
Дескрипторы плотности (1x / 2x / 3x)
Для изображений фиксированного размера — иконок, аватаров, логотипов — используйте densities вместо widths. Браузер выбирает кандидата, соответствующего плотности пикселей устройства; sizes не нужен. densities имеет приоритет над widths (два типа дескрипторов нельзя смешивать в одном srcset).
:densities принимает две формы:
<!-- 1. Карта URL по плотности — отдельные файлы (рекомендуется для статичных ассетов). -->
<VImage
src="/avatar.png"
alt="Avatar"
:width="48"
:height="48"
:densities="{ 1: '/avatar.png', 2: '/avatar@2x.png', 3: '/avatar@3x.png' }"
/>
<!-- → srcset="/avatar.png 1x, /avatar@2x.png 2x, /avatar@3x.png 3x" -->
<!-- 2. Список плотностей — переиспользует единственный `src` для каждой плотности. Полезно
только когда сам URL учитывает разрешение (эндпоинт CDN/DPR). -->
<VImage src="https://cdn.example.com/avatar?dpr=auto" alt="Avatar" :densities="[1, 2, 3]" />
<!-- → srcset="…?dpr=auto 1x, …?dpr=auto 2x, …?dpr=auto 3x" -->Использование утилит напрямую:
import { generateSrcset, generateSizes, generateDensitySrcset } from 'vue-image-kit'
generateSrcset('/photo.jpg', [400, 800, 1200])
// → '/photo.jpg 400w, /photo.jpg 800w, /photo.jpg 1200w'
generateSizes('(max-width: 768px) 100vw, 50vw')
// → '(max-width: 768px) 100vw, 50vw'
generateSizes()
// → '100vw'
generateDensitySrcset('/logo.png', [1, 2, 3])
// → '/logo.png 1x, /logo.png 2x, /logo.png 3x'
// Отдельные файлы на плотность через карту URL:
generateDensitySrcset({ 1: '/a.png', 2: '/a@2x.png' }, [1, 2])
// → '/a.png 1x, /a@2x.png 2x'Переключение источников WebP / AVIF
Когда src — объект вместо строки, <VImage> рендерит элемент <picture> с соответствующими элементами <source>:
<VImage
:src="{
avif: '/photo.avif',
webp: '/photo.webp',
fallback: '/photo.jpg',
}"
alt="Photo"
:width="1200"
:height="800"
/>Рендерит:
<picture>
<source srcset="/photo.avif" type="image/avif" />
<source srcset="/photo.webp" type="image/webp" />
<img src="/photo.jpg" alt="Photo" width="1200" height="800" />
</picture>Браузер выбирает первый поддерживаемый формат. Если задан только webp, добавляется только один <source>. fallback требуется всегда.
Объект SrcSet
interface SrcSet {
avif?: string // URL версии AVIF
webp?: string // URL версии WebP
fallback: string // Обязателен — оригинальный формат (JPEG/PNG)
}Адаптивные источники (арт-дирекция)
Используйте, когда нужно отдавать принципиально другое изображение (другая обрезка, другая композиция) в зависимости от размера экрана. Реализовано через именованные брейкпоинты — браузер выбирает первый подходящий <source media="...">.
Глобальные брейкпоинты (задаются один раз при установке плагина)
// main.ts
app.use(VImageKitPlugin, {
breakpoints: {
sm: '(max-width: 640px)',
md: '(max-width: 1024px)',
lg: '(min-width: 1025px)',
},
})Использование в компонентах — только ключи
<VImage
src="/hero-desktop.jpg"
alt="Hero"
:sources="{
sm: '/hero-mobile.jpg',
md: '/hero-tablet.jpg',
}"
/>Генерирует:
<picture>
<source media="(max-width: 640px)" srcset="/hero-mobile.jpg" />
<source media="(max-width: 1024px)" srcset="/hero-tablet.jpg" />
<img src="/hero-desktop.jpg" alt="Hero" />
</picture>Порядок <source> устанавливается автоматически по возрастанию max-width — это требование <picture>, который выбирает первый подходящий source.
Брейкпоинты на уровне компонента
Сливаются с глобальными брейкпоинтами. Локальные ключи имеют приоритет при конфликте:
<VImage
src="/product-desktop.jpg"
alt="Product"
:breakpoints="{
xs: '(max-width: 375px)',
wide: '(min-width: 1600px)',
}"
:sources="{
xs: '/product-xs.jpg',
sm: '/product-mobile.jpg',
md: '/product-tablet.jpg',
wide: '/product-wide.jpg',
}"
/>Итоговый <picture> содержит элементы <source> для xs, sm, md (из слитых брейкпоинтов) и wide — отсортированные автоматически.
Комбинирование с AVIF/WebP
Адаптивные источники (sources) и источники по формату (src как объект) независимы и рендерятся вместе:
<VImage
:src="{ avif: '/hero.avif', webp: '/hero.webp', fallback: '/hero.jpg' }"
:sources="{ sm: '/hero-mobile.jpg' }"
alt="Hero"
/><picture>
<source media="(max-width: 640px)" srcset="/hero-mobile.jpg" />
<source srcset="/hero.avif" type="image/avif" />
<source srcset="/hero.webp" type="image/webp" />
<img src="/hero.jpg" alt="Hero" />
</picture>Это покрывает вариант «один набор обрезки + один набор форматов, независимо друг от друга». Для другой обрезки и других форматов на разных брейкпоинтах — например, портретная обрезка AVIF/WebP на мобильном, ландшафтная AVIF/WebP на десктопе — значение брейкпоинта в sources само может быть объектом { avif?, webp?, fallback } вместо обычного URL:
<VImage
alt="Hero"
:sources="{
sm: { avif: '/hero-mobile.avif', webp: '/hero-mobile.webp', fallback: '/hero-mobile.jpg' },
md: { webp: '/hero-tablet.webp', fallback: '/hero-tablet.jpg' },
}"
src="/hero-desktop.jpg"
/><picture>
<source media="(max-width: 640px)" srcset="/hero-mobile.avif" type="image/avif" />
<source media="(max-width: 640px)" srcset="/hero-mobile.webp" type="image/webp" />
<source media="(max-width: 640px)" srcset="/hero-mobile.jpg" />
<source media="(max-width: 1024px)" srcset="/hero-tablet.webp" type="image/webp" />
<source media="(max-width: 1024px)" srcset="/hero-tablet.jpg" />
<img src="/hero-desktop.jpg" alt="Hero" />
</picture>Брейкпоинты с обычным URL и с объектом формата можно свободно смешивать в одном объекте sources. avif/webp опциональны для каждого брейкпоинта — испускаются только те форматы, которые у вас реально есть.
BreakpointMap
type BreakpointMap = Record<string, string>
// ключ — произвольное имя, значение — CSS media queryПриоритет брейкпоинтов
| Источник | Приоритет |
|---|---|
Локальный проп breakpoints на компоненте | Высокий — переопределяет глобальные ключи при конфликте |
Глобальные breakpoints из VImageKitPlugin | Базовый — доступны во всех компонентах |
buildSizes helper
Постройте строку атрибута sizes из объекта, ключи которого — брейкпоинты — работает с именованными брейкпоинтами плагина.
import { buildSizes } from 'vue-image-kit'
const breakpoints = { sm: '(max-width: 640px)', md: '(max-width: 1024px)' }
buildSizes({ sm: '100vw', md: '50vw', default: '33vw' }, breakpoints)
// → '(max-width: 640px) 100vw, (max-width: 1024px) 50vw, 33vw'generatePreloadLink
Генерирует HTML-строку <link rel="preload"> для критичных изображений над первым экраном. Используйте в Nuxt useHead или внедряйте в SSR <head>, чтобы улучшить LCP.
import { generatePreloadLink, generateSrcset } from 'vue-image-kit'
const srcset = generateSrcset('/hero.jpg', [400, 800, 1200])
const link = generatePreloadLink('/hero.jpg', {
srcset,
sizes: '100vw',
})
// → '<link rel="preload" as="image" href="/hero.jpg" imagesrcset="..." imagesizes="100vw">'В Nuxt:
<script setup lang="ts">
import { generatePreloadLink } from 'vue-image-kit'
useHead({
link: [{ innerHTML: generatePreloadLink('/hero.jpg', { sizes: '100vw' }) }],
})
</script>Пресеты раскладки
Проп layout переключает способ размещения обёртки. Если оставить его незаданным, сохраняется текущее поведение по умолчанию — заполнение ширины контейнера, aspect-ratio сохраняется из width/height — так что для существующего кода ничего не меняется.
fixed — точная рамка width×height, без адаптивного масштабирования (как обычный <img width height>):
<VImage src="/icon.jpg" alt="Icon" :width="64" :height="64" layout="fixed" />responsive — то же поведение заполнения контейнера, что и по умолчанию, плюс автогенерируемый sizes из width, если sizes не задан явно ((min-width: {width}px) {width}px, 100vw — «шириной в свой собственный размер, иначе на всю ширину вьюпорта»):
<VImage
src="/photo.jpg"
alt="Photo"
:width="800"
:height="600"
:widths="[400, 800, 1200]"
layout="responsive"
/>fill — абсолютно заполняет позиционированного родителя (position: absolute; inset: 0); сам родитель должен иметь position: relative (или аналог). width/height становятся опциональными — типично для hero-баннеров или карточек, где размер задаёт контейнер:
<div style="position: relative; aspect-ratio: 16 / 9;">
<VImage src="/hero.jpg" alt="Hero" layout="fill" fit="cover" priority />
</div>