Під час аудиту сайту одного нашого клієнта, виробника меблів з Вінниці, Lighthouse показав незрозумілий рядок: “No <picture> elements anywhere on page (0 found)”. Клієнт запитав, це взагалі критично? Ми перевірили зображення на сторінці: головне фото вагою 340 KB у форматі JPEG. LCP, 5.8 секунди. PageSpeed, 41/100 на мобільному. Якби це зображення подавалось у форматі AVIF через `<picture>`, воно важило б 80 KB, а LCP впав би до 2 секунд.
Це не рідкісна ситуація. Це стандартна поведінка WordPress.
WordPress вміє генерувати адаптивні зображення через srcset з 2015 року, а WebP, з 2022. Але <picture>, HTML-елемент, який дозволяє браузеру вибирати між форматами, досі не з’явився в ядрі. І це конкретна втрата: важчі файли, повільніший LCP, гірші позиції там, де конкурент з ідентичним контентом оптимізував зображення правильно.
У цій статті розберемо, в чому різниця між srcset і <picture>, чому WordPress досі не перейшов на <picture>, що ви втрачаєте без нього, і як виправити це без злому ядра, кількома рядками PHP або плагіном.
srcset і <picture>: в чому принципова різниця
На перший погляд обидва підходи вирішують одну задачу: показати правильне зображення на правильному пристрої. Але вирішують вони різні аспекти цієї задачі.
srcset, атрибут тегу <img>, який дає браузеру список варіантів одного зображення різних розмірів:
<img src="photo-800w.jpg"
srcset="photo-400w.jpg 400w, photo-800w.jpg 800w, photo-1200w.jpg 1200w"
sizes="(max-width: 600px) 400px, 800px"
alt="Опис зображення">
Браузер вибирає розмір залежно від ширини екрану і щільності пікселів, і завантажує відповідний файл. Але є обмеження: браузер вибирає між варіантами одного формату. Якщо в srcset тільки JPEG, він завантажить JPEG, незалежно від того, чи підтримує цей браузер WebP або AVIF.
<picture>, контейнер, який дозволяє задати кілька форматів з умовами вибору:
<picture>
<source srcset="photo.avif" type="image/avif">
<source srcset="photo.webp" type="image/webp">
<img src="photo.jpg" alt="Опис зображення">
</picture>
Логіка проста: браузер перевіряє <source> зверху вниз. Підтримує AVIF, завантажує AVIF. Ні, перевіряє WebP. Ні, бере як fallback. Тег <img src>
<img> завжди залишається і завжди є fallback для старих браузерів.
Коротко: srcset вирішує питання розміру, <picture> вирішує питання формату (і може вирішувати обидва одночасно). Детальна специфікація елемента доступна на MDN Web Docs.
Art direction: різні кадри для різних екранів
<picture> вирішує ще одну задачу, яку srcset не може, art direction. Це коли на мобільному і десктопі показується різне зображення, а не просто менший варіант того самого:
<picture>
<source media="(max-width: 767px)" srcset="hero-mobile.webp" type="image/webp">
<source media="(max-width: 767px)" srcset="hero-mobile.jpg">
<source media="(min-width: 768px)" srcset="hero-desktop.webp" type="image/webp">
<img src="hero-desktop.jpg" alt="Головна сторінка">
</picture>
Практичний приклад: на десктопі, широкий пейзажний кадр офісу. На мобільному, портретне фото з обличчям по центру. Без art direction браузер просто стискає десктопний варіант, і на маленькому екрані деталі губляться.
Чому WordPress досі не використовує <picture>
WordPress додав підтримку srcset у версії 4.4 (грудень 2015). Генерацію WebP при завантаженні, у 6.1 (листопад 2022). Але <picture> в ядрі досі немає. Причини реальні.
Зворотна сумісність. Мільйони тем і плагінів стилізують напряму через CSS-селектори типу .content img, figure img, article img. Якщо WordPress раптово почне обгортати кожен img у <picture>, частина цих стилів перестане працювати. Selectors перестануть збігатися. Layouts поламаються. Це ризик, на який ядро не готове без довгого перехідного періоду.
Складність генерації файлів. <picture> з кількома форматами вимагає, щоб на сервері існували JPEG, WebP і AVIF версії кожного зображення. WordPress вже генерує кілька розмірів при завантаженні, додати ще кілька форматів означає суттєво збільшити навантаження на CPU і дисковий простір при кожному upload.
AVIF нерівномірний. Хоча більшість сучасних браузерів підтримують AVIF, час декодування на старих або слабких пристроях може бути гіршим ніж WebP. WordPress ядро консервативне в таких рішеннях.
Результат: WordPress генерує WebP (якщо сервер підтримує GD або Imagick з WebP), але обгортає зображення тільки у <img> з srcset. Браузер отримує набір розмірів одного формату, і ніколи не дізнається, що є WebP або AVIF версія, бо їх ніхто не пропонує.
Добра новина: це виправляється без змін у ядрі, через хуки або плагіни.
Що ви втрачаєте без адаптивних зображень у сучасних форматах
Перейдемо до цифр, щоб зрозуміти реальний масштаб проблеми.
Різниця у вазі файлів
Типове фото 1200×800px у різних форматах:
- JPEG (якість 80%): 180–230 KB
- WebP: 80–120 KB
- AVIF: 45–75 KB
Різниця між JPEG і AVIF, в 3–4 рази. Якщо на сторінці 6–8 зображень, це 600–900 KB зайвого трафіку для кожного відвідувача з браузером, що підтримує AVIF, Chrome, Firefox, Safari 16+. А це більше 90% вашої аудиторії вже сьогодні — перевірити підтримку конкретних браузерів можна на caniuse.com.
Важливий нюанс: AVIF підтримується у браузерах, але не кожен сервер вміє його генерувати. PHP-функція imageavif() з’явилась у PHP 8.1 і вимагає libavif. Якщо ваш хостинг на PHP 7.x або старому GD — AVIF недоступний без плагіна. У такому випадку WebP вже дає суттєву перевагу порівняно з JPEG: зменшення ваги на 25–35% без втрати якості.
Вплив на LCP і ранжування
LCP (Largest Contentful Paint), у більшості випадків це завантаження головного зображення сторінки. Hero-блок, featured image, продуктова фотографія. Якщо воно важить 230 KB замість 65 KB, різниця у часі завантаження на 4G мобільному може становити 2–3 секунди.
Google використовує Core Web Vitals як сигнал ранжування. Пороговий LCP для “доброго” результату, 2.5 секунди. Сайти з LCP 5+ секунд конкурують з суттєвою невигодою навіть при однаковій якості контенту. Детально про те, що означають ці метрики для вашого бізнесу, у нашій статті про Core Web Vitals.
Іванна запустила інтернет-магазин одягу на WordPress у 2024 році. Фотографії товарів, в середньому 280 KB у JPEG, бо фотограф здавав файли “як є”. PageSpeed на мобільному, 47. Після масової конвертації в WebP і AVIF через Imagify і додавання <picture> через плагін: середня вага фото впала до 72 KB, LCP, з 6.1 до 2.4 секунди, PageSpeed, з 47 до 79. За два місяці органічний трафік виріс на 28%, а bounce rate на мобільному знизився з 74% до 51%.
Мобільний трафік і ліміти даних
В Україні мобільний трафік складає 55–65% для більшості сайтів. Мобільні користувачі, особливо ті, хто дбає про витрати трафіку, відчувають різницю між сайтом, що завантажує 1.5 MB зображень, і сайтом з 400 KB. Частина просто закриє вкладку.
Адаптивні зображення WordPress у форматі AVIF через <picture> — це не тільки про SEO. Це про те, скільки мегабайт мобільного трафіку ваш сайт “з’їдає” у кожного відвідувача. Для ecommerce-сайтів з десятками фото на сторінці каталогу різниця між JPEG і AVIF — це різниця між 3 MB і 700 KB на один перегляд.
Які зображення оптимізувати першими
Не всі зображення однаково впливають на швидкість. Якщо ресурси обмежені, оптимізуйте в такому порядку:
- Hero-зображення і featured images — зазвичай найважчі і найчастіше є LCP-елементом. Пріоритет максимальний.
- Зображення вище fold — все, що видно без прокрутки. Завантажуються першими і безпосередньо впливають на FCP і LCP.
- Зображення в картках товарів або постів — особливо на сторінках категорій з 20+ зображеннями.
- Зображення нижче fold — менш критичні для Core Web Vitals, але все одно впливають на загальний розмір сторінки.
Адаптивні зображення з підтримкою сучасних форматів мають найбільший ефект саме для перших двох груп. Плагіни типу Imagify застосовують конвертацію до всіх зображень одразу — це зручно, але якщо починаєте з PHP-хука, вручну розставте пріоритети.
Як виправити: <picture> на WordPress
Є два шляхи, PHP-хук для точного контролю або плагін для швидкого старту.
Спосіб 1: PHP-хук (без плагінів)
З WordPress 6.0 є фільтр wp_content_img_tag, він перехоплює кожен в контенті перед рендерингом. Додайте у functions.php вашої теми або в mu-plugin:
add_filter( 'wp_content_img_tag', function( $filtered_image, $context, $attachment_id ) {
if (! $attachment_id ) {
return $filtered_image;
}
$upload_dir = wp_upload_dir();
$src = wp_get_attachment_url( $attachment_id );
$path = str_replace( $upload_dir['baseurl'], $upload_dir['basedir'], $src );
$avif_path = preg_replace( '/\.(jpe?g|png)$/i', '.avif', $path );
$webp_path = preg_replace( '/\.(jpe?g|png)$/i', '.webp', $path );
$avif_url = file_exists( $avif_path ) ? str_replace( $upload_dir['basedir'], $upload_dir['baseurl'], $avif_path ): null;
$webp_url = file_exists( $webp_path ) ? str_replace( $upload_dir['basedir'], $upload_dir['baseurl'], $webp_path ): null;
if (! $avif_url && ! $webp_url ) {
return $filtered_image;
}
$sources = '';
if ( $avif_url ) {
$sources .= sprintf( '<source srcset="%s" type="image/avif">', esc_url( $avif_url ) );
}
if ( $webp_url ) {
$sources .= sprintf( '<source srcset="%s" type="image/webp">', esc_url( $webp_url ) );
}
return sprintf( '<picture>%s%s</picture>', $sources, $filtered_image );
}, 10, 3 );
Логіка проста: якщо поруч з оригінальним файлом є .avif або .webp версія, обгортаємо в <picture> з відповідними <source>. Якщо немає, повертаємо <img> без змін. Fallback завжди є.
Генерація WebP і AVIF при завантаженні
Щоб хук мав що обгортати, потрібні WebP і AVIF файли. WordPress 6.1+ генерує WebP автоматично при наявності відповідної підтримки у GD або Imagick. Для AVIF, потрібен Imagick 7+ з підтримкою libavif. Додайте у functions.php:
add_filter( 'wp_upload_image_mime_transforms', function( $transforms ) {
foreach ( $transforms as &$mime_transforms ) {
$mime_transforms[] = [
'output_format' => 'image/avif',
'quality' => 75,
];
}
return $transforms;
} );
Важливо: генерація AVIF CPU-інтенсивна. На слабкому хостингу завантаження великих зображень може займати кілька секунд. Якщо ваш хостинг не справляється, розгляньте варіанти: або зовнішній сервіс оптимізації, або перехід на кращий сервер. Що враховувати при виборі WordPress-хостингу, розглядаємо окремо.
Спосіб 2: Плагін
Якщо PHP, не ваша зона, є плагіни:
- Imagify, конвертує в WebP і AVIF, є опція “Use
<picture>tag”. Безкоштовний ліміт 20 MB на місяць, потім від $4.99/міс. - ShortPixel, аналогічний функціонал, безкоштовно 100 зображень на місяць.
- Optimole, хмарна оптимізація і CDN, автоматично подає правильний формат через свій проксі.
Плагіни зручні для швидкого старту, але мають обмеження безкоштовних тарифів. Для великих бібліотек медіа, рахуйте вартість заздалегідь.
Art direction для hero-блоків
Для головних зображень, де кадрування важливе, використовуйте функцію-хелпер:
function smtv_picture( $desktop_id, $mobile_id, $alt = '', $class = '' ) {
$desktop_url = wp_get_attachment_url( $desktop_id );
$mobile_url = wp_get_attachment_url( $mobile_id );
return sprintf(
'<picture class="%s">
<source media="(max-width: 767px)" srcset="%s" type="image/webp">
<source media="(max-width: 767px)" srcset="%s">
<img src="%s" alt="%s" loading="lazy" decoding="async">
</picture>',
esc_attr( $class ),
esc_url( preg_replace( '/\.(jpe?g|png)$/i', '.webp', $mobile_url ) ),
esc_url( $mobile_url ),
esc_url( $desktop_url ),
esc_attr( $alt )
);
}
Викликайте у шаблоні теми, передаючи ID десктопного і мобільного зображення окремо.
Підводні камені при впровадженні
Кілька речей, які варто перевірити після додавання <picture>.
CSS-стилі. Якщо тема стилізує article img { max-width: 100%; }, після обгортання в <picture> стилі залишаться на <img>, все буде добре. Але якщо є селектор article > img (прямий нащадок), він перестане збігатися, бо тепер між article і img стоїть picture. Перевірте стилі теми.
Lazy loading. Атрибут loading="lazy" треба ставити на <img> всередині <picture>, не на <source>. WordPress автоматично додає loading="lazy" до <img>, переконайтесь, що він зберігається після обгортання хуком.
Кешування. Після змін обов’язково очистіть кеш (WP Rocket, LiteSpeed Cache, або серверний кеш) і перевірте кілька сторінок, що кешовані версії теж показують <picture>.
Перевірка в DevTools. Network → Images, перевірте, що тип файлів у колонці Type показує image/avif або image/webp, а не image/jpeg. Якщо все ще JPEG, або файли не згенеровані, або хук не спрацьовує.
fetchpriority для LCP-зображення. Якщо головне зображення сторінки (hero) є LCP-елементом, додайте fetchpriority="high" до тегу <img> всередині <picture>. Це підказує браузеру завантажити його першочергово, ще до завершення парсингу DOM. Без цього атрибута браузер може відкласти завантаження hero-зображення на кілька сотень мілісекунд, навіть якщо воно знаходиться вгорі сторінки.
Результати: що очікувати
За нашим досвідом оптимізації WordPress-сайтів після впровадження <picture> з WebP/AVIF:
- Середня вага зображень знижується на 40–65%
- LCP покращується на 1.5–3.5 секунди (залежно від початкового стану і ваги hero-зображення)
- PageSpeed Insights перестає показувати попередження “Serve images in next-gen formats”
- Мобільний bounce rate знижується на 10–25% (при умові, що зображення були основним гальмом)
Варто розуміти, що адаптивні зображення WordPress — це не срібна куля. Якщо LCP-елемент — це текст або кнопка, а не зображення, ефект буде мінімальним. Але якщо основна гальмівна точка — саме завантаження зображень (що трапляється у 70–80% сайтів на WordPress з нативними темами), <picture> з AVIF/WebP — це найшвидший шлях до помітного результату.
Це один з найефективніших кроків технічної оптимізації з точки зору співвідношення зусиль до результату. Про інші причини повільного WordPress-сайту і як їх виправити, читайте у нашому матеріалі про швидкість WordPress.
Висновок
WordPress застряг між 2015 роком (srcset) і можливостями сучасних браузерів (AVIF, art direction). <picture> закриває цей розрив: браузер отримує вибір формату і завантажує зображення в 3–4 рази менше за розміром без видимої різниці у якості.
Для бізнесу, це конкретні числа: швидший LCP, краще ранжування в Google, менше відмов на мобільному. Для розробника, кілька годин роботи: налаштування генерації WebP/AVIF і один PHP-хук або плагін.
Якщо хочете перевірити стан зображень на вашому сайті або впровадити <picture> як частину технічної SEO-оптимізації, зв’яжіться з нами. Розберемо конкретно, що гальмує ваш сайт і що дасть найбільший ефект першим кроком.