Маскирование в CSS: когда clip-path уже не вывозит
Присаживайся, коллега. Давай по-честному: сколько раз ты сталкивался с ситуацией, когда дизайнер притаскивает макет, где картинка плавно растворяется в фоне, или, что еще хуже, имеет сложную форму с мягкими краями и полупрозрачностью? Обычным свойством opacity тут не отделаешься, а если фон под картинкой — градиент или другой сложный паттерн, то начинаются настоящие танцы с бубном.
Обычно в такие моменты в голову приходит clip-path. Это крутой инструмент, и мы уже разбирали, как с его помощью делать создание сложных фигур через clip-path. Но у него есть жирный минус: он работает бинарно. Либо пиксель виден, либо нет. Никакой мягкой растушевки или полупрозрачности. И вот тут на сцену выходит mask-image — тяжелая артиллерия для тех, кто хочет делать интерфейсы уровня «Apple».
Как мы страдали раньше
До того как современные браузеры подружились с CSS-масками, жизнь была похожа на средневековую пытку. У нас было три пути, и все они вели в тупик:
- PNG-заплатки: Мы накладывали поверх картинки прозрачный PNG-файл, который имитировал переход в фон. Поменяли цвет фона? Перерисовывай все картинки в Photoshop. Это был ад для поддержки.
- Инлайновый SVG: Мы оборачивали контент в огромные куски SVG-кода с тегами
<mask>или<clippath>. Это раздувало DOM и превращало чтение кода в разгадывание ребусов. - Canvas-хаки: Если нужно было что-то динамическое, подключали JS и рисовали через Canvas. О производительности и доступности в такие моменты старались не думать.
Как делать правильно в 2026 году
Сегодня mask-image — это фактически background-image, только наоборот. Вместо того чтобы рисовать что-то на элементе, маска определяет, какие части элемента будут видны. Самое мощное — это использование градиентов в качестве масок.
Но современный подход идет дальше. Теперь мы используем mask-composite. Это свойство позволяет смешивать несколько масок, используя логические операции: сложение, вычитание, пересечение. Например, ты можешь взять одну маску-градиент и «вычесть» из неё форму иконки. При этом важно не забывать про пропорции контента, используя свойство aspect-ratio, чтобы маска не «поплыла» на разных экранах.
В 2026 году стандарт окончательно устаканился, и мы можем использовать маски без лишних префиксов (хотя для старых Safari -webkit- все еще иногда мелькает в автопрефиксерах, но мы-то смотрим в будущее).
Готовый сниппет кода
Давай соберем карточку с «эффектом растворения», где верхняя часть картинки плавно уходит в прозрачность, а по центру вырезано круглое отверстие. Все это — на чистом CSS.
.cool-card {
width: 300px;
aspect-ratio: 1 / 1;
background: url('hero-image.jpg') center/cover;
/* Определяем две маски: градиент и круг */
--mask-gradient: linear-gradient(to bottom, transparent, black 50%);
--mask-circle: radial-gradient(circle at center, transparent 20%, black 21%);
/* Применяем маски */
mask-image: var(--mask-gradient), var(--mask-circle);
/* Композитинг: оставляем только то, что входит в обе маски (пересечение) */
/* В современном CSS используем ключевые слова стандарта */
mask-composite: intersect;
/* Для совместимости со старым WebKit (Safari/Chrome) */
-webkit-mask-composite: source-in;
transition: mask-image 0.3s ease;
}
.cool-card:hover {
/* Маски можно анимировать! */
--mask-circle: radial-gradient(circle at center, transparent 0%, black 0%);
}
Частая ошибка новичков
Самый частый затык — это непонимание разницы между Alpha Mask и Luminance Mask.
По умолчанию CSS использует mask-mode: alpha. Это значит, что браузер смотрит только на прозрачность твоей маски. Если ты используешь в качестве маски картинку, где есть черный и белый цвета, но нет прозрачности (альфа-канала), то маска… просто не сработает. Весь элемент останется видимым.
Если тебе нужно, чтобы маска работала по яркости (белое — видно, черное — скрыто), нужно явно прописать mask-mode: luminance. Но на практике проще всегда работать с прозрачностью в linear-gradient или PNG/SVG, так меньше шансов выстрелить себе в ногу при кроссбраузерной верстке.
И помни: маски — это про прозрачность, а не про цвет. Не пытайся задать цвет внутри mask-image, он там просто игнорируется.
🔥 Больше фишек, готовых сниппетов и передовых подходов к CSS мы публикуем в нашем Telegram-канале. Подписывайтесь, чтобы не пропустить!