Дайджесты новостей
Макросъёмка дизайн-системы иконок на чистом CSS с трафаретом маски mask-image и палитрой токенов кастомных свойств.

Иконки на чистом CSS: техника Ли Веру с кастомными свойствами и масками

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

Инлайн-SVG? Он раздувает HTML-разметку мегабайтами повторяющихся тегов <path>, засоряет DOM-дерево и не кэшируется браузером. SVG-спрайты? Требуют архаичных конструкций <svg><use href="#icon"/></svg> и создают проблемы с изолированной стилизацией. Иконочные шрифты (icon fonts)? Ломаются при сбое сети и заставляют экранные дикторы для незрячих читать служебные символы Юникода как бессмысленный шум.

Известный исследователь веб-стандартов Ли Веру (Lea Verou) опубликовала программную статью и библиотеку @nudeui/icons, предложив изящную методологию: перенести управление иконочной системой целиком на уровень CSS.

Токены дизайна и маскирование через mask-image

В основе подхода лежит стандартизированное свойство mask-image (уже вошедшее в Baseline всех современных браузеров) в сочетании с токенизацией через CSS Custom Properties.

Вся векторная графика убирается из разметки и объявляется один раз в виде глобальных токенов в блоке :root. Компоненты интерфейса не содержат тегов SVG — иконка формируется псевдоэлементом ::before, цвет которого заливается нативным currentColor, а контур вырезается CSS-маской:

/* 1. Глобальная регистрация иконочных токенов */
:root {
  --icon-trash: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M3 6h18m-2 0v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2'/%3E%3C/svg%3E");
  --icon-edit: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7'/%3E%3C/svg%3E");
}

/* 2. Базовый класс кнопки */
.btn-icon {
  display: inline-flex;
  align-items: center;
  gap: 0.5em;
}

.btn-icon::before {
  content: "";
  display: inline-block;
  width: 1em;
  height: 1em;
  background-color: currentColor;
  -webkit-mask: var(--icon) no-repeat center / contain;
  mask: var(--icon) no-repeat center / contain;
}

/* 3. Назначение конкретной иконки */
.btn-delete {
  --icon: var(--icon-trash);
}

В результате разметка кнопки в HTML выглядит безупречно лаконично:

<!-- Чистый HTML без единого тега SVG внутри кнопки -->
<button class="btn-icon btn-delete">Удалить запись</button>

Масштабирование, темы и Container Style Queries

Что дает этот подход в реальной дизайн-системе?

  1. Автоматическое наследование цвета: иконка залита currentColor. Меняется цвет кнопки при наведении, фокусе или переключении на темную тему — иконка мгновенно принимает тот же оттенок без дополнительных правил.
  2. Пропорциональное масштабирование: размер зафиксирован в относительных единицах 1em. Увеличиваешь шрифт заголовка — иконка гармонично увеличивается вместе с текстом.
  3. Реактивность через Style Queries: используя современные контейнерные запросы стилей (@container style(--variant: warning)), можно динамически подменять иконку внутри карточки в зависимости от темы или состояния родителя без манипуляций с DOM в JavaScript. Тонкости таких стилистических запросов мы изучали в статье Определение перекрытия элементов средствами чистого CSS: якорное позиционирование и Style Queries.

Чек-лист доступности (a11y) при использовании CSS-иконок

  • Кнопки с иконками без видимого текста снабжены атрибутом aria-label="Описание действия"
  • Псевдоэлементы ::before с масками не содержат текста в свойстве content во избежание озвучки скринридерами
  • Проверено визуальное отображение в высококонтрастном режиме Windows High Contrast

Методология Ли Веру наглядно доказывает: возможности современного CSS позволяют убрать из HTML тонны инфраструктурного мусора, вернув верстке былую элегантность.