Что такое CSS маски и зачем они нужны

Источник: «CSS Masking»
В мире дизайна маскирование — популярная техника достижения уникальных дизайнерских эффектов. Как дизайнер, я использовал его много раз, но редко использую в Интернете. Думаю, причина, по которой я не использую CSS маски, заключается в поддержке браузеров. Они частично поддерживаются в браузерах blink (Chrome и Edge) и полностью поддерживаются в Safari и Firefox.

Хорошая новость заключается в том, что CSS маскирование будет частью Interop 2023, а это значит, что мы должны ожидать кросс-браузерной поддержки (Ура!!).

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

Что такое маскирование

Проще говоря, маскирование работает таким образом, что скрывает часть элемента, не стирая его.

Рассмотрим следующий рисунок:

Пример использования CSS маски

У нас есть изображение и есть маска. В дизайнерских приложениях, таких как Photoshop, мы можем вставить изображение внутри серой фигуры, и это приведёт к маскированию изображения.

Способ, который работает, заключается в том, что он скрывает некоторые части изображения, не стирая его (они всё ещё там, но скрыты).

Видимая и невидимая части изображения с CSS маской

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

Например, мы можем создать градиентную маску, как показано ниже.

Создание градиентной CSS маски

В градиенте есть заполненные и прозрачные пиксели. Заполненные — там, где будет видна часть элемента, а прозрачные — там, где скрытые части.

Создание градиентной маски в графическом редакторе

В Photoshop мы можем добавить маску слоя к группе слоёв, и содержимое этой группы будет замаскировано внутри неё. Этот способ работает с помощью инструмента Кисть, чтобы скрыть часть группы, и она будет замаскирована.

Маска слоя в Adobe Photoshop

Содержимое, которое замаскировано, не стирается, оно просто скрывается (обратите внимание на элементы группы).

Ладно, хватит теории. В следующих разделах я рассмотрю способы маскирования CSS.

Как маскировать в CSS

В CSS есть несколько способов маскировать элементы:

Основное различие между свойством mask и clip-path заключается в том, что первое используется для изображений и градиентов, а второе для путей. В этой статье основное внимание будет уделено свойству mask.

В CSS у нас есть сокращённое свойство mask, аналогичная свойству background. Да, вы правильно прочитали. Вот почему я думаю, что синтаксис легко запомнить, потому что он буквально такой же, как свойство background, но с несколькими дополнительными свойствами.

Вместо того чтобы перечислять все свойства CSS маски, я приведу пример, в котором функции маски постепенно будут расширяться, чтобы вы могли заметить разницу.

CSS background выглядит так:

.card__thumb {
background-image: url('hero-cool.png');
}

… а CSS mask выглядит так:

.card__thumb {
mask-image: url('hero-cool.png');
}

Это круто, правда? Это значительно облегчит понимание и запоминание CSS масок.

Давайте переделаем первоначальный пример с помощью CSS.

Во-первых, мне нужно экспортировать фигуру как png изображение.

Создание изображения для CSS маски

Предположим, я хочу применить маску к изображению.

<img src="ahmad-shadeed-web-directions.jpg" alt="" />
img {
mask-image: url("shape.png");
}

Можете ли вы ожидать такой результат? По умолчанию маска будет повторяться, а её размер будет равен самому изображению маски. В настоящее время результат выглядит следующим образом:

CSS маска по умолчанию. Маска повторяется, а размер равен самому изображению маски

Чтобы изменить это, нужно установить mask-repeat в no-repeat, как и фоновые изображения CSS.

img {
mask-image: url("shape.png");
mask-repeat: no-repeat;
}
CSS маска по умолчанию. Маска не повторяется, а размер равен самому изображению маски

Потрясающе! Обратите внимание, что маска расположена в левом верхнем углу. Мы можем изменить это с помощью mask-position. Обратите внимание, синтаксис идентичен background-images!

img {
mask-image: url("shape.png");
mask-repeat: no-repeat;
mask-position: center;
}
CSS маска по умолчанию. Маска не повторяется, размер равен самому изображению маски, позиционируется по центру изображения.

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

img {
mask-image: url("shape.png");
mask-repeat: no-repeat;
mask-position: center;
mask-size: 60%;
}
CSS маска по умолчанию. Маска не повторяется, размер равен самому изображению маски, позиционируется по центру изображения. Размер маски 60%

Есть ещё несколько свойств маски, но я не хочу перегружать вас ими сейчас. Мы вернёмся к ним позже, с реальными вариантами использования.

Маскирование с помощью CSS градиентов

CSS маскирование — это не только использование изображения, также можно использовать градиенты для создания мощных и полезных эффектов маскирования.

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

В следующем примере mas-image содержит линейный CSS градиент от полностью чёрного до прозрачного.

img {
mask-image: linear-gradient(#000, transparent);
}
CSS маска с линейным градиентом от полностью чёрного до прозрачного

Согласно MDN

По умолчанию это означает, что альфа-канал изображения маски будет умножен на альфа-канал элемента. Это можно контролировать с помощью свойства mask-mode.

Это означает, что вы можете использовать любой цвет кроме чёрного, и маска всё равно будет работать, потому что режим маскирования по умолчанию установлена на alpha (позже мы рассмотрим это подробнее).

img {
mask-image: linear-gradient(red, transparent);
}
CSS маска с линейным градиентом от красного до прозрачного

Опять, концепция маскировки заключается в том, что прозрачный пиксель будет скрыт. Вот упрощённый пример градиента с жёсткими цветовыми стоп точками:

img {
mask-image: linear-gradient(#000 50%, transparent 0);
}
CSS маска с линейным градиентом с жёсткими цветовыми стоп точками

Круто! Теперь, когда основные концепции маскирования ясны (надеюсь, на это), давайте рассмотрим несколько практических вариантов использования CSS масок.

Практические варианты использования и примеры

Исчезновение изображения

Интересное использование маскирования — это когда мы хотим затемнить изображение и заставить его сливаться с фоном под ним.

Рассмотрим следующее изображение:

CSS маска с линейным градиентом

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

.hero__thumb:after {
position: absolute;
inset: 0;
background: linear-gradient(to top, #f1f1f1, transparent)
}

Хотя это может работать, это не сработает при изменении основного цвета фона. Обратите внимание, что у главного изображения теперь жёсткие цветовые стоп точки:

CSS маска с линейным градиентом с жёсткими цветовыми стоп точками

С помощью CSS маскирования можно замаскировать главное изображение и заставить его работать с любым цветом фона.

.hero__thumb {
mask-image: linear-gradient(#000, transparent);
}

Вот и всё! Теперь эффект затухания реален и не подведёт при изменении фона главной страницы. Смотри следующий пример:

CSS маска с линейным градиентом с жёсткими цветовыми стоп точками

Маскирование текстового содержимого: Пример 1

Когда мы хотим отобразить длинный текст, но места недостаточно, чтобы отобразить его полностью, решением будет затухание текста как в начале, таки в конце. Затем текст будет анимироваться в любом направлении, чтобы показать оставшееся содержимое.

Рассмотрим следующий рисунок:

CSS маска затухающий текст

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

CSS маска затухающий текст с фоновым изображением

Чтобы реализовать это в CSS, нужно добавить маску градиента, затемняющую содержимое в начале и в конце.

Мне нравиться сначала делать в CSS градиенте и видеть результат, а затем применять его как маску. Это помогает визуализировать градиент перед использованием его в качестве маски.

.c-card__footer {
background-image: linear-gradient(90deg, transparent, #000 15%, #000 85%, transparent 100%);
}
CSS маска. Градиент и CSS маска с градиентом в действии

Имея на руках всё выше перечисленное, мы можем применить его как маску.

.c-card__footer {
mask-image: linear-gradient(90deg, transparent, #000 15%, #000 85%, transparent 100%);
}

Всё ещё не идеально? Мы можем возиться со значениями градиента, пока результат не станет идеальным.

Маскирование текстового содержимого: Пример 2

Это то же самое, что и предыдущий пример, но применяется вертикально. Я видел это в live video в Instagram.

Рассмотрим следующее изображение:

CSS маска. Вертикальная градиентная маска

Заметили как контент размывается вверху? В этом маленьком месте могут быть комментарии ленты, экшены и другие вещи. Использование CSS маски идеально подходит для этого.

Во-первых, давайте посмотрим на градиент.

CSS маска с вертикальным градиентом в действии

В CSS это может быть реализовано примерно так:

.whatever-the-class-name {
mask-image: linear-gradient(to bottom, transparent, #000);
}

Маскирование списков

Я видел этот классный пример Скотта Толински, когда проводил исследование CSS масок. Идея в том, что у нас есть список возможностей, уроков или чего-то ещё. Мы хотим скрывать текст, чтобы больше заинтересовать пользователя тем, что там находится.

Рассмотрим следующий пример:

CSS маска с вертикальным градиентом и списком

Как вы видите слева, у нас есть список, а в самом низу он затемнён. Использование CSS маскирования для этого подходит идеально, так как оно может сливаться с нижним фоном, будь то изображение или тёмный фон.

CSS маска с вертикальным градиентом и списком с тёмным фоном

Давайте посмотрим на градиент маски, чтобы понять, как он работает.

CSS маска. Градиент и маска с градиентом в действии

В CSS это выглядит так:

.list {
mask-image: linear-gradient(to bottom, #000, transparent 95%);
}

Интересные эффекты изображения

С CSS масками и градиентами возможности создания визуальных эффектов безграничны. Это простой пример того, как мы можем создать визуальный эффект для изображения.

Этот быстрый дизайн я сделал для этой демонстрации.

Макет для демонстрации эффектов CSS маски и градиента

Эффект изображения, который вы видите, состоит из пяти линейных градиентов. Добавляя разные позиции для каждой из них, мы можем сделать что-то похожее.

Рассмотрим градиент по ближе:

.thumb {
mask-image: linear-gradient(to bottom, #000, #000),
linear-gradient(to bottom, #000, #000),
linear-gradient(to bottom, #000, #000),
linear-gradient(to bottom, #000, #000),
linear-gradient(to bottom, #000, #000);
mask-size: 18% 70%;
mask-position: 0 100%, 25% 25%, 50% 50%, 75% 0, 100% 50%;
mask-repeat: no-repeat;
}

Визуально маска выглядит так:

Интересные эффекты изображения. Градиент и CSS Маска

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

.thumb {
mask-image: linear-gradient(to bottom, transparent, #000),
linear-gradient(to bottom, #000, transparent),
linear-gradient(to bottom, transparent, #000),
linear-gradient(to bottom, #000, transparent),
linear-gradient(to bottom, transparent, #000);
mask-size: 18% 70%;
mask-position: 0 100%, 25% 25%, 50% 50%, 75% 0, 100% 50%;
mask-repeat: no-repeat;
}
Интересные эффекты изображения. Затухающий градиент и CSS Маска

Также можно анимировать размер или позицию маски при наведении курсора.

Это мощно. Представьте, что вы сочетаете это с анимацией на основе прокрутки страницы. Ситуация может выйти из-под контроля (в хорошем смысле).

Закруглённые вкладки

Я подумал о том, чтобы попробовать CSS маски для улучшения пользовательского интерфейса под названием Закругление углов

Идея состоит в том, что мы хотим закруглить стороны элемента таким образом, чтобы он сочетался с border-radius, которые есть у элемента.

Закруглённые вкладки

В статье Chris Coyier объяснил, как добиться этого с помощью нескольких псевдо элементов. Более динамичным решением было бы использование CSS маски.

Давайте рассмотрим форму, которую я хочу получить.

Закруглённые вкладки

Фигура состоит из квадрата и круга. Нам нужно их пересечение.

Как этого добиться? Мы можем использовать многослойные маски вместе со свойством mask-composition для выполнения над ними операции компоновки.

Сначала, нужно создать элемент для хранения маски.

.nav-item.active:before {
content: "";
position: absolute;
left: 100%;
bottom: 0;
width: 24px;
height: 24px;
background-color: var(--active-bg);
}
Закруглённые вкладки. Псевдоэлемент для хранения скругления

В этом пространстве нужно нарисовать круг и квадрат, чтобы скомпоновать их. К счастью, мы можем сделать это, смешав линейный и радиальный градиенты.

.nav-item.active:before {
content: "";
position: absolute;
left: 100%;
bottom: 0;
width: 24px;
height: 24px;
background-color: var(--active-bg);
background-image: linear-gradient(to top, #000, #000),
radial-gradient(circle 15px at center, #000 80%, transparent 81%);
background-size: 12px 12px, 100%;
background-position: bottom left, center;
background-repeat: no-repeat, repeat;
}

Обратите внимание на следующее:

Закруглённые вкладки. Пример как будут выглядеть два градиента

Данное изображение приведено для визуальной демонстрации того, как будут выглядеть два градиента. Следующий шаг — сделать их! В CSS маскировании мы можем использовать свойство mask-composite для объединения двух фигур.

.nav-item.active:before {
content: "";
position: absolute;
left: 100%;
bottom: 0;
width: 24px;
height: 24px;
background-color: var(--active-bg);
mask-image: linear-gradient(to top, red, red),
radial-gradient(circle 15px at center, green 80%, transparent 81%);
mask-size: 12px 12px, 100%;
mask-position: bottom left, center;
mask-repeat: no-repeat, repeat;
mask-composite: subtract;
}

Вот результат вышеизложенного:

Закруглённые вкладки. Результат компоновки фигур

Выше был CSS код для фигуры справа от вкладки. Для другой стороны мы можем просто изменить mask-position, и она перевернётся.

.nav-item.active:after {
/* other styles */
mask-position: bottom right, center;
}

Готовый пример на CodePen:

See the Pen

Вырезание нескольких аватаров

В своей статье об эффекте вырезания я исследовал различные способы создания выреза в CSS.

Один из примеров хорош для CSS маскирования.

Вырезание аватара. Пример.

С CSS маскированием мы можем использовать радиальный градиент для достижения этого эффекта.

.avatar {
-webkit-mask-image: radial-gradient(ellipse 54px 135px at 11px center, #0000 30px, #000 0);
}
Вырезание аватара.

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

Заключение

Когда я начал больше изучать маскирование в CSS, ресурсы были ограничены. Что ещё более важно, было очень мало практических вариантов использования, которые мы могли бы использовать в нашем повседневном рабочем процессе. Я надеюсь, что к концу этой статьи у вас появится представление о том, где использовать CSS маскирование в вашем следующем проекте.

Я не стал углубляться в свойства типа mask-mode, потому что, честно говоря, не нашёл проблем для решения с ними (до сих пор). Я обновлю статью, когда у меня будет убедительный пример использования такого свойства.

Дополнительные ресурс

Если вы хотите отточить свои навыки в ещё большем количестве примеров CSS маскирования, вам необходимо взглянуть на следующее:

Дополнительные материалы

Предыдущая Статья

Laravel: Руководство по тестированию с Pest

Следующая Статья

Ошибка Nginx 502 Bad Gateway - Причины и решения