Пошук уроків, статей та іншого контенту
Створите зображення, які коректно адаптуються до ширини контейнера та різних пристроїв.
Адаптивне зображення змінює свій розмір відповідно до ширини контейнера або екрана пристрою.
На великому екрані воно може бути широким, а на смартфоні — займати всю доступну ширину, не виходячи за межі сторінки.
У Next.js для зображень використовується компонент Image:
оптимізує розмір зображення;
завантажує відповідний варіант для пристрою;
допомагає уникати зміщення вмісту сторінки;
підтримує адаптивне масштабування.
Створіть папку public/images у корені проєкту та додайте до неї файл:
public/
└── images/
└── landscape.jpgФайли з папки public доступні від кореня сайту. Тому це зображення матиме шлях:
/images/landscape.jpgДля адаптивного зображення зазвичай вказують його початкові width і height, а через CSS дозволяють займати всю ширину контейнера.
app/page.tsximport Image from "next/image";
export default function HomePage() {
return (
<main className="page">
<article className="card">
<Image
src="/images/landscape.jpg"
alt="Гірський пейзаж"
width={1200}
height={800}
sizes="100vw"
className="responsive-image"
/>
<h1>Подорож у гори</h1>
<p>
Це зображення адаптується до ширини батьківського контейнера.
</p>
</article>
</main>
);
}app/globals.css* {
box-sizing: border-box;
}
body {
margin: 0;
font-family: Arial, sans-serif;
background: #f3f4f6;
}
.page {
width: min(100% - 32px, 900px);
margin: 32px auto;
}
.card {
overflow: hidden;
border-radius: 16px;
background: white;
box-shadow: 0 8px 24px rgb(0 0 0 / 10%);
}
.responsive-image {
display: block;
width: 100%;
height: auto;
}
.card h1,
.card p {
margin-right: 24px;
margin-left: 24px;
}
.card h1 {
margin-top: 24px;
}
.card p {
padding-bottom: 24px;
color: #4b5563;
}Властивість width: 100% розтягує зображення до ширини контейнера, а height: auto зберігає його пропорції.
Атрибути width і height у Image описують початкові пропорції зображення. Вони не забороняють зображенню ставати меншим на вузькому екрані.
sizesАтрибут sizes повідомляє браузеру, яку ширину зображення воно матиме на різних екранах.
У попередньому прикладі:
sizes="100vw"означає, що зображення може займати всю ширину вікна браузера.
Якщо зображення розташоване в контейнері, який має максимальну ширину, краще описати це точніше:
<Image
src="/images/landscape.jpg"
alt="Гірський пейзаж"
width={1200}
height={800}
sizes="(max-width: 932px) 100vw, 900px"
className="responsive-image"
/>Це означає:
на екранах шириною до 932px зображення займає всю ширину вікна;
на ширших екранах воно займає не більше 900px.
Точний sizes допомагає браузеру вибрати відповідний файл і не завантажувати надто велике зображення.
Інший варіант — зображення повністю заповнює блок заданого розміру. Для цього використовують fill.
import Image from "next/image";
export default function HomePage() {
return (
<main className="page">
<section className="hero">
<Image
src="/images/landscape.jpg"
alt="Гірський пейзаж на заході сонця"
fill
sizes="(max-width: 768px) 100vw, 900px"
className="hero-image"
/>
<div className="hero-content">
<h1>Відкривайте нові місця</h1>
<p>Плануйте наступну подорож разом із нами.</p>
</div>
</section>
</main>
);
}.page {
width: min(100% - 32px, 900px);
margin: 32px auto;
}
.hero {
position: relative;
min-height: 420px;
overflow: hidden;
border-radius: 16px;
}
.hero-image {
object-fit: cover;
}
.hero-content {
position: absolute;
right: 24px;
bottom: 24px;
left: 24px;
color: white;
text-shadow: 0 2px 8px rgb(0 0 0 / 80%);
}fillКоли використовується fill:
компонент Image заповнює весь батьківський елемент;
батьківський елемент повинен мати position: relative;
контейнер повинен мати висоту або мінімальну висоту;
object-fit: cover заповнює контейнер, зберігаючи пропорції зображення.
Якщо пропорції контейнера та зображення різні, частина зображення може бути обрізана. Це нормальна поведінка для object-fit: cover.
object-fit: containІноді обрізати зображення не можна. Наприклад, це стосується товару, документа або логотипа.
У такому разі можна використати contain:
<Image
src="/images/landscape.jpg"
alt="Зображення товару"
fill
sizes="100vw"
className="contain-image"
/>.contain-image {
object-fit: contain;
background: #e5e7eb;
}contain показує все зображення, але навколо нього можуть з’явитися вільні області.
Ось повний приклад картки, у якій зображення змінює ширину разом із карткою.
app/page.tsximport Image from "next/image";
const articles = [
{
title: "Морська подорож",
description: "Ідеї для літнього відпочинку біля моря.",
image: "/images/landscape.jpg",
},
{
title: "Гірський маршрут",
description: "Підготуйтеся до подорожі в гори.",
image: "/images/landscape.jpg",
},
];
export default function HomePage() {
return (
<main className="page">
<h1>Популярні маршрути</h1>
<section className="cards">
{articles.map((article) => (
<article className="card" key={article.title}>
<Image
src={article.image}
alt={article.title}
width={800}
height={500}
sizes="(max-width: 700px) 100vw, 50vw"
className="card-image"
/>
<div className="card-content">
<h2>{article.title}</h2>
<p>{article.description}</p>
</div>
</article>
))}
</section>
</main>
);
}app/globals.css* {
box-sizing: border-box;
}
body {
margin: 0;
font-family: Arial, sans-serif;
background: #f3f4f6;
}
.page {
width: min(100% - 32px, 1000px);
margin: 32px auto;
}
.cards {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 24px;
}
.card {
overflow: hidden;
border-radius: 16px;
background: white;
box-shadow: 0 8px 24px rgb(0 0 0 / 10%);
}
.card-image {
display: block;
width: 100%;
height: auto;
}
.card-content {
padding: 20px;
}
.card-content h2 {
margin: 0 0 8px;
}
.card-content p {
margin: 0;
color: #4b5563;
}
@media (max-width: 700px) {
.cards {
grid-template-columns: 1fr;
}
}На широкому екрані картки розташовані у два стовпці. На вузькому екрані кожна картка займає весь доступний простір, а її зображення зменшується разом із карткою.
Використовуйте звичайний варіант із width і height, якщо:
зображення має зберегти свою пропорцію;
воно розташоване у звичайному потоці сторінки;
висота повинна автоматично змінюватися разом із шириною.
Використовуйте fill, якщо:
зображення має бути фоном або обкладинкою блоку;
контейнер має фіксовану або мінімальну висоту;
поверх зображення потрібно розташувати текст чи інші елементи.
altПогано:
<Image
src="/images/landscape.jpg"
width={1200}
height={800}
/>Краще:
<Image
src="/images/landscape.jpg"
alt="Гірський пейзаж"
width={1200}
height={800}
/>alt описує зображення для користувачів, які використовують скринрідер. Якщо зображення декоративне, можна використати порожній опис:
<Image
src="/images/landscape.jpg"
alt=""
width={1200}
height={800}
/>fill без розміру батьківського елементаПогано:
<div>
<Image
src="/images/landscape.jpg"
alt="Пейзаж"
fill
/>
</div>Батьківський елемент не має позиціонування та висоти. Через це зображення може не відображатися очікуваним чином.
Правильно:
<div className="image-container">
<Image
src="/images/landscape.jpg"
alt="Пейзаж"
fill
sizes="100vw"
/>
</div>.image-container {
position: relative;
height: 320px;
}Якщо використовується звичайний HTML-елемент img або власні стилі, перевірте, що ширина не перевищує контейнер:
img {
max-width: 100%;
height: auto;
}Для Image також часто використовують:
.responsive-image {
display: block;
width: 100%;
height: auto;
}object-fitobject-fit: cover може обрізати краї зображення. Якщо потрібно показати зображення повністю, використовуйте:
.image {
object-fit: contain;
}Перевірте сторінку на різних ширинах:
Відкрийте сторінку у браузері.
Увімкніть інструменти розробника.
Перемикайте ширину viewport між мобільним і настільним розмірами.
Переконайтеся, що зображення:
не виходить за межі контейнера;
зберігає пропорції;
не перекриває текст;
коректно заповнює контейнер у режимі fill.
Компонент Image з пакета next/image призначений для роботи із зображеннями в Next.js.
Для звичайного адаптивного зображення використовуйте width, height і CSS width: 100%.
Атрибут sizes описує ширину зображення на різних екранах.
fill змушує зображення заповнити батьківський контейнер.
Для fill батьківський елемент повинен мати position: relative і визначену висоту.
object-fit: cover заповнює контейнер із можливим обрізанням.
object-fit: contain показує зображення повністю.
Завжди додавайте зрозумілий атрибут alt.