Comments 71
Я недавно попробовал avif. Экспортировал из последнего GIMP. При уровнях качества около 80-90% изображение содержало заметные артифакты по сравнению с jpeg, а галочка lossless выдала картинку, чей объем на диске чудовищно превосходил исходник в jpeg.
Может, стоило попробовать конвертировать из PNG (оригинал) в JPEG и AVIF, и уже такие результаты сравнивать? Ведь JPEG -> AVIF предсказуемо наложит только новые артефакты на уже имеющиеся в JPEG. А размер lossless сравнивать тоже с PNG оригиналом, поскольку качества пиксель-в-пиксель в JPEG нет именно из-за размеров.
В WordPress это решается плагином, а совать поддержку всевозможных форматов, которые то появляются, то пропадают, в ядро — ядро лопнет.
Ну или же, при боязне плагинов — есть хук из пары строк для добавления поддержки любого нового формата.
mime_types
и upload_mimes
, например так:function mihdan_edit_upload_types( $existing_mimes = array() ) {
// allow .woff
$existing_mimes['woff'] = 'font/woff';
// disallow .jpg files
unset( $existing_mimes['jpg'] );
return $existing_mimes;
}
add_filter( 'upload_mimes', 'mihdan_edit_upload_types' );
Тут подробней
Вот когда они начнут из коробки понимать WEBP, AVIF, HEIF…
Боюсь никогда, для генерирования этого (а WP из коробки как минимум нарезает миниатюры) всего надо в php добавлять библиотеки, и далеко не каждый хостер этим вообще будет заниматься.
Никаким образом не затрудняет. Через html-элемент picture можно указывать ссылки на разные типы картинок. Браузер определяет, есть ли поддержка webp и качает картинку нужного типа. Вот пример, где я так сделал.
Спасибо за статью. До этого использовал либу, чтобы инициализировать lazy загрузку. А оказывается все уже и без нее работает))
"Cumulative Layout Shift (CLS)" — спасибо, теперь буду знать, что у этого супер-бесячего эффекта есть название.
<img src="..." />
А как надо изменить? Чтобы это было управляемо разработчиками? Чтобы это приносило больше пользы чем проблем?
Lazy loading для своей работы требует height и width. Если их не будет, то будет происходить пересчет layout'а слишком часто, а это вызывает проблемы с позиционированием в других местах. А брать эти значения из самого изображения нельзя без загрузки самого изображения, то есть руками все же надо указывать метаинформацию.
Но это все ещё не решает проблему с объемом изображения, который сейчас решается через srcset.
А что вам надо подстраивать в lazy loading стандартном?
Ps, если включить lazy load по умолчанию тогда поломается светлое механизм пикселей аналитики. Так что в ближайшие несколько десятков лет включать это поведение по умолчанию будет просто невыгодно самим браузерам.
Размытая заглушка
Зачем в svg прятать png? Почему просто png туда не замостить?
ехал data через data… видит data в реке data
У меня другой вопрос. Зачем их инлайново вставлять?
И еще возможно лучше вместо png использовать собственно svg для создания цветных пятен, которые необходимо размыть. Или так будет хуже размытие и общий вид заглушки?
А зачем не-инлайново их вставлять?
Интересно сколько десятилетий нужно web-у чтобы сделать <img/>
или <picture/>
действительно адаптивным. А не то что есть сейчас. Сейчас все эти srcset
-ы скачут от размера окна, что само по себе весьма бредовая идея, т.к. она предполагает что вы, размещая картинку, всегда в деталях знаете её точный размер и размер окна. Я даже не знаю где это за пределами блогов\лендингов нужно.
В то время как очевидно, что вот такое вот решение:
<picture aspectratio="1/2">
<sоurce src="..." width="1000"/>
<sоurce src="..." width="700"/>
<sоurce src="..." width="200"/>
</picture>
Решило бы 99% всех задач гораздо лучше. У браузера итак есть всё что нужно:
- он знает pixel density
- он знает размер
<img/>
- он знает пропускную способность сети
А мы в свою очередь можем предоставить ему недостающее:
- список файлов и их размеры
- aspect ratio (одинаковый для всех файлов)
А все эти полумеры с srcset
, sizes
это прямо какой-то детский сад с очень ограниченным применением (мне пока ни разу не пригодилось, т.к. не было высеченных в скале layout-ов).
Было бы гораздо проще если бы браузер использовал width и height, как пропорции и сам закладывал высоту блока пропорционально, и учитывая max-width: 100% для img
В то время как очевидно, что вот такое вот решение:
<picture aspectratio="1/2"> <sоurce src="..." width="1000"/> <sоurce src="..." width="700"/> <sоurce src="..." width="200"/> </picture>
Решило бы 99% всех задач гораздо лучше.
Так оно вроде так и работает
<picture>
<source srcset="mdn-logo-wide.png" media="min-width: 600px">
<img src="mdn-logo-narrow.png" alt="MDN">
</picture>
Прописал условия и вуаля
У браузера итак есть всё что нужно:
- он знает pixel density
- он знает размер
- он знает пропускную способность сети
Он ведь узнает это все когда загрузит картинку, а в вашем примере их три и получается надо грузить все три что узнать то что ему и не надо. Или я не правильно вас понял?
А все эти полумеры с srcset, sizes это прямо какой-то детский сад с очень ограниченным применением (мне пока ни разу не пригодилось, т.к. не было высеченных в скале layout-ов).
А зачем вам высеченный в скале шаблон, он же адаптивный должен быть и размера экрана как раз вполне хватает. Как правило выделяет два размера для ПК и моб, иногда еще один для планшетов(но чаще он совпадает с ПК). Я смотрю максимальную ширину для каждого шаблона и накидываю 20% чтоб не терялось качество, и вот под них пишем правила.
Все, браузер грузит только одну картинку. Гугл на 20% превышение ширины не ругается в своих оценках, скорость загрузки для мобильных заметно возрастает, контент не страдает.
У меня встречались случаи, когда надо не просто разные миниатюры одного изображения показывать, а абсолютно разные картинки под разные устройства и вот с этим Picture очень даже справляется. Это на много лучше чем пилить бекграундами с медиа в стилях.
А вот aspect-ratio и правда иногда не хватает, помню когда-то для магазина пришлось допиливать костыль на js
Если я правильно понял faiwer (и в этом с ним трудно не согласиться), то неудобство состоит в том, что значение атрибута media применяется к экрану и может быть никак не связано с размером самой картинки. Например, у картинки через стили может быть указано max-width:100px (или ширина ограничена неявно через стили родителя), но раз в media-атрибуте указано, что для экранов с шириной больше 600px нужно грузить большую картинку — браузер будет грузить большую картинку.
Так оно вроде так и работает
Нет. Оно так НЕ работает.
<sourсe srcset="mdn-logo-wide.png" media="min-width: 600px">
Вот тут min-width
это не размер картинки. Это размер окна. По сути мусор.
и размера экрана как раз вполне хватает.
Ни разу не хватает. Я даже больше скажу это вообще не тот фактор который играет роль. Мне глубоков плевать какого размера окно. Единственное что важно — какого размера сам контейнер картинки. И он может быть вообще не связан с размером окна. Либо связан столь причудливым образом, что любая попытка эту взаимосвязь выставить будет безумной.
У меня встречались случаи, когда надо не просто разные миниатюры одного изображения показывать, а абсолютно разные картинки под разные устройства и вот с этим Picture очень даже справляется.
А вот это очень редкий кейс. Но да, для него уже что-то есть.
Я потратил много времени на написание нормального Picture компонента, который, используя ResizeObserver, работает как надо (за исключением того что ResizeObserver очень ненадёжная штука). И у меня бомбит от того, что из каждого утюга пишут про то какой <picture/>
хороший, при том какой он плохой. Прямо стыдно за коммитет, что они такую херню утвердили.
А вот если ширина контейнера не задана тогда что грузить, что-то по дефолту?
Идем дальше. Рядом с картинкой идет текст без переносов и он не помещается в свой блок, браузер начинает адаптировать его и уменьшает контейнер с вашей картинкой, что тогда, грузить еще одну миниатюру?
Ни разу не хватает. Я даже больше скажу это вообще не тот фактор который играет роль. Мне глубоков плевать какого размера окно.
Если у вас ширина картинок задана жестко то да ширина экрана вам и не нужна, но если вы знаете этот размер то можете туда и нужную картинку подставить. Ну разве что у вас этот размер меняется от ширины экрана но тут опять же, вы будете это делать через медиа.
Если у вас ширина контейнера(в котором будет картинка) задана относительно, то она точно зависит от ширины окна и тут снова медиа все решает.
Да бывают случаи когда заказчик хочет чтоб у него под все возможные ширины экрана были личные стили, но это уже зайоб заказчика и вот тогда приходится костылями на js решать, но чаще всего медиа достаточно.
Я потратил много времени на написание нормального Picture компонента, который, используя ResizeObserver, работает как надо (за исключением того что ResizeObserver очень ненадёжная штука). И у меня бомбит от того, что из каждого утюга пишут про то какой <picture/> хороший, при том какой он плохой. Прямо стыдно за коммитет, что они такую херню утвердили.
То есть вы сами говорите, что это не тривиальная задача, но хотите чтоб это встроили в ядро и оно само там как-то как догадывалось заранее кокой ширины будет контейнер. Я так понимаю, ваша реализация ждет рендеринга своего контейнера, а только потом начинает грузить картинку, а при ресайзе ее заменяет новой?
Браузер не может ждать пока отрендерится весь контент, чтоб точно знать ширину контейнера и определять, что ему грузить. Если бы так было то мы бы вернулись в 2000-е к IE который сначала текст отрисовывал, а потом по очереди грузил нужные картинки.
Собственно я это к чему все написал: во время загрузки ширина окна не меняется, она заранее известна и можно сходу понять какую картинку загрузить на основании media-правил, не ожидая когда оно там все отрисует.
Я правильно понял: вы хотите чтобы браузер грузил url картинки в зависимости от ширины контейнера в котором находится эта картинка?
Под контейнером я подразумеваю сам тег <img/>
. Не его родительский условный <div/>
, а сам. Т.е. тот самый прямоугольник в котором браузер будет рисовать картинку.
А вот если ширина контейнера не задана тогда что грузить, что-то по дефолту?
Нет. Браузер знает фактический размер контейнера в котором рисует картинку (<img/>
, <picture/>
). Как он задан — второстепенный вопрос. Главное что итоговый размер известен браузеру.
Остальное комментировать не буду, т.к. нерелевантно. Плевать какая разметка у страницы. Главное что на момент рендера браузеру уже известные размеры и доступные файлы изображения.
и оно само там как-то как догадывалось заранее кокой ширины будет контейнер.
Оно знает размер контейнера. Это браузер. Это render фаза. Весь CSS + HTML layout уже просчитан. Ему не нужно догадываться. Это вводные данные.
и можно сходу понять какую картинку загрузить на основании media-правил,
Только в самых тривиальных случаях. Размер картинки может зависеть от десятка параметров, среди которых размер окна может вообще отсутствовать.
То есть вы сами говорите, что это не тривиальная задача, но хотите чтоб это встроили в ядро
Да. Я хочу чтобы это встроили в ядро. Вместо этого убожества, что есть сейчас. Заодно я хочу content queries. Надеюсь я доживу до того дня, когда их наконец внедрят.
Вам намекают на то, что сейчас браузер может начать грузить изображения сразу после разбора HTML
Интересный момент. Не думал о нём, т.к. пишу только SPA последние много-много лет. Т.е. мне совсем не актуально. Но ок, представим себе ситуацию:
- у нас есть множество файлов изображений с одинаковым aspect-ratio
- мы хотим чтобы браузер грузил нужный файл ещё ДО того как он смог организовать render
- для этого нам нужно гарантированно задать изображению точные размеры
Если так, то этот момент можно продумать в спецификации. Дескать если данных достаточно, то браузер оставляет за собой возможность загрузить изображения до рендера.
Нет. Браузер знает фактический размер контейнера в котором рисует картинку (, <picture/>). Как он задан — второстепенный вопрос. Главное что итоговый размер известен браузеру.
Не согласен. Он узнает окончательный размер только при рендеринге всех соседних блоков и тогда сработает событие load. До этого блоки могут меняться, а если вы вообще никак явно не указали ширину то она будет нулевой.
Вот к примеру визуализация данной страницы, когда уходит запрос и когда закончен рендеринг. Запросы на картинки ушли на 2,2 сек, а применение стилей закончилось только 2,8 сек, а бывает что подключение стилей объявляют в футере и они отрендерятся (будет известен точный размер блока картинки) еще позже.
Вот можете сами убедиться о чем знает браузер и когда пример на codepen.io (Только открывайте с чисткой кэша)
А дальше откройте консоль к примеру этой странице на закладке network и посмотрите когда отработало событие DOMContentLoaded и load. В браузере большинство мелких картинок уже загружено еще до события DOMContentLoaded.
О, теперь понял вас. Вы про ситуацию когда стили ещё не загружены. Тысячу лет с таким не сталкивался, т.к. последние годы работал только с SPA. Для SPA это чаще не актуально (хотя зависит от имплементации). Т.к. HTML уже инжектится на страницу со всеми необходимыми стилями. Т.е. размеры известны сразу после appendChild
. И DOMContentLoaded
давно позади.
Касательно immediate загрузки без стилей. Ну тут нужно думать. Варианты есть, но уже не так всё однозначно. Например отложить загрузку пока изображение равно 0х0. Меня бы вполне устроило. Это точно лучше чем грузить что попало.
Либо я чего-то не понимаю, но как быть вот с этим при адаптивном дизайне
<!-- Providing width and height is more important than ever. -->
<img height="853" width="1280" … />
То есть на десктопе все ок, но когда открываешь в мобилке, то появляются ограменные отступы от изображения сверху и снизу
И еще вопрос про srcset и sizes, какой в этом смысл. Если уже давно число пикселей расчитывается сложнее
Число физических (реальных) пикселей равно числу CSS-пикселей, умноженному на соотношение пикселей (pixel ratio).
Век экранов, у которых число реальных и CSS-пикселей совпадает, давно кончился. Помните, когда-то Apple революционно вышла на рынок с ретина-дисплеями? Это когда pixel ratio — 2. На Samsung Galaxy S6 2015 года соотношение физических пикселей к CSS-пикселям 4! Большинство китайских смартфонов сегодня — это pixel ratio 2-3.
А значит, если у нас на мобилке картинка занимает 360px, нет смысла загружать иллюстрацию шириной меньше, чем 360×2=720px! А обладатель корейского флагмана был бы не против и все 1440px загрузить.
Так что в этой штуке очень мало смысла, возможно кто-то меня перубедит
И w — дескриптор ширины. Это очень удобно, если запомнить, что w — это реальные пиксели, а px — CSS-пиксели, и тогда работа srcset/sizes станет еще понятнее.
Я тут один помню времена, когда не было flex и grid и колонки делались через float:left и это было очень прогрессивно, так как многие еще и таблицы использовали :).
Или для видео надо было мудрить флеш-плейер с js. А сейчас оно из коробки может показывать.
А уж про адаптацию под три-четыре браузера вообще вспоминать не хочется (хотя иногда приходится под сафари что-то доделывать)
За статью спасибо про некоторые подходы не знал.
Набросал тут скрипт sh, для сжатия изображений с помощью optipng, advpng, pngcrush и jpegoptim. Может кому пригодится.
Скрипт: https://blog.upagge.ru/posts/snippet/2021/shell-script/image-optimization/
Максимально оптимизированная веб-загрузка изображений в 2021 году