Что такое валидные картинки
Три способа поддержать вставку картинок в поле ввода от разработчиков Яндекс.Почты
Не так давно мы подробно рассказывали про новые аттачи в Яндекс.Почте. В декабре в у нас появился новый просмоторщик картинок. Работать с изображениями в Почте благодаря этим нововведениям стало действительно проще и удобнее.
Тем не менее, оставалась ещё одна сложность: в связи с браузерными ограничениями изображения нельзя было вставлять прямо в тело письма. Картинку нужно было сохранить на своём компьютере и уже оттуда прикрепить к письму, как любой другой файл.
Мы долго думали над этой проблемой. Можно было использовать java-апплет или flash, но у этих решений были существенные ограничения. Например, при использовании java-апплета нужно будет обязательно разрешать выполнение апплета в браузере. В итоге мы решили использовать новые возможности современных браузеров, такие как Clipboard API, File API и Drag n Drop.
Читайте в нашем посте о том, как вставлять в письмо картинки из буфера обмена или по публичному URL и как добавлять их в тело письма простым перетягиванием с рабочего стола.
Вставка картинок из буфера обмена
До недавнего времени полноценная работа с буфером обмена в веб-приложениях казалась невозможной. Но затем появился новый API, специально предназначенный именно для этого (Clipboard API). Он представляет собой интерфейс для работы с данными из буфера обмена при копировании, вырезании и вставке. Интерфейс достаточно универсальный и работает не только с текстовыми данными, но и с файлами в разных форматах. Но, как это обычно бывает, поддерживается он не всеми браузерами и в разном объёме.
Наиболее полная поддержка на сегодняшний день реализована только в WebKit-браузерах (Safari, Chrome, Яндекс.Браузер). В этих браузерах для событий copy, cut и paste в объекте события есть доступ к объекту clipboardData. У clipboardData есть свойства items (элементы в буфере обмена) и types (типы информации в буфере обмена). Получать или менять информацию из буфера можно при помощи методов getData и setData.
В Chrome (c 18 версии) и Яндекс.Браузере есть доступ к картинкам в буфере обмена при вставке. Делается это примерно так:
Кроме браузеров на движке WebKit, вставка картинкок из буфера обмена также работает в Firefox: там картинки в designMode сразу вставляются в data:uri.
Вставка картинок по публичному URL
Одно из самых простых и привычных действий — скопировать картинку со страницы в интернете и вставить её в письмо — не поддерживается браузерами по умолчанию. В Safari 5+ в объекте clipboardData нет свойства items, но есть массив types, содержащий типы копируемой иформации. И если копируемая картинка уже есть в интернете по публичному урлу, то её тоже получится вставить. При обычной вставке картинок в designMode Safari создает элемент img с фейковым значением аттрибута src (webkit-fake-url://416873AC. ). К этому ресурсу никак нельзя получить доступ из JS, поэтому, чтобы фейковая картинка не вставлялась нужно делать preventDefault у объекта события.
Вставка по публичному урлу по умолчанию работает в IE9 и выше.
Вставка перетягиванием
Помимо прямого копирования картинок из буфера обмена или по публичному урлу, в некоторых браузерах есть возможность вставлять картинки драг-н-дропом. Это очень удобно, потому что можно добавить к письму несколько картинок сразу.
Это работает в Firefox, Safari 5.1+, Chrome и Яндекс.Браузере.
. Доклад Яндекса
«Просто добавь картинку на сайт», — говорили они. А оказалось, что «просто» не значит «правильно». В докладе я постарался разобраться, как эффективно добавлять изображения на страницу, какие форматы графики для каких случаев полезны и как автоматизировать автоматизируемое.
— Всем привет. У меня доклад с интригующим названием в виде одного тега.
Коротко представлюсь. Возможно, вы слышали о подкасте «Веб-стандарты» — иногда там можно услышать мой голос. И если новости в пабликах «Веб-стандартов» выходят с опечатками — скорее всего, это я. Работаю я в Яндекс.Поиске, разработчиком интерфейсов.
Сегодняшний доклад — по мотивам другого доклада. В 2019 году я успел вскочить в последний вагон и на последнем Web Standards Days прочитал доклад про ссылку.
Интригующее название было. Тогда из зала прозвучал вопрос: «Когда будет про следующие теги?» Сегодня вы смотрите доклад именно про следующий тег, о котором мне хотелось рассказать.
Начнем с истории. Шёл 1995 год. Тогда впервые появился тег img в стандарте HTML 2.0. Вы можете найти спецификацию — в то время они писались гораздо более сухо, чем сейчас. Но там есть интересные моменты.
В стандарте HTML 2.0 можно найти, что атрибутов у img тогда было не то чтобы много.
В 2020 году стандарт немножко поразноцветнее, и в нём гораздо больше подробностей.
Этого достаточно, чтобы начать работать с картинкой. JavaScript, например, может взять этот код и дополнить. Возможностей много.
Есть и другие сущности, которые можно получить из HTTP-заголовков. Их удобно использовать, чтобы экономить трафик, принимать другие решения.
Атрибут src — мощная и сложная штука, потому что это один из немногих способов внутри HTML дернуть какой-нибудь URL. Ссылка — первый способ, но ссылка — это когда ты кликаешь сам, осознанно. А здесь пользователь ничего не нажимает, но куда-то идет запрос. Здесь речь и про безопасность тоже. Та ещё задача.
Форматы графики могут быть разные: gif, jpeg, ico, png, apng, tiff, svg, webp, avif и так далее. Это самые популярные из них. TIFF, кстати, до сих поддерживается в Safari. Другие браузеры я не проверял. Но официально поддержки вроде как нет.
Мы уже доросли до того, что AVIF — это поддерживаемый браузерами формат графики.
Про форматы изображений я в 2018 году читал отдельный доклад.
Он был про то, как любым способом доставлять картинки (в том числе через background ), как и что сжимать.
Вот еще один способ дёрнуть какой-нибудь URL без HTML:
Нужно понимать, когда у картинки при загрузке вызывается обработчик onerror в коде выше. Это произойдет в нескольких случаях:
А вот такой пример мы же тоже в жизни видели, да?
Почему-то ресурсы не доходят, и браузер рисует какую-то странную иконку. Что нужно делать?
Есть важный нюанс: IMG — заменяемый элемент. Это значит, если картинка загрузилась, то всякие псевдоэлементы вы ему задать не можете — потому что IMG так себя ведет. Но если картинка не загрузилась, там появляется целый shadow-root, который вы можете посмотреть в Chrome DevTools, если поставите галочку «Show user agent shadow DOM» в настройках. Так можно увидеть, что вместо картинки показывается полноценный новый HTML. Вы можете добавлять туда псевдоэлементы before и after. И это можно использовать.
Например, Ире Адеринокун предлагает интересный способ.
Кажется, это даже можно автоматизировать. Например, парсить страницу через Puppeteer или еще чем-нибудь. Если какие-то картинки сломались, находите, какие именно, даже таким визуальным способом, и где-то их собираете. Хотя, конечно, профилировать запросы в сеть в этом смысле гораздо удобнее. Но есть и такой способ.
Но всё равно такой плейсхолдер выглядит не очень, да? А что, если мы его стилизуем?
Если у нас есть доступ к before и after, там же можно много чего натворить. Например, добавить after, приподнять его z-индексом над картинкой, чтобы не было видно стандартной иконки. И стилизуйте как хотите. Я эмодзи вставил — работает.
Главное — фантазия. У Лин Фишер, например, фантазии много, и есть сайт a.singlediv.com, где она на одном div делает целые анимированные произведения искусства. У вас есть before и after, целых два псевдоэлемента, которые можно стилизовать. Задумайтесь.
Но, допустим, мы вообще не хотим сломанных картинок. Можно ведь использовать сервис-воркер! Как с ними быть?
Еще один пример от Ире Адеринокун.
В сервис-воркере есть возможность, если мы вешаем обработчик на событие fetch и видим, что запрос сработал хорошо, просто вернуть его результат браузеру. Сходили за ресурсом — он есть — вернули.
Но есть два случая: либо мы сходили за ресурсом и ответ — не ок, либо на каком-то из этапов выбросилась ошибка. Это, скорее всего, значит, что пользователь в этот момент находится офлайн. Что можно сделать?
Можно определить, был ли это вообще поход за картинкой или не за картинкой, сделать вспомогательную функцию для этого.
Затем мы просто берем непонятные нам случаи — когда либо что-то с запросом, либо выбрасывается ошибка — и возвращаем из кэша уже то, что лежит на локальном устройстве пользователя.
Вместо непонятной дефолтной иконки мы можем вернуть стильный плейсхолдер. Не стесняйтесь призвать дизайнера в помощь, чтобы сделать это красиво, а не своими силами рисовать плейсхолдеры при помощи CSS.
Конечно, можно пойти дальше и вообще все картинки закэшировать, чтобы они всегда возвращались. Но это не так интересно.
Что будет, если мы атрибуту alt зададим пустое значение?
Во-первых, браузер не будет показывать эту сломанную иконку, когда картинка не загрузится. Вы даже не увидите, что у вас что-то не так. Не загрузилось, размеров нет, будет пусто. Во-вторых, для невизуальных браузеров это ещё и призыв не озвучивать картинку.
Таким образом, если у вас декоративное изображение, вы можете его спрятать.
Доступность
Картинки — визуальная штука. Людям с хорошим зрением, конечно, хорошо в интернетах сидеть и всё видеть, но я рекомендую вам сходить на weblind.ru, — отличный ресурс, где собраны рекомендации, как минимальными усилиями сделать ваши сайты чуть более доступными.
Короткая выдержка оттуда. Есть изображения информативные и декоративные. Информативные — это которые про контент, когда пишется текст, следом идёт картинка, которая дополняет этот текст, и вы в alt можете описать, что на этой картинке. Описывайте так, что если бы вы читали этот текст-описание, то как будто картинки даже не и было, можно её себе представить.
Декоративные — не несут особого смысла и, скорее всего, сделаны для красоты. Их можно спокойно выбросить, и ничего с текстом не случится.
У сайта «Веб-стандартов» есть CONTRIBUTING.md для тех, кто пишет статьи, переводы и так далее. У нас есть рекомендации, как всё это делать лучше. Совместно с Татьяной Фокиной сделали классные советы, которыми я хочу с вами поделиться.
Про пустой alt мы уже поговорили.
Это хорошие практики. Если действительно что-то мешает чтению картинки на слух, используйте их.
Если вы хотите запихнуть в картинку нечто сложное, например график, то я рекомендую посмотреть в сторону SVG и выставить для него правильную роль.
Здесь я рекомендую посмотреть замечательный доклад Сергея Кригера о том, как делать доступные графики, — на случай, если вам действительно нужно сделать график и описать его, чтобы все могли им пользоваться.
Вернёмся к котятам.
Размеры
Итак, вы указываете это значение ширины. Тогда возникает вопрос: откуда браузер берёт второй размер, высоту?
А если задать только высоту, как браузер рассчитывает ширину? Откуда он её берет?
Здесь можно копнуть глубже. Например, вы можете расковырять ваши картинки как бинарные файлы и посмотреть в спецификации.
В спецификации PNG первые восемь байт вообще прибиты гвоздями, эти байты и говорят, что это PNG-файл. Дальше всякая служебная информация, и есть кусочек, я его подсветил выше, который говорит: ширина и высота вот такие. Прямо в первых, буквально заголовочных кусках файла есть размеры.
С GIF всё ещё проще, потому что сам формат проще.
Тут можно сходу сказать, что у этой гифки размеры 500×275. Можно прямо в текстовом редакторе посмотреть.
С JPEG — сложнее. Cходу такой же красивый и наглядный пример вам собрать не смог, потому что там много интересного, но не очень очевидного. С WebP даже не пытался.
Но для любых графических форматов есть правило: в самом верху файла, буквально с первыми пакетами при скачивании приходит размер. Как только браузер делает запрос за картинкой, и картинка начинает приходить, браузер тут же выцепливает эти размеры и резервирует с их учётом под картинку место.
Очень рекомендую доклад Полины Гуртовой «Картинки как коробки. Что же там внутри?». Полина классно рассказала, как вообще всё внутри устроено, про разные форматы, в том числе про PNG, о котором я только что говорил. Есть видео и расшифровка на Хабре, обязательно почитайте.
Тут важно задавать правильные размеры. Я думаю, все вы видели эти ужасные случаи, когда прямоугольная картинка из-за криво заданных размеров зачем-то вписывается в квадрат, и получается нечто непропорциональное. Поэтому здесь хорошо бы, конечно, прикрутить какую-то автоматику. Но если вы делаете это руками, скорее всего в бизнес-процессах есть этап добавления картинки где-нибудь в вашей админке, если контентом занимается контент-менеджер. Там вы можете получить размеры, сохранить их в базу и потом подставлять эти размеры в клиентский код. Например, подставлять физические размеры картинки, как есть. А уже дальше в CSS вычислить, что с ними делать.
Но на самом деле нет, уже не можем. Авторы спецификаций обсуждали-обсуждали и пришли к тому, что, кажется, можно сделать более элегантно.
Поддержка у этого свойства достаточно хорошая, на мое удивление. Уже можно, даже нужно, 66% пользователей будут счастливы.
Загрузка
Дальше можно поиграться с тем, как вообще эту картинку получить.
Для начала можем задать, какую информацию мы отправляем на сервер. Вы же иногда подключаете картинки из каких-нибудь CDN или с внешних ресурсов, не только у себя их держите.
В данном случае я чётко говорю браузеру: отправляй, пожалуйста, только домен и все. Больше ничего не надо, полный URL отправлять не надо. В конце концов это тоже информация, которую тот, кто хранит картинку, может использовать.
Ещё один вариант — это когда вы ходите за картинкой на другой домен.
Понятно, что мы, разработчики, можем эту картинку скачать себе любым другим способом и расковырять её у себя локально. Но если вы не настроили cross-origin запрос, то от браузера получите ошибку DOMException. Она будет говорить: простите, данные с другого домена — нельзя. И в этом случае нужно добавить атрибут crossorigin картинке, чтобы всё заработало.
У него есть в том числе и значение. По умолчанию это анонимный CORS-запрос. Он такой идёт на сервер: «Ну, пожалуйста, можно я поковыряюсь в байтиках?» И если сервер в ответ: «А, давай! Пожалуйста, на тебе Accept, бери всё и ковыряй», — то в canvas вы сможете поиграться с данными.
На самом деле это история не только про canvas. Например, вы хотите бинарные данные в LocalStorage положить. Подходов и применений много, но вам нужно получить доступ к бинарникам.
Яркий пример — CodePen. Если вы там когда-нибудь рисовали на canvas что-то из внешних изображений, то, возможно, сталкивались с ошибкой доступа к данным. Я сталкивался. Приходилось хранить картинки в base64, потому что у меня бесплатный аккаунт.
И он вроде как классный, но есть нюансы. У него три значения:
Но, например, в исходном коде Chromium можно найти такие интересные настройки.
Offline — 8000
Slow 2G — 8000
2G — 6000
3G — 2500
4G — 1250
Когда соединение офлайн или очень медленное, то браузер загружает все картинки в пределах 8000 пикселей от текущего вьюпорта. При этом на самом быстром соединении — в пределах 1250 пикселей.
Причем значения постоянно меняются. Я так понимаю, разработчики браузеров проводят замеры, эксперименты, в интернете идут холивары, какие числа более правильные, потому что каждый браузер немножко по-своему их подбирает.
Чем хуже соединение, тем больше картинок качается. Это не очень очевидно, и вам нужно понимать, что это не про экономию трафика, а именно про скорость соединения.
Зачем так сделано — объяснение простое. Пользователь обычно страницы скроллит. И на медленном соединении, пока он доскроллит, уже всё должно быть хорошо, хорошо видны картинки. У пользователя должен быть потрясающий опыт пользования вашей страницей.
Чем медленнее соединение, тем раньше за картинкой нужно сходить. На быстром соединении оно вроде как быстро загрузится, зачем париться?
Но эти значения — 1250 — достаточно большие. Используйте на свой страх и риск, если вы в первую очередь задумывались про экономию трафика, а не про скорость.
В официальной статье про lazy loading на web.dev описан способ, как это сделать с поддержкой браузеров, которые не умеют в нативную ленивую загрузку.
Если нет, то взять библиотечку, которая сделает то же самое, но уже без браузерных механизмов. Если вновь поковыряться в коде того же Chromium, там точно так же создается Intersection Observer, как если бы вы это делали руками. И точно так же, но с более внутренними механизмами, делается всякая магия: «Ага, здесь мы определяем, сколько до вьюпорта, дальше качаем».
Это когда вы уже прямо тюните сайт под перформанс.
В голове у нас процесс такой: картинка загрузилась, потом нарисовалась. На самом деле в серединке, между «загрузилось» и «нарисовалось», есть декодинг и ресайз картинки, не нулевые по времени процессы.
Декодинг картинки на среднестатистическом устройстве Moto G — это 300 миллисекунд в примере Эдди, заметно даже глазом. Стоит задуматься, что большие картинки декодируются дольше и, может, их надо позже декодировать, если не хотим зря тратить ресурсы. Важно: желательно не давать браузеру и ресайзить тоже. Пускай сразу приходит только самое нужное.
Помните: когда у вас выполняется JS, он блокирует основной поток. Будем считать, что браузер однопоточный, и вы блокируете рендеринг. Если вы выполняете долгий JS, то и картинка не нарисуется. Потому что браузер в этот момент занят, он ваш while (true) обрабатывает.
Здесь самое интересное. Спеки четко не прописаны, инструкция — грузить изображение, которое явно больше. То есть браузеры решают сами, как это оптимально сделать. И в разных браузерах поведение разное.
В srcset ещё можно указывать плотность пикселей.
Иначе вы будете очень долго дебажить, почему вы просите одну картинку загрузить, а она вообще не та.
Вы можете позамерять, насколько эффективно вы используете картинки на странице. Например, я зашел на сайт GDG Russia при помощи пакета imaging-heap от Filament Group.
Прелесть в том, что мы можем поддерживать разные форматы. Не так уж давно зарелизился формат AVIF, в Chrome он уже поддерживается.
У Джейка Арчибальда есть потрясающая статья, которая объясняет, почему этот формат клёвый, в каких случаях он работает хорошо. Вы можете увидеть, что для некоторых картинок AVIF сжимает лучше, чем SVG. У меня в голове это по первости не укладывалось — это же векторный формат, а нас учили, что векторный формат занимает мало. Ничего подобного.
AVIF — это видеокодек AV1, который оптимизирован и адаптирован под изображения. Внезапно видеокодек позволяет сжимать картинки лучше, чем специальные картиночные форматы.
Обязательно посмотрите в статье Джейка, что это за формат такой. Кажется, его уже пора использовать.
Ингвар Степанян в твиттере поделился отличным способом, как вообще при помощи JavaScript минимальным кодом определять, поддерживает ли браузер тот или иной формат.
Ещё у нас есть медиавыражения. Мы можем точно так же под разные медиавыражения получать разные картинки. Например, смотрим на высоту изображения, ширину вьюпорта и берем более широкую, десктопную картинку. А для маленьких экранов — мобильную.
Звучит страшно: WebP, AVIF, JPG, PNG, все эти retina, да еще и под разные размеры! Как с этим работать?
Можно, конечно, попробовать руками.
Я обожаю инструмент Squoosh, там уже поддерживается AVIF. Так вот, Squoosh позволяет сжимать картинки, менять их размеры и не только. Но руками это долго.
Ещё пользуюсь ImageOptim. Например, некоторые картинки для этого доклада сжаты там. Тоже потрясающий инструмент. Но это всё — не автоматизация.
Для доклада собрал свой подход. Я фанат Gulp. Можете посмотреть у меня в репозитории: mefody/image-processor.
Использую простые пакеты: gulp-imagemin, gulp-responsive, imagemin-guetzli, imagemin-pngquant, imagemin-svgo, imagemin-webp. Думаю, у вас может быть похоже.
Я просто из этого стартера собираю себе почти под любой проект оптимизатор картинок, который распиливает их по разным размерам. gulp-imagemin внутри себя содержит imagemin.
Чем этот пакет хорош? Тем, что туда можно подключать новые плагины. Но там пока нет поддержки AVIF (на момент подготовки доклада — прим. автора).
Зато там есть поддержка Guetzli. Этот алгоритм тоже разработан в Google. В чем его суть?
Что обычно делают оптимизаторы? Они снижают качество у JPG, не меняя информацию о цвете. А Guetzli ещё и меняет цвета картинок, но так, чтобы визуально для глаза это почти не чувствовалось. Ключевое слово — «почти». И оказывается, за счёт такого незаметного изменения цветов можно сделать сжатие значительно круче.
Но происходит страшное. Даже на картинке 1000×1000 у вас начинает жужжать ноутбук, всё это обрабатывается очень долго. Алгоритм банально делает очень много разных переборов и сравнений. При этом сжимает настолько потрясающе, что у меня JPG обычно весят меньше, чем WebP. Поэтому я могу из своих source в принципе выкидывать ненужный мне WebP. Но, кстати, объём у сжатых через Guetzli картинок всё равно больше, чем у AVIF. Я попробовал.
Кстати, «guetzli» — это, я так понимаю, сладость, скандинавская выпечка. Как-то в подкасте мы пытались выяснить, что такое guetzli, brotli, zopfli. Оказалось, всё это — выпечка.
AVIF уже, на самом деле, в gulp засунуть можно, но через костыли.
Для этого ещё нужно дополнительное шевеление бубном на Mac.
Я устанавливаю пакеты через brew. avifenc — это C++-пакет, который умеет работать с AVIF.
Словом, работу с AVIF уже можно автоматизировать. Не ленитесь.
Что ещё можно делать? Например, дёргать всего одну картинку, которую положить на CDN, который будет сам решать, что отдавать.
Например, у «Злых Марсиан» есть проект imgproxy. Очень рекомендую вам на него посмотреть. С ним можно всевозможными настройками задать размер, retina/не retina. Даже водяные знаки можно рисовать. Подобные CDN позволяют вам не думать про сборку. У вас есть только исходник, а уже CDN берет на себя часть работы, чтобы этот исходник, например, при первом обращении обработать, закэшировать и отдать.
Ещё одна важная штука. В media вы можете задавать любые медиазапросы, не только про ширину и высоту. Например, можно подсмотреть, что у пользователя установлена настройка, что он любит тёмную тему.
Раз он выставил её у себя в системе, так дайте ему отдельную картинку для тёмной темы. Потому что если вы на черной странице нарисуете яркую белую гифку, пользователь чуть-чуть ослепнет и будет ваш сайт чуть-чуть не любить.
Когда пользователь будет между разными темами переключаться, это, кстати, может произвести вау-эффект.
Ещё важно помнить про пользователей, которые не любят движение на сайтах.
А вот если пользователь нормально относится к гифкам, рисуйте ему эти гифки. Хотя есть отдельный доклад Вадима Макеева pepelsbey «Делайте из слона муху», где он говорит, что не надо. Лучше подключайте видео, потому что GIF безумно много весит.
Пятиминутка ностальгии
И другие атрибуты, из прошлого.
Это прикольно, и, кстати, оно до сих пор работает в браузерах. Кажется, в Safari есть нюансы, но в целом вроде как работает. Сейчас непонятно, зачем, но поиграться можно.
Таким образом можно одну картинку-меню сделать, обработать на сервере, узнать, куда пользователь кликнул. И, например, нарисовать иконки, в которые надо кликать.
Так делали раньше. Сейчас я таких обработчиков уже не встречал, но если хотите поприкалываться, почему бы и нет.
И есть deprecated-атрибуты, такие как align, border, hspace, vspace, name, onerror. Они браузерами всё ещё поддерживаются. Работает обратная совместимость веба: нельзя просто сломать половину сайтов.
Но считается, что вместо них уже нужен CSS. Причем атрибут align работает интересно, позволяет внутри блоков всякое выравнивать. Вроде как можно через float это всё сделать, но align более гибкий, что ли. Мне он в своё время нравился, а сейчас он уже deprecated.
Рамки
Есть задача, которая часто встаёт перед разработчиками, — поместить картинку в какие-то рамки.
Если просто выровнять по ширине — пожалуйста.
Максимальную ширину ставим 100%, высоту — auto, и браузер масштабирует как надо. Всё будет хорошо для горизонтальных картинок.
А что если нам нужны заданные пропорции? Например, часто есть такой заказ: «Давай вставим превьюшку с YouTube, которая обязательно должна быть 16×9».
Есть старый-добрый padding-хак.
Поддержка уже хорошая, но если вам нужно поддерживать много всякого, то, опять же, у Вадима Макеева на его канале есть подробный разбор.
Кадрирование
Which will the Twitter algorithm pick: Mitch McConnell or Barack Obama? pic.twitter.com/bR1GRyCkia
Но будьте аккуратны, потому что Twitter с таким угодил в скандал. Оказалось, что алгоритм, который определял, как правильней кадрировать, был расистским. Публично извинялись. Машинное обучение — вроде крутая штука, но там ещё очень много проблем в том, как определить, что показывать.
Мне нравится подход, который случайно нашел на CodePen.
Вы можете использовать две картинки, тогда у вас не будет пустого пространства. Точнее, URL у картинок одинаковый. Но подключаете вы их в контейнере друг за дружкой. Первую прячете, чтобы ее не было слышно, например, на скринридере.
В итоге у вас получается вот такой эффект:
Красиво. На YouTube некоторые блогеры вертикальные видео похоже обрабатывают.
По ссылочке есть полный код, как это сделать. Мне такой подход больше нравится, потому что мы хотели заполнить всё, — заполнили, при этом картинку видно всю, а мы ничего лишнего не обрезали.
Знаете, что у картинок есть в CSS особенность — там можно задавать способ, как их рендерить?
По умолчанию браузер, увеличивая вашу картинку, как-то её смазывает. Есть алгоритм, который делает это сглаживание. Вы можете сказать: «Нет, браузер, я хочу pixelated». И, увеличивая картинку, он будет реально рисовать чёткие границы пикселей.
Это полезно, если у вас, например, сайт про пиксельную графику, Lego, что-то с этим связанное. Я на некоторых сайтах видел — обалденный эффект. Выставляете маленькую иконку, скажем, 12×12, растягиваете ее, и такой пиксельный эффект сохраняется. Это ещё и обалденная экономия трафика.
Быстрее
Как можно еще быстрее грузить картинки?
Есть подробный разбор от Эдди Османи, как эта штука работает. Можете посмотреть, как preload помогает ресурсы больше скомпоновать и загрузиться быстрее.
Итоги
Надеюсь, image-processor, который я для вас собрал, будет вам полезен. Я, по крайней мере, им пользуюсь. Может, и вам пригодится.
Есть еще классные материалы, которые я могу посоветовать: