Иконки — не контент
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")
С помощью спрайта мы уменьшаем количество запросов к серверу, вместо десятков мелких файликов грузим одну стопку из всех иконок, и просто обращаемся к нему, запрашивая у него отдельные фрагментики в нужном месте.