Всем привет! Меня зовут Лихопой Кирилл и я - фронтенд-разработчик в компании idaproject. Сегодня я представляю вам перевод статьи о новой CSS-фиче, которую, я уверен, многие ждали. И это - object-view-box
, которое позволит нам обрезать и масштабировать фотографии не прибегая к “костылям” в виде фонового изображения или доп. элементов.
Итак, знакомьтесь - object-view-box!
Мне всегда хотелось иметь нативное средство в CSS для обрезания и позиционирования изображения в любом направлении, которое мне нужно. Это было возможно с использованием дополнительных HTML-элементов и их комбинацией с различными CSS-свойствами, которые я покажу чуть позже.
В этой статье я познакомлю вас с новым CSS-свойством object-view-box
, которое было предложено Jake Archibald еще год назад. Оно позволяет нам обрезать и изменять размер таких HTML-элементов, как <img>
или <video>
.
Проблема
В примере ниже у нас есть изображение, которое необходимо обрезать. Заметьте, что нам нужна определенная часть изображения.
Сейчас мы можем решить эту проблему одним из следующих способов
Использовать
<img>
, обернув его в дополнительный элементИспользовать изображение как
background-image
и изменить его позиционирование и размер
Оборачивание в дополнительный элемент
Это достаточно распространенное решение данной проблемы. Посмотрим, как это выглядит:
Оборачиваем изображение в другой элемент (в нашем случае
<figure>
)Добавляем
position: relative
иoverflow: hidden
Добавим
position: absolute
для изображения и поиграемся со значениями позиционирования и размером, чтобы добиться желаемого результата.
<figure>
<img src="img/brownies.jpg" alt="">
</figure>
figure {
position: relative;
width: 300px;
aspect-ratio: 1;
overflow: hidden;
border-radius: 15px;
}
img {
position: absolute;
left: -23%:
top: 0;
right: 0;
bottom: 0;
width: 180%;
height: 100%;
object-fit: cover;
}
Установить изображение в качестве фона
Для этого решения мы используем <div>
и установим наше изображение в качестве фона, затем изменим позиционирования и размер.
<div class="brownies"></div>
.brownies {
width: 300px;
aspect-ratio: 3/2;
background-image: url("brownies.jpg");
background-size: 700px auto;
background-position: 77% 68%;
background-repeat: no-repeat;
}
Это работает как надо, но что, если мы хотим применить вышеуказанное к элементу <img>
? Именно в этом и заключается суть свойства object-view-box
.
Представляем object-view-box
Я очень сильно обрадовался, когда увидел, что свойство object-view-box
может быть добавлено в Chrome 104. Сейчас оно доступно в Chrome canary.
Согласно черновику CSS:
Свойство
object-view-box
указывает “область просмотра” для элемента, так же, как это делает аттрибут<svg viewbox>
, позволяя увеличить или обрезать контент элемента.
Свойство принимает значение <basic-shape-rect> = <inset()> | <rect()> | <xywh()>
. Для демонстрации, в этой статье мы сосредоточимся на использовании inset()
.
Давайте вернемся к нашей проблеме.
С object-view-box
у нас есть возможность использовать inset
, чтобы нарисовать прямоугольник через указание 4 сторон (top, right, bottom, left), а затему применить object-fit: cover
, чтобы избежать искажения.
<img src="img/brownies.jpg" alt="">
img {
aspect-ratio: 1;
width: 300px;
object-view-box: inset(25% 20% 15% 0%);
}
Как это вообще работает? Не переживайте, я все сейчас объясню. Давайте разбираться дальше!
Внутренний размер изображения
Внутренний размер изображения - это его дефолтные ширина и высота. Изображение в примере имеет внутренний размер 1194 x 1194 px
.
img {
aspect-ratio: 1;
width: 300px;
}
С такими стилями визуальный размер изображения будет 300 x 300 px
.
Наша цель - нарисовать прямоугольник на оригинальных размерах изображения. Для этого используем значение inset()
.
Использование inset()
Значение inset()
будет считаться от оригинальной высоты и ширины изображения. Это поможет нам нарисовать прямоугольник как бы внутри изображения и указать 4 стороны, как для свойств margin
или padding
.
Давайте вернемся к свойству object-view-box
.
img {
aspect-ratio: 1;
width: 300px;
object-view-box: inset(25% 20% 15% 0%);
}
В примере выше показано закулисье того, что изображено на картинке. Значения 25%
,20%
,15%
и 0%
отвечают за верх, право, низ и лево, соответственно.
Если изображение квадратное, обрезанный результат будет искажен.
Но мы можем легко исправить это с помощью свойства object-fit
.
img {
aspect-ratio: 1;
width: 300px;
object-view-box: inset(25% 20% 15% 0%);
object-fit: cover;
}
Выглядит супер, не правда ли? Такая возможность может быть очень полезна в адаптиве или для показа разных частей изображения.
Увеличение / уменьшение масштаба
Мы можем использовать inset
, чтобы масштабировать наше изображение. Во время тестирования я выяснил, что transition
и animation
не работают с object-view-box
.
Мы также может уменьшить масштаб с помощью отрицательного значения inset
.
Пример
Ниже вы найдете ссылку на пример, который вы прямо сейчас можете протестировать в Chrome canary. Только убедитесь, что у вас включена опция “Experimental Web Platform features”.
А вы ждали эту фичу для CSS?
Комментарии (12)
eps
23.05.2022 01:48+1Согласно специцификации CSS:Согласно черновика спецификации CSS
W3C это ещё не обсудил до конца, не стандартизировал и "новым CSS-свойством" эта штука ещё не является.
Работа свойства может поменяться в процессе стандартизации. Поддержка браузеров появится не раньше, чем стандартизация закончится.
sanchezzzhak
23.05.2022 02:13Спасибо за статью и за вариант с абсолютом.
Новые фишки всегда хорошо, но что мы будем делать с IOS, где применение новых фич CSS просто не будет работать, в силу того что Сафари = IOS Version.Статистика за май по IOS+Версия (на моем сайте)
Без учета фильтра по OS - 886.282 уников по рекламе
iOS 15.4 - 40045
iOS 15.3 - 23128
iOS 14.8 - 8299
iOS 12.5 - 8113
iOS 15.2 - 6143
iOS 15.1 - 5963
iOS 14.7 - 5527
iOS 14.4 - 5380
iOS 14.6 - 4740
iOS 15.0 - 3299
iOS 14.2 - 1215
iOS 13.3 - 1102
iOS 14.3 - 1124
iOS 10.3 - 1315
iOS 13.6 - 1037
iOS 12.4 - 745
iOS 14.0 - 615
iOS 13.5 - 666 --- упс. просто число
iOS 15.5 - 677 --- ласт версия
iOS 14.5 - 474
iOS 13.7 - 422
iOS 14.1 - 514
iOS 12.3 - 237
iOS 13.4 - 199
iOS 12.1 - 422
iOS 13.1 - 234
iOS 11.4 - 625
iOS 5.1 - 275
iOS 11.0 - 169
iOS 12.2 - 457
iOS 13.2 - 87
iOS 7.0 - 443
iOS 10.2 - 51
iOS 9.1 - 61
iOS 12.0 - 33
iOS 11.2 - 63
iOS 5.0 - 52
iOS 11.1 - 22
iOS 11.3 - 21
iOS 13.0 - 19
iOS 6.0 - 25
iOS 10.1 - 5
iOS 4.3 - 2
iOS 9.3 - 5
iOS 3.2 - 76
iOS 9.0 - 11
iOS 15.6 - 3
iOS 7.1 - 2----------------------------
Total: 124178
Лучше всего загружать картинки максимально допустимые, а дальше уменьшать там где это нужно. Можно например в nginx поставить модуль, который налету нам сделает картинки, нужного размера.
nginx-module-image-filter # Поддержка формата WebP появилась в версии 1.11.6.
NickKolok
23.05.2022 15:54Выглядит явно избыточно. Очередной слой наворотов в браузеры. Очередной пакет полифиллов. Очередные тормоза. Брр!
Хотя элементарных фоллбэков при блокировке сервака со статикой до сих пор нет (если есть - просветите). Грубо говоря,
<script src="//cloudflare.com/jquery-6.6.6.js" src_if_failed="//rkn.gov.ru/jquery-6.6.6.js" integrity="..." >
BlackStar1991
Сложно представить практическое применение данного свойства. Отдавать браузеру пользователя заведомо большее (неправильное) изображение, ганять больший объем трафика сетью, увеличивать скорость глобального потепления... что бы потом средствами CSS вырезать определенный кусок картинки, который будет на этапе показа жрать ресурсы видеокарты, что бы показать нужную область изображения
neervel Автор
Я думаю что практическое применение все таки найдется. Например, в случае, когда размер картинки зависит не от нас, а загружается через api, заказчиком, или изображений слишком много, чтобы их отредактировать вручную.
BlackStar1991
Вот, интересная мысль.... я готов копнуть даже глубже. Поскольку object-view-box допустим для тега video, то таким образом можно "обрезать" видео с ватермарками, не грузя его себе не сервер, а давая пользователю "видеть" только нужную часть видео, не нарушая чужую собственность на контент =) Просто скрой 10% бордюра с логотипом компании...
sden77
а что мешает это сделать, спрятав видеоплеер в контейнер нужного размера с overflow:hidden
neervel Автор
Как раз таки идея в том, чтобы делать это не с помощью доп. контейнера, а именно нативными средствами css
neervel Автор
Или такой вариант, да.
Плюс в статье ещё идёт речь о других параметрах, кроме inset, так что там ещё больше возможностей
sden77
Я так подозреваю, применение обычное - это загрузка картинок на сервер с кадрированием и ресайзом. Не уверен, что имело смысл добавлять эту функциональность в браузеры - они и так чрезмерно переусложнены, а реализуется это элементарно с помощью джаваскрипта
ivan386
Лучше уж использовать CSS напрямую чем через Javascript.
pae174
Альтернатива для CSS спрайтов.