Как стать автором
Обновить
2752.78
RUVDS.com
VDS/VPS-хостинг. Скидка 15% по коду HABR15

Основные принципы маскирования в CSS

Уровень сложностиСредний
Время на прочтение8 мин
Количество просмотров13K
Автор оригинала: Ahmad Shadeed

В мире дизайна маскирование является популярной техникой реализации уникальных эффектов. Будучи дизайнером, я сам использовал эту технику много раз, но не очень часто в веб-среде. Думаю, что от её применения на сайтах меня удерживала недостаточная поддержка браузерами. Полноценно этот функционал поддерживается в Safari и Firefox, а вот в браузерах на движке Blink (Chrome и Edge) — лишь частично.

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

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

Поехали!

Содержание



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


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

Взгляните на этот рисунок:



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

Принцип заключается в скрытии некоторых частей изображения без их стирания.



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

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



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



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



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

Хорошо, теории хватит. Далее мы разберём способы маскирования в CSS.

Как применять маски в CSS


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

  • свойство mask;
  • свойство clip-path;
  • SVG <mask>.

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

Его можно назвать сокращённым вариантом свойства background, но со своими особенностями.

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

Применение background выглядит так:

.card__thumb {
    background-image: url('hero-cool.png');
}
А применение маски так:
.card__thumb {
    mask-image: url('hero-cool.png');
}




Круто, правда? Такой подход существенно упростит понимание и запоминание масок.

Теперь повторим в CSS наш первый пример.

Для начала нужно экспортировать фигуру в виде изображения png.



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

<img src="ahmad-shadeed-web-directions.jpg" alt="" />

img {
    mask-image: url("shape.png");
}

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



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

img {
    mask-image: url("shape.png");
    mask-repeat: no-repeat;
}



Прекрасно! Заметьте, что маска оказалась в верхнем левом углу. Её положение можно изменить с помощью mask-position. Опять же, обратите внимание, что синтаксис идентичен синтаксису для фоновых изображений.

img {
    mask-image: url("shape.png");
    mask-repeat: no-repeat;
    mask-position: center;
}



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

img {
    mask-image: url("shape.png");
    mask-repeat: no-repeat;
    mask-position: center;
    mask-size: 60%;
}



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

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


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

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

В следующем примере mask-image состоит из линейного градиента, переходящего от чёрного к прозрачному.

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



Из MDN:

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

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

img {
    mask-image: linear-gradient(red, transparent);
}



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

img {
    mask-image: linear-gradient(#000 50%, transparent 0);
}



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

Практические примеры


▍ Затухание изображения


В качестве интересного варианта применения маскирования можно привести затухание изображения при его смешивании с фоновой картинкой.

Взгляните на эту картинку:



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

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

И хотя такой вариант может сработать, при изменении фонового цвета всё нарушится. Обратите внимание, что hero-изображение теперь имеет жёсткий переход:



В качестве альтернативы можно маскировать hero-изображение так, чтобы оно работало с любым цветом фона.

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

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



▍ Маскирование текста: пример 1


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

Возьмём следующий рисунок:



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



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

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

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



Градиент готов. Теперь можно задействовать его в качестве маски:

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

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

▍ Маскирование текста: пример 2


Это тот же пример, но теперь градиент будет вертикальным. Я видел такое в роликах на Instagram.

Взгляните на следующее изображение:



Обратите внимание, что верхняя часть текста размывается. В этой небольшой области могут находиться комментарии к ленте, действия и прочее. Маскирование идеально для этого подойдёт.

Для начала посмотрим на сам градиент.



В CSS это может выглядеть так:

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

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


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

Вот смотрите:



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



Теперь посмотрим на градиентную маску, чтобы понять, как она работает.



В CSS это будет выглядеть так:

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

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


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

Вот простой дизайн, который я сделал для этого демо.



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

Взглянем на градиенты более детально:

.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;
}

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



Для создания эффекта затухания в каждом прямоугольнике маски нужно обновить градиент и добавить ключевое слово 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;
}



▍ Скругление вкладок


Я также подумал о возможном применении масок к функционалу UI под названием «скругление углов» (round out corners).

Наша задача — скруглить стороны элемента так, чтобы они смешались с его border-radius.



В своей статье Крис Койер объяснил, как можно достичь этого эффекта с помощью множества псевдо-элементов. Более же динамичным решением будет использование маски CSS.

Для начала повнимательнее взглянем на фигуру, которую нужно получить.



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

Как этого достичь? Можно использовать многослойные маски, объединив их с помощью свойства mask-composite.

Первым делом мы создадим элемент для хранения самой маски.

.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;
}

Обратите внимание на следующее:
  • в качестве размера квадрата я установил 12px 12px;
  • квадрат расположен в левом нижнем углу (bottom left);
  • для фигуры квадрата background-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;
}

В итоге получится:



Код выше предназначен для фигуры справа. Для второй же стороны можно просто изменить mask-position.

.nav-item.active:after {
    /* другие стили */
    mask-position: bottom right, center;
}

Демо

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


В своей статье (англ.), посвящённой эффекту вырезания, я рассказал о нескольких способах его реализации в CSS.

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



В этом случае можно получить такой эффект с помощью радиального градиента.

.avatar {
    -webkit-mask-image: radial-gradient(ellipse 54px 135px at 11px center, #0000 30px, #000 0);
}



Очень рекомендую ту статью, так как в ней есть много подробных примеров вроде приведённого выше.

Заключение


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

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


Если вы хотите отточить навыки на дополнительных примерах, то рекомендую следующие материалы:


Благодарю за чтение!

Telegram-канал с розыгрышами призов, новостями IT и постами о ретроиграх 🕹️
Теги:
Хабы:
Всего голосов 44: ↑44 и ↓0+44
Комментарии1

Публикации

Информация

Сайт
ruvds.com
Дата регистрации
Дата основания
Численность
11–30 человек
Местоположение
Россия
Представитель
ruvds