Перейти к содержимому
Изображения и медиа

Почему WordPress портит фото при загрузке и как это исправить

В девяти случаях из десяти изображения на самом деле не размытые — WordPress уменьшил их при загрузке и теперь отдаёт урезанную копию. Начиная с WordPress 5.3 любое

Опубликовано

В девяти случаях из десяти изображения на самом деле не размытые — WordPress уменьшил их при загрузке и теперь отдаёт урезанную копию. Начиная с WordPress 5.3 любое изображение шире или выше 2560px без предупреждения заменяется версией -scaled с ограничением 2560px по длинной стороне, и именно этот уменьшенный файл ваш шаблон растягивает под hero-блок, полноширинный блок или retina-дисплей. Чтобы исправить это, нужно сначала доказать, что произошло именно это, а затем либо поднять порог, либо перестать загружать изображения, которые должны быть крупнее контейнера, в котором они находятся.

Почему так происходит

Когда вы загружаете фотографию, WordPress запускает wp_create_image_subsizes()wp-admin/includes/image.php). Если длинная сторона превышает big_image_size_threshold — по умолчанию 2560px — вызывается _wp_image_meta_replace_original(), создаётся your-photo-scaled.jpg, а метаданные вложения переписываются так, что размер full теперь указывает на уменьшенную копию. Ваш настоящий оригинал остаётся на диске как your-photo.jpg и доступен через wp_get_original_image_path(), но на фронтенде его никто не отдаёт. Каждый промежуточный размер и каждый кандидат в srcset генерируется из уменьшенного файла 2560px, а не из того, что вы загрузили.

Вот откуда берётся размытие. Вы загружаете чёткое изображение 4000px для полноэкранной шапки. WordPress ограничивает его до 2560px. На обычном дисплее в контейнере шириной 1600px всё нормально. Но на 2x retina-экране браузеру нужно примерно 3200 реальных пикселей, чтобы чётко заполнить этот контейнер, а есть только 2560 — недостающее он дорисовывает апскейлом. Мягкие края, «мыльный» текст на изображении — ровно тот симптом «размытости после загрузки».

Вторая половина той же проблемы — srcset выбирает слишком маленький размер. Если ваш шаблон сообщает ширину контента, которая не совпадает с реально отрисованным контейнером, WordPress отдаёт браузеру промежуточный -1024x683 или -1536x1024, и он растягивается. Причина та же — контейнер больше, чем доступное количество пикселей — только триггер другой.

Проверьте, что WordPress отдал на самом деле

Не гадайте. Кликните по размытому изображению правой кнопкой, откройте его в новой вкладке и посмотрите на имя файла в URL. Если оно заканчивается на -scaled.jpg или суффиксом с размерами вроде -1024x683.jpg, то всё подтвердилось: браузер отрисовывает уменьшенную производную, а не вашу загрузку. Можно также открыть инспектор элемента и прочитать currentSrc, чтобы точно увидеть, какого кандидата выбрал браузер.

Чтобы увидеть всю картину до того, как что-либо перезагружать, закиньте изображение в инструмент размеров изображений WordPress — он покажет каждую производную, которую WordPress сгенерирует из этого конкретного файла, включая то, создаётся ли копия -scaled и с какими размерами. Так вы заранее узнаете, достаточно ли крупный ваш исходник для того места, куда вы его ставите.

На сервере можно вывести список всех урезанных файлов:

find wp-content/uploads -name '*-scaled.*'

Как это исправить, по порядку

1. Если ваши изображения действительно должны быть крупнее 2560px (большие hero-блоки, retina, галереи полиграфического качества), поднимите порог:

// functions.php or a small mu-plugin
add_filter( 'big_image_size_threshold', function () {
    return 3840; // longest edge, in pixels
} );

Или полностью отключите ограничение:

add_filter( 'big_image_size_threshold', '__return_false' );

2. Перезагрузите проблемные изображения. Этот шаг обычно пропускают. Изменение порога влияет только на новые загрузки. У изображений, уже находящихся в медиатеке, остаются старые метаданные, а пересоздание миниатюр перестраивает промежуточные размеры из урезанного файла -scaled — оно не возвращает выброшенное разрешение обратно. Надёжный путь такой: измените фильтр, удалите вложение, загрузите заново.

3. Если ваш исходник уже ≤2560px, но по-прежнему размытый, дело не в пороге — контейнер больше самого изображения. Загрузите более крупный исходник или уменьшите контейнер. Для retina-чёткости исходник должен быть примерно вдвое шире контейнера в CSS-пикселях.

4. Только после всего вышеперечисленного пересоздайте миниатюры, чтобы промежуточные размеры были согласованы — но помните, что это уборка, а не лечение.

Чего делать не стоит

Не выкручивайте качество JPEG на 100. WordPress сжимает до качества по умолчанию 82 через wp_editor_set_quality, и половина советов в интернете предлагает это переопределить:

add_filter( 'wp_editor_set_quality', function () { return 90; } );

Это нормально для уменьшения артефактов сжатия, но растянутое, апскейленное изображение — это проблема разрешения, а не сжатия. Переход с 82 на 100 раздувает файлы и почти ничего не делает с той мягкостью, которую вы видите.

Не отключайте -scaled рефлекторно. Отключение ограничения (для этого есть инструмент) — правильное решение, если вы отдаёте изображения выше 2560px. Но если ваша настоящая проблема — растягивание слишком маленького промежуточного размера, отключение ничего не изменит, а вы без причины потеряете экономию трафика. Сначала диагностика.

Не сваливайте вину на кеш и не пересоздавайте миниатюры первым делом. Пересоздание читает из того же урезанного исходника, поэтому не может восстановить детали. Очистка CDN или кеша страниц не тронет файл, который изначально был маленьким на диске.

Не хватайтесь за CSS шаблона или object-fit. Никакая стилизация не добавит пикселей. Если отданный файл заканчивается на -scaled или суффикс с размерами, проблема в файле, а не в вёрстке.

Всё ещё не получается?

Если вы убедились, что отданный файл — это ваша полноразмерная загрузка (без -scaled, без суффикса с размерами), а он всё равно мягкий, проверьте, не переписывает ли какой-нибудь плагин ваш src на сжатый прокси (оптимизатор, CDN с ресайзом изображений или библиотека ленивой загрузки). Прогоните изображение через инструмент размеров изображений, чтобы подтвердить, что WordPress должен генерировать, а затем сравните это с тем, что браузер реально загружает. Когда эти два не совпадают, виновник — что-то между WordPress и браузером.