Пошук уроків, статей та іншого контенту
Налаштуєте автоматичне стиснення, зміну розміру й сучасну доставку зображень у Next.js.
Зображення часто займають більшу частину розміру вебсторінки. Великі файли можуть:
уповільнювати завантаження сторінки;
збільшувати використання мобільного інтернету;
погіршувати показники продуктивності;
створювати різкі зміни макета під час завантаження.
Next.js має компонент Image, який автоматично:
змінює розмір зображення під конкретний екран;
стискає файл;
генерує сучасні формати, зокрема WebP та AVIF;
завантажує зображення із затримкою, якщо воно ще не потрібне;
додає атрибути для адаптивної доставки;
допомагає уникати зміщення вмісту, якщо відомі розміри зображення.
ImageДля оптимізації потрібно використовувати Image з пакета next/image, а не звичайний HTML-елемент <img>.
Створимо файл зображення:
public/
└── images/
└── mountain.jpgФайли з каталогу public доступні від кореня сайту. Тому зображення public/images/mountain.jpg матиме адресу /images/mountain.jpg.
Приклад сторінки:
import Image from 'next/image';
export default function HomePage() {
return (
<main>
<h1>Подорожі Україною</h1>
<Image
src="/images/mountain.jpg"
alt="Гори, вкриті лісом"
width={1200}
height={800}
/>
</main>
);
}Властивості width і height описують початкові розміри зображення. Вони не обов’язково визначають фактичний розмір на екрані, але допомагають браузеру заздалегідь зарезервувати місце.
Це запобігає зміщенню тексту та інших елементів під час завантаження зображення.
altВластивість alt описує зображення для доступності та випадків, коли файл не вдалося завантажити.
<Image
src="/images/mountain.jpg"
alt="Гори, вкриті лісом"
width={1200}
height={800}
/>Якщо зображення декоративне й не має змістовного опису, можна використати порожній alt:
<Image
src="/images/decorative-line.png"
alt=""
width={600}
height={20}
/>Для зображення, яке має займати всю ширину контейнера, можна використовувати CSS і властивість width.
import Image from 'next/image';
export default function ArticlePage() {
return (
<main>
<article>
<h1>Національні парки України</h1>
<Image
src="/images/mountain.jpg"
alt="Пейзаж національного парку"
width={1600}
height={900}
style={{
width: '100%',
height: 'auto',
}}
/>
<p>
Великі зображення можуть автоматично підлаштовуватися під ширину
контейнера.
</p>
</article>
</main>
);
}У цьому прикладі:
width={1600} і height={900} задають співвідношення сторін;
width: '100%' дозволяє зображенню зменшуватися на вузьких екранах;
height: 'auto' зберігає пропорції.
Іноді потрібно, щоб зображення повністю заповнювало блок. Для цього використовується fill.
Батьківський елемент повинен мати:
position: relative;
визначену висоту або співвідношення сторін.
import Image from 'next/image';
export default function Hero() {
return (
<section
style={{
position: 'relative',
height: '400px',
overflow: 'hidden',
}}
>
<Image
src="/images/mountain.jpg"
alt="Гірський пейзаж"
fill
sizes="100vw"
style={{
objectFit: 'cover',
}}
/>
<div
style={{
position: 'relative',
zIndex: 1,
color: 'white',
padding: '40px',
}}
>
<h1>Відкривайте Україну</h1>
</div>
</section>
);
}objectFit: 'cover' заповнює весь контейнер, але може обрізати частину зображення.
sizesКоли використовується fill або адаптивна ширина, Next.js потрібно повідомити, яку ширину зображення воно займатиме на різних екранах.
<Image
src="/images/mountain.jpg"
alt="Гірський пейзаж"
fill
sizes="(max-width: 768px) 100vw, 50vw"
style={{ objectFit: 'cover' }}
/>Цей запис означає:
на екранах до 768px зображення займає всю ширину вікна;
на більших екранах зображення займає приблизно половину ширини.
Завдяки sizes браузер може вибрати відповідний варіант зображення замість завантаження надто великого файлу.
Next.js створює кілька варіантів зображення різної ширини. Браузер вибирає варіант відповідно до:
ширини екрана;
щільності пікселів;
значення sizes;
доступної мережі.
Наприклад, для картки товару не потрібно завантажувати зображення шириною 2000 пікселів, якщо картка на екрані має ширину лише 300 пікселів.
import Image from 'next/image';
type ProductCardProps = {
name: string;
image: string;
};
export function ProductCard({ name, image }: ProductCardProps) {
return (
<article>
<Image
src={image}
alt={name}
width={400}
height={300}
sizes="(max-width: 640px) 100vw, (max-width: 1024px) 50vw, 25vw"
style={{
width: '100%',
height: 'auto',
}}
/>
<h2>{name}</h2>
</article>
);
}Next.js може автоматично доставляти зображення в сучасному форматі. Браузер отримує формат, який він підтримує, а вихідний файл залишається доступним як джерело.
У next.config.mjs можна вказати бажаний порядок форматів:
/** @type {import('next').NextConfig} */
const nextConfig = {
images: {
formats: ['image/avif', 'image/webp'],
},
};
export default nextConfig;Після зміни конфігурації потрібно перезапустити сервер розробки.
AVIF часто дає менший розмір файлу, але його кодування може потребувати більше ресурсів. WebP має широку підтримку та також добре стискає зображення.
Використання Image не означає, що потрібно вручну створювати окремі WebP- або AVIF-файли для кожного зображення.
Для локальних зображень достатньо вказати шлях, що починається з /.
Для віддалених зображень Next.js потрібно явно дозволити домен у конфігурації. Наприклад:
/** @type {import('next').NextConfig} */
const nextConfig = {
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 'images.example.com',
pathname: '/photos/**',
},
],
},
};
export default nextConfig;Після цього віддалене зображення можна використати так:
import Image from 'next/image';
export default function Profile() {
return (
<Image
src="https://images.example.com/photos/avatar.jpg"
alt="Фото профілю"
width={160}
height={160}
/>
);
}Важливо вказувати конкретні дозволені домени та шляхи. Не варто дозволяти будь-який домен без потреби.
<img>У більшості випадків у Next.js варто використовувати Image. Звичайний <img> не отримує автоматичної оптимізації Next.js.
Компонент Image особливо корисний для:
фотографій;
зображень товарів;
обкладинок статей;
банерів;
великих ілюстрацій.
Маленькі декоративні зображення або спеціальні випадки можуть не потребувати оптимізації, але це має бути свідоме рішення.
Нижче наведено мінімальний приклад сторінки для App Router. Він працює за умови, що файл public/images/mountain.jpg існує.
import Image from 'next/image';
export default function HomePage() {
return (
<main
style={{
maxWidth: '900px',
margin: '0 auto',
padding: '24px',
}}
>
<h1>Гірський маршрут</h1>
<Image
src="/images/mountain.jpg"
alt="Гори на тлі блакитного неба"
width={1600}
height={1000}
sizes="(max-width: 900px) 100vw, 900px"
style={{
width: '100%',
height: 'auto',
borderRadius: '12px',
}}
/>
<p>
Компонент Image автоматично підбирає відповідний розмір і формат
зображення для пристрою користувача.
</p>
</main>
);
}Для файлу public/images/logo.png правильний шлях:
<Image src="/images/logo.png" alt="Логотип" width={200} height={60} />Не потрібно писати /public у шляху:
// Неправильно
<Image src="/public/images/logo.png" alt="Логотип" width={200} height={60} />Для звичайного зображення потрібно вказати width і height або використати fill.
// Правильно
<Image
src="/images/logo.png"
alt="Логотип"
width={200}
height={60}
/>fill без розмірів батьківського елементаЯкщо контейнер не має висоти, зображення може не відображатися очікуваним чином.
// Батьківський контейнер має позицію та висоту
<div style={{ position: 'relative', height: '300px' }}>
<Image
src="/images/mountain.jpg"
alt="Гірський пейзаж"
fill
sizes="100vw"
style={{ objectFit: 'cover' }}
/>
</div>sizesБез sizes браузер може отримати більший файл, ніж потрібно. Для адаптивного зображення із fill бажано вказувати це значення явно.
alt для декоративного зображенняНе потрібно описувати декоративну лінію, фон або інший елемент, який не додає змісту сторінці. Для таких зображень використовуйте alt="".
Для оптимізації зображень у Next.js використовуйте Image з next/image.
Локальні файли зберігайте в каталозі public і звертайтеся до них без /public у шляху.
Для звичайних зображень задавайте width і height.
Для зображення, яке заповнює контейнер, використовуйте fill.
Разом із fill або адаптивним зображенням вказуйте sizes.
Next.js автоматично змінює розмір, стискає та доставляє сучасні формати зображень.
Для віддалених зображень спочатку дозвольте потрібний домен у remotePatterns.
Завжди додавайте коректний alt, щоб зображення були доступними.