Иконки — не контент
firefoxicБольшинство материалов для новичков об иконках, учат вставлять иконки инлайном в разметку. Об этом полезно знать, потому что в некоторых случаях может пригодиться на практике. Но ещё полезнее умение удалять иконки из разметки.
Ведь что такое иконки? Это всего лишь дополнительная стилизация интерфейсного текста. Ключевое слово — стилизация. Не место им в разметке, они не несут никакой уникальной и важной информации, а всего лишь стилизуют, как и рамка вокруг кнопки. А это значит, что их лучше перенести в стили.
Но чтобы было удобно ими управлять, а также чтобы они нам не мешали стилизовать состояния, лучше их вставлять в фон не самого элемента, а псевдоэлемента того элемента, к которому нужно иконку прикрутить.
Так мы сможем иконку встраивать в любой контекст: инлайновый, блочный, флексовый, гридовый, да хоть флоатом можно прибить их вправо/влево.
План действий
- Если иконки уже заинлайнены, то удаляем их из разметки, убедившись в наличии оригиналов svg в icons/. При отсутствии — снова экспортируем.
- У элемента, в котором должна быть вставлена иконка, создаём псевдоэлемент. Обычно
::before
, потому что обычно иконка нужна перед текстом, даже если текст доступно скрыт. В очень редких случаях иконка нужна после текста, тогда::after
, хотя и в этом случае можно стилями поставить куда угодно. - Задаём псевдику
content: "";
без которого псевдика не будет. - Задаём псевдику нужный
display
вместо дефолтногоinline
(если его родительflex
илиgrid
, то необязательноdisplay
менять, но лучше перестраховаться и задатьblock
). - Задаём псевдику нужные иконке размеры.
- Прописываем путь до иконки с остальными настройками фона.
Пример с сердечком:
.favourite::before { content: ""; display: block; width: 20px; height: 20px; background: ulr("../icons/heart.svg") no-repeat center / contain; }
Перекраска
Теперь встаёт вопрос, как их перекрашивать при разных состояниях, ведь к фону не пробиться свойством fill
.
Тут нам помогут CSS-маски! Принцип их работы как у трафарета, только наоборот:
- всё, что попадает под непрозрачную часть изображения, по которому делаем маску — то видно,
- а что под прозрачной частью — ничего не видно.
Технически же это всё ещё проще — нам просто надо свойство background
заменить на mask
, не меняя ничего в его значении. А затем залить в фон нужный нам цвет. И лучше в виде использования кастомного свойства, унаследованного от самого элемента.
.favourite { --icon-fill: orange; } .favourite::before { content: ""; display: block; width: 20px; height: 20px; mask: ulr("../icons/heart.svg") no-repeat center / contain; background: var(--icon-fill); }
Для перекраски при наведении, просто меняем значение кастомки на элементе,
.favourite:hover { --icon-fill: orangered; }
В Chrome всё ещё требуется префикс -webkit-
для масок. Поэтому нам всё ещё нужен autoprefixer.
Один SVG, чтобы править всеми
Ну и сразу можно сделать следующий шаг — использовать фрагменты собираемого плагином стекового спрайта. При этом пути к иконкам надо поправить.
Примеры замены пути:
-url("../icons/heart.svg") +url("../icons/stack.svg#heart")
Если иконка лежит в поддиректории, то плагин добавляет её префиксом к имени фрагмента, отделяя их по умолчанию подчёркиванием:
-url("../icons/social/telegram.svg") +url("../icons/stack.svg#social_telegram")
С помощью спрайта мы уменьшаем количество запросов к серверу, вместо десятков мелких файликов грузим одну стопку из всех иконок, и просто обращаемся к нему, запрашивая у него отдельные фрагментики в нужном месте.