DevGang
Авторизоваться

Использование CSS-масок для создания зубчатых краев

Я работал над проектом, который имел этот аккуратный зазубренный край вдоль нижней части изображения баннера.

Выглядит остро... во многих отношениях
Выглядит остро... во многих отношениях

Это то, что заставило меня задуматься на секунду и я кое-что узнал в процессе! Я решил написать, как я пришел к этому, чтобы вы могли использовать мой опыт в своих собственных проектах.

Я начал со старого доброго HTML-изображения в элементе оболочки:

<div class="jagged-wrapper">
  <img src="path-to-image.jpg" />
</div>

Затем я использовал псевдоэлемент ::after, чтобы добавить на него повторяющееся фоновое изображение:  

.jagged-wrapper::after {
  content: "";
  background-image: url('data:image/svg+xml;utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1 1" preserveAspectRatio="none"><polygon style="fill:white;" points="1,0 1,1 0,1 "/></svg>');
  background-size: 30px 30px;
  width: 100%;
  height: 30px;
  position: absolute;
  bottom: 0px;
  right: 0;
  z-index: 2;
}

Это код SVG, преобразованный в URI данных.

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1 1" preserveAspectRatio="none">
  <polygon style="fill: white;" points="1,0 1,1 0,1 "/>
</svg>

"Вот и оно!"

Хотя это конечно работает, но доставляет много хлопот. Трудно читать разметку SVG в CSS таким образом. Кроме того, раздражает необходимость не забывать цитировать их (например, url('data:image/svg+xml'...)). Конечно, мы можем кодировать SVG на base64, чтобы избежать этого, но это еще более раздражает. Кроме того SVG должен быть заполнен тем же цветом фона, что и изображение (или где бы оно ни использовалось), иначе он не будет работать.

Подождите, а разве не для этого нужна маскировка? Да! Да, именно для этого и существует маскировка.

Это привело меня к новому подходу: использовать изображение, подобное приведенному выше, в качестве CSS-маски, чтобы “отсутствующие " биты изображения баннера, действительно отсутствовали. Вместо того, чтобы рисовать треугольники цвета фона поверх баннера, мы должны полностью замаскировать эти треугольники от баннера и пропустить реальный фон. Таким образом это работает на любом фоне!

Маскирование в значительной степени поддерживается везде - по крайней мере, простым способом, о котором я говорю здесь. Мы также говорим о чем-то, что может быть реализовано с прогрессивным улучшением. Если маски не поддерживаются в данном браузере, то вы просто не получите "пилообразный" эффект.

Эти данные поддержки браузера&nbsp;взяты&nbsp;из&nbsp;Caniuse, в которых есть более подробная информация.&nbsp;Число указывает, что браузер поддерживает функцию в этой версии и выше&nbsp;&nbsp;
Эти данные поддержки браузера взяты из Caniuse, в которых есть более подробная информация. Число указывает, что браузер поддерживает функцию в этой версии и выше  

Одним из способов работы маски CSS является предоставление изображения с альфа-каналом в виде mask-image. Базовый элемент, маскируемый, становится полупрозрачным в той степени, в которой mask-image диктует альфа-канал. Таким образом, если изображение маски представляет собой белый чайник на прозрачном фоне, маскированный элемент будет обрезан по форме чайника, и все, что снаружи, будет скрыто.  

Нам нужно одно "пилообразное" изображение, похожее на SVG выше, где верхняя левая половина заполнена белым, а нижняя левая половина полупрозрачной. В идеале это изображение не было бы настоящим SVG, поскольку это вернуло бы нас в ужасный беспорядок URI данных, в котором мы были прежде.

В этот момент вы можете подумать: "Эй, просто вставьте SVG непосредственно в CSS, определите маску в нем, а затем укажите CSS на идентификатор маски в SVG!"

Хорошая идея! И это безусловно выполнимо, если вы можете редактировать HTML. Однако для моего конкретного проекта я работал в WordPress и я действительно хотел ограничить свои изменения чистым CSS, а не вставлять дополнительные части в HTML. Это было бы намного больше работы. Я не думаю что это необычно, для такого изменения презентации полезно не редактировать HTML. Мы в основном придерживаемся идеи избегать семантически бесполезных элементов-обёрток только для того, чтобы обеспечить привязки к стилю, но я чувствую, что это также относится к добавлению всей разметки SVG к документу или даже шаблону WordPress.

Вместо этого мы можем использовать линейный градиент CSS, чтобы создать форму треугольника:  

.el {
  linear-gradient(
    to bottom right,
    white,
    white 50%,
    transparent 50%,
    transparent
  );
}

Вот оно на радиальном фоне, так что вы можете видеть что он действительно прозрачный:

Отлично! Мы можем просто использовать это как mask-image на нашем баннере? Нужно установить mask-size, что как background-size, и mask-repeat, как background-repeat и готово?

К сожалению нет. Не так хорошо, как хотелось бы.

Первая причина в том, что, если вы не используете Firefox, вы скорее всего не увидите никакой маскировки в этом примере выше. Это связано с тем, что Blink и WebKit все еще поддерживают маскирование только с префиксом поставщика, на момент написания. Это означает, что нам нужны префиксные -webkit- версии. 

Помимо префиксов поставщиков, то что мы делаем, также концептуально неправильно. Если мы ограничим маску только нижней полосой изображения mask-size, то у остальной части изображения вообще не будет mask-image, что полностью ее маскирует. В результате мы не можем использовать "пилообраз" в качестве маски. Нам нужен прямоугольник mask-image размером с изображение, с "пилообразным" концом внизу. 

Что-то вроде этого:

Мы делаем это с двумя градиентными изображениями. Первое изображение - это тот же "пилообразный" треугольник что и выше, который установлен repeat-x и расположен bottom так, что повторяется только вдоль нижнего края изображения. Второе изображение - это еще один градиент, прозрачный для нижних 30 пикселей (чтобы не мешать "пилообразному"), непрозрачный над этим (который в демонстрации показан переходом от черного к белому) и занимающий весь размер элемента. 

Итак, теперь у нас есть этот клинообразный кусок с одним треугольным "пилообразным" дном в нижней части и он занимает всю высоту нашего изображения баннера двумя отдельными частями. Наконец, мы можем использовать эти фрагменты mask-image, повторяя их горизонтально на нашем изображении и это должно иметь желаемый эффект:  

И вот оно у нас!

Источник:

#CSS #HTML
Комментарии
Чтобы оставить комментарий, необходимо авторизоваться

Присоединяйся в тусовку

Поделитесь своим опытом, расскажите о новом инструменте, библиотеке или фреймворке. Для этого не обязательно становится постоянным автором.

Попробовать

Оплатив хостинг 25$ в подарок вы получите 100$ на счет

Получить