Масштабирование изображений на CSS / Хабр
Приветствую. Представляю вашему вниманию перевод статьи «CSS-Only Full-Width Responsive Images 2 Ways», опубликованной 14 апреля 2020 года автора Stephanie Eckles
Это третья статья из серии, посвящённой ознакомлению с современными способами решения CSS-проблем, с которыми я сталкивалась на протяжении более 13 лет в роли фронтенд-разработчика.
В не очень далёком прошлом, когда JQuery ещё был «Царём горы», наиболее популярным инструментом для реализации отзывчивости фоновых изображений был JQuery-плагин Backstretch
Я использовала этот плагина где-то на 30 сайтах, пока приведённое ниже свойство не получило достаточную поддержку браузерами (а если точнее, пока существенно не снизилась доля использования IE ниже 9 версии). И свойство это:
background-size: cover;
Согласно данным caniuse.com, данное свойство и значение поддерживается современными браузерами уже более 9 лет. Но вебсайты, использующие упомянутый плагин Backstretch или собственное подобное решение, могли до сих пор не обновиться.
Альтернативный метод использует стандартный тег img
и магию свойства
object-fit: cover;
Давайте рассмотрим, как использовать каждое из решений и узнаем, в каких ситуациях следует отдавать предпочтение каждому из них.
Использование
background-size: cover
В течение 10 лет я создавала глубоко настраиваемые темы и плагины для корпоративных сайтов, разработанных на WordPress. Рассмотрим сценарий использования свойства background-size: cover
на примере карточки одного из тех шаблонов.
Начнём с примера, когда фоновое изображение элемента задаётся через background-image
в HTML-атрибуте style
. Рекомендуется использовать aria-label
, который заменит атрибут alt
, присутствующий в тегах img
.
<article> <div aria-label="Preview of Whizzbang Widget"></div> <div> <h4>Whizzbang Widget SuperDeluxe</h4> <p> Liquorice candy macaroon soufflé jelly cake. Candy canes ice cream biscuit marzipan. Macaroon pie sesame snaps jelly-o. </p> <a href="#">Add to Cart</a> </div> </article>
Соответственно, CSS-стили могут быть следующими. Здесь используется трюк с padding-bottom
, позволяющий задать соотношение сторон 16:9 для div-элемента, содержащего изображение:
.card__img { background-size: cover; background-position: center; /* Соотношение сторон 16:9 */ padding-bottom: 62.5%; }
Всё вместе это будет выглядеть следующим образом:
Использование
object-fit: cover
Это новый способ, который, согласно данным caniuse, можно использовать без полифила, только если вам не нужна поддержка IE и Edge < 16
Это свойство применяется непосредственно к тегу img
, поэтому мы обновляем HTML-нашей карточки на следующий, меняя тег div
на img
и атрибут aria-label
на alt
:
<article> <img alt="Preview of Whizzbang Widget" src="https://placeimg. com/320/240/tech"/> <div> <h4>Whizzbang Widget SuperDeluxe</h4> <p> Liquorice candy macaroon soufflé jelly cake. Candy canes ice cream biscuit marzipan. Macaroon pie sesame snaps jelly-o. </p> <a href="#">Add to Cart</a> </div> </article>
Затем CSS-код дополняется свойством height
, которое будет ограничивать изображение любого размера так, чтобы оно имело заданное соотношение сторон. Если собственный размер изображения больше заданных ограничений, срабатывает свойство object-fit
, которое по умолчанию центрирует изображение внутри границ, созданных контейнером карточки и свойством height
:
.card__img { object-fit: cover; height: 30vh; }
В результате получаем следующее:
Когда использовать каждое из решений
Если нужна поддержка старых версий IE, то если не подключать полифил, вы ограничены лишь решением background-size
(мне грустно говорить это в 2020 году, но это всё ещё может быть актуально для корпоративного сектора и сферы образования).
Оба решения позволяют получить полноразмерное адаптивное изображение, основанное на контролируемом вами соотношении сторон.
Когда следует выбирать background-size
:
- при использовании с контейнером, в котором предполагается размещать какое-то содержимое. Например, с шапкой сайта
- если необходимо применить дополнительные эффекты с помощью псевдоэлементов, которые нельзя использовать с тегом
img
- если изображение носит декоративный характер и не потребности в семантике тега
img
Когда следует выбирать object-fit
:
- использование стандартного тега
img
лучше всего подходит для контекстных изображений, позволяя сохранить семантику
2D трансформации. Масштабирование | CSS: Transform (трансформация объектов)
Зарегистрируйтесь для доступа к 15+ бесплатным курсам по программированию с тренажером
Масштабирование — возможность увеличивать или уменьшать элемент на определённый коэффициент. Это полезный трюк, который очень часто используется в анимациях. Например, вы могли его встречать при наведении курсора на какой-либо элемент. В таком случае масштабирование используется во время события hover
. Попробуйте навести курсор мыши на квадрат в следующем примере:
Для масштабирования квадрата использовалась функция scale()
свойства transform
. В качестве значения может быть указано одно или два числа. На самом деле таких чисел может быть и три, но подробнее об этом мы поговорим в уроке, посвящённом масштабированию в 3D.
- Одно значение: масштабирование происходит на одинаковый коэффициент и по оси x и по оси y. Именно одно значение было использовано в примере выше.
- Два значения: в качестве первого значения передаётся масштабирование по оси x, а в качестве второго аргумента масштабирование по оси y.
Но что именно масштабируется? Если вы попробовали навести курсор в прошлом примере, то заметили, что масштабировался не только сам квадрат, но и текст внутри него. Именно так и будет происходит: функция scale()
влияет на всё, что расположено внутри блока и на него самого.
Стандартным значением функции scale()
является единица. Вы можете думать о значениях, как об процентах, где единица равна 100%. Таким образом достаточно просто определить диапазон возможных значений: 0 <= x < ∞
. Или, другими словами, функция scale()
принимает значение от нуля до бесконечности. Если элемент получит масштабирование со значением ноль, то он просто скроется. Мы можем увеличивать объект до абсолютно любого размера. Но так обычно не делают 🙂
Любое значение меньше единицы уменьшает элемент, а больше единицы увеличивает его. Обратите внимание, что число не обязательно должно быть целым. В качестве значения могут выступать и такие: scale(1.2)
, scale(0.3)
, scale(2.1)
и так далее. Главное — использовать разделитель в виде точки, иначе вы случайно укажете два разных значения: для оси x и для оси y.
Пример выше хоть и выглядит достаточно простым, но кроет в себе несколько важных моментов, о которых стоит помнить:
- Функция
scale()
не влияет на HTML элементы, расположенные рядом. Попробуйте убрать свойствоtransform
у блока с классомsquare blue
. Вы увидите, что он окажется под зелёным блоком, ровно в том месте, где и был бы без использования свойства
. То есть элемент ведёт себя так, как будто у него установлено относительное позиционирование. transform - По умолчанию, зелёный элемент оказался выше красного. Здесь происходит контекст наложения элементов друг на друга и он такой же, как и при использовании абсолютного позиционирования: блоки, расположенные ниже в HTML, по умолчанию, будут располагаться выше в контексте наложения, если не указать иного с помощью свойства
z-index
.
На самом деле, вы можете указать отрицательное значение для любого направления при использовании функции scale
. Но что это даст? Представьте, что происходит с элементом, когда его масштабирование по оси x стремится к нулю. Элемент всё больше начинается сплющиваться до тех пор, пока значение не станет нулём. Элемент визуально исчезнет, хотя, на самом деле он продолжит своё существование. Если дать теперь отрицательное значение, то элементу нужно расти, но куда? Правильно — в противоположную сторону. Таким образом мы увидим элемент как если бы находились позади него, или, по-простому, мы отзеркалим элемент по оси x.
При использовании scale
вы так же можете установить произвольную точку трансформации с помощью transform-origin
.
Зачастую в этом нет особого смысла, кроме как в использовании одного из четырёх стандартных значений:
top
right
bottom
left
Что же произойдёт при использовании этих значений? На самом деле всё будет работать так, как и надо — мы просто сменим точку трансформации.
Вернёмся к первому примеру урока:
После применения scale(1.5)
к центральному блоку он немного сменил своё расположение, так как трансформировался от центральной точки элемента. Именно от неё произошло увеличение. Но что делать, если мы хотим увеличить элемент, но оставить верхнюю левую точку там, где она была бы до применения трансформации? Это может быть очень полезно при создании анимации, так как мы уверены в том, где элемент будет находиться.
Именно здесь пригодится свойство transform-origin
. Как было сказано в прошлых уроках, оно может принимать одно или несколько значений:
- Одно значение — установка точки трансформации по оси x.
- Два значения — установка точки трансформации по осям x и y.
Воспользуемся этими значениями и укажем, что центральный блок должен иметь точку трансформации в следующем виде:
- По оси x точка трансформации должна находиться слева
- По оси y точка трансформации должна находиться сверху
Таким образом точкой трансформации станет верхний левый угол, а значит масштабирование будет происходит именно от этой точки, что не даст ей переместиться:
Именно использование свойства transform-origin
позволяет добиться эффекта появления элемента слева направо, как часто бывает при наведении на элемент. Попробуйте в следующем примере навести курсор мыши на иконку подписки.
Scale — Tailwind CSS
Основное использование
Масштабирование элемента масштабировать элемент.
<изображение> <изображение>
Использование отрицательных значений
Чтобы использовать отрицательное значение шкалы, поставьте перед именем класса дефис, чтобы преобразовать его в отрицательное значение.
Удаление преобразований
Чтобы удалить сразу все преобразования элемента, используйте утилиту transform-none
:
Это может быть полезно, если вы хотите удалить преобразования по условию, например, при наведении или в определенной точке останова.
Аппаратное ускорение
Если ваш переход работает лучше при рендеринге с помощью графического процессора, а не центрального процессора, вы можете принудительно использовать аппаратное ускорение, добавив transform-gpu
утилита:
Используйте transform-cpu
для принудительного возврата к ЦП, если вам нужно отменить это условно.
Условное применение
Наведение, фокус и другие состояния
Tailwind позволяет вам условно применять служебные классы в различных состояниях, используя модификаторы вариантов. Например, используйте hover:scale-125
, чтобы применять утилиту scale-125
только при наведении.
<дел>
Полный список всех доступных модификаторов состояния см. в документации Hover, Focus и других состояний.
Точки останова и медиа-запросы
Вы также можете использовать модификаторы вариантов для целевых медиа-запросов, таких как чувствительные точки останова, темный режим, предпочтения с уменьшенным движением и т. д. Например, используйте md:scale-125
, чтобы применить утилиту scale-125
только при средних размерах экрана и выше.
<дел>