Тред про иконки. >>>
Ограничения в задаче: есть базовые иконки, которые используются везде. Есть специфические иконки, которые выполняют одну задачку и их не планируется использовать где-то еще. Есть специфические для платформы.
Сверху добавляем браузерную поддержку и желание, чтобы иконки кешировались, реиспользовались и работали на двух стеках: xslt + mustache, react. Последнее уже наша специфика, но все остальное справедливо для большинства проектов.
Накидываем, прототипируем варианты:
Inline svg. Идея проста: каждую svg вставляем inline в код. fill, stroke убираем и будем стилизовать иконку через css классы.
Чтобы просто было использовать в react пишем свой loader.
Код прототипа для inline варианта (вместе с кастомным webpack loader): gist.github.com/xnimorz/8dfe0c…
Лоадер направляем на .svg иконки.
Выглядит просто и легко, но каждая иконка — это куча тегов в DOM, а значит куча данных, которые используются при SSR, увеличение количества DOM нод.
Вроде бы сам подход удобный, но что-то не хочется.
В защиту решения: можно сделать поддержку многоцветных иконок, анимацию цветовых переходов.
Можем улучшить этот вариант и использовать inline svg + use директиву.
Идея такая: на этапе сборки превращаем все иконки в одну большую мега-иконку, где весь контент описан, например в
<symbol />
теге. Вставляем эту иконку на страницу (она будет не видна для пользователя), а все реальные иконки просто используют тег <use />
Код становится проще, нам уже не обязательно делать кастомный лоадер. Достаточно обычного react-компонента: gist.github.com/xnimorz/543dc8…
Вместо одной большой мега-иконки можно использовать другой подход: в компоненте icon храним singleton-Map, в ней отмечаем, какая иконка была использована.
Если добавляется новая иконка, то вставляем эту иконку через
symbol
, помечаем в singleton и добавляем реальное использование через use
.
Этот подход избавляет нас от необходимости клеить все в одну иконку и делает подгрузку иконок на странице ленивой.Главная проблема подхода: у
<symbol>
должен быть id. А значит мы получаем опасность пересечений, если иконки не сосредоточены в одном месте и мы не берем их id по пути к файлу. То есть мы приходим к глобальной области видимости, от которой так стараемся в том же css уходить.Можно для иконок сделать решение аналогичное подходу css-modules и добавлять хеши например. Но мы начинаем строить космические корабли и переусложнять архитектуру.
Сама идея inline svg + use хороша и для многих проектов может зайти. Этот подход экономит и размер данных, и имеет хорошие возможности кастомизации.
Спрайты. Старые-добрые спрайты. Сама иконка выглядит примерно так: gist.githubusercontent.com/xnimorz/e0f107… Через use задаем состояния иконки и через background-position управляем тем, какую иконку увидит пользователь.
Теряем удобные анимации по сравнению с предыдущими случаями, получаем возможность работать с многоцветными иконками и отсутствуют глобальные имена.
Если вы не поддерживаете "старые" браузеры типа IE11, то можно выбрать хипстерский способ через filter. Работает очень просто, вставляете иконку через background-image одного цвета и фильтрами настраиваете нужный вам цвет.
Здесь есть даже готовый калькулятор таких стилей codepen.io/sosuke/pen/Pjo…
Главные минусы: вас будут не очень сильно любить за стили вида: filter: invert(17%) sepia(32%) saturate(5440%) hue-rotate(344deg) brightness(89%) contrast(93%); Также не работает в старых браузерах и поддержку нескольких цветов настроить будет сложно.
Здесь этот способ описан подробнее: css-tricks.com/solved-with-cs…
Плюсы — удобно, все средствами css.
Можно использовать css mask и затем через background-color задавать цвет. способ крайне простой, и нативно понятный, но с поддержкой все еще хуже caniuse.com/#feat=css-masks. И иконки в этом случае должны быть одноцветные (или градиентные)
Можно сделать свой иконочный шрифт. Про его проблемы не писал разве что ленивый. (отложенная загрузка, разное отображение в разных системах, браузерах и т.д. и т.п.)
Какое бы вы решение выбрали?
🤔
60.6%
inline (c use или без)🤔
22.1%
Спрайты🤔
5.8%
filter или mask🤔
11.5%
Свой вариант