Иконочный шрифт, SVG-спрайт или inline SVG: что выбрать для сайта

Для большинства сайтов лучший выбор — SVG: спрайт из элементов <symbol>, если иконок много и они повторяются на разных страницах, или inline SVG, если их немного или нужны анимация и несколько цветов. Иконочный шрифт уступает обоим вариантам в доступности и чёткости, поэтому сегодня его оставляют в основном в старых проектах. Ниже — как работает каждый способ и где у него слабые места.

Как работают три способа

Иконочный шрифт

Каждая иконка — символ шрифта, обычно из области Юникода для частного использования (Private Use Area). Шрифт подключают через @font-face, а иконку выводят псевдоэлементом:

@font-face {
  font-family: "icons";
  src: url("/fonts/icons.woff2") format("woff2");
  font-display: block;
}
.icon-cart::before { font-family: "icons"; content: "\e001"; }

Цвет и размер задаются как у текста — свойствами color и font-size. Собрать такой шрифт из своих SVG можно генератором иконочного шрифта: на выходе получится woff2 и готовый CSS.

SVG-спрайт

Все иконки лежат в одном файле, каждая — внутри <symbol> со своим id. На странице иконку подключают ссылкой через <use>:

<svg class="icon" width="24" height="24" aria-hidden="true">
  <use href="/sprite.svg#cart"></use>
</svg>

Файл спрайта кэшируется браузером, а currentColor внутри символов берёт цвет у <svg> на странице. Внешний спрайт должен лежать на том же домене, что и сайт: загрузку для <use> с чужого домена браузеры блокируют даже при настроенном CORS. Собрать спрайт из набора файлов поможет генератор SVG-спрайтов.

Inline SVG

Код иконки вставляется прямо в HTML. Дополнительных запросов нет, и каждый элемент доступен для CSS: можно анимировать отдельные линии и красить части в разные цвета. Минус — код повторяется при каждом использовании и не кэшируется отдельно от страницы. В компонентных фреймворках это почти незаметно: иконка живёт в компоненте, а сжатие gzip или Brotli хорошо справляется с повторами. На страницах векторных иконок freeicons есть кнопка «Копировать как React».

Доступность

Здесь у шрифтов главная проблема. Скринридер может попытаться прочитать символ из области частного использования или сгенерированный CSS-контент, и пользователь услышит бессмыслицу или ничего. Если шрифт не загрузился или посетитель запретил сайтам менять шрифты — такая настройка есть, например, в Firefox, — вместо иконок появятся пустые квадраты или случайные символы.

С SVG правила проще:

  • декоративная иконка рядом с текстом — aria-hidden="true", действие объяснит сам текст;
  • кнопка только с иконкой — подпись на самой кнопке: <button aria-label="Удалить">;
  • самостоятельная смысловая картинка — role="img" и aria-label у <svg>.

Со шрифтом можно добиться того же: aria-hidden на иконке и визуально скрытый текст рядом. Но об этом чаще забывают, а ошибку не видно глазами.

Скорость загрузки

  • Шрифт — один файл, который загружается целиком, даже если на странице две иконки из двухсот. Пока он грузится, иконок нет: font-display: block на это время прячет символы, иначе на их месте мелькнут квадраты или буквы запасного шрифта.
  • Спрайт — тоже один кэшируемый файл. Собирайте его под проект, без неиспользуемых символов.
  • Inline SVG появляется сразу вместе с HTML, но увеличивает размер страницы: для десятка иконок это оправдано, для сотен повторов в каталоге — уже нет.

Для всех SVG-вариантов оптимизируйте исходники через SVGO: удаление метаданных и лишней точности координат уменьшает и спрайт, и HTML.

Качество отрисовки

Шрифт рисуется как текст: к нему применяются сглаживание и хинтинг, а положение зависит от line-height и метрик шрифта. Отсюда размытые края, иконки, смещённые на пиксель относительно текста, и разная толщина линий в разных браузерах и системах. SVG рисуется как геометрия: иконка, построенная на сетке 24×24, в 24 px выглядит так, как задумал дизайнер.

Ещё одно ограничение — цвет. Символ шрифта окрашивается целиком в один цвет, а SVG может сочетать несколько: основной через currentColor и дополнительные через CSS-переменные. Подробнее — в статье о способах изменить цвет SVG.

Сравнение

КритерийИконочный шрифтSVG-спрайтInline SVG
Доступностьнужны обходные приёмыхорошаяхорошая
Чёткостькак у текста, возможна размытостьвысокаявысокая
Цветодин, через colorcurrentColor и переменныелюбой, вплоть до отдельных частей
Кэшированиедада, если файл внешнийнет, в составе HTML
Когда видна иконкапосле загрузки шрифтапосле загрузки спрайтасразу с HTML
Анимация частейнетограниченаполная

Что выбрать

  1. Сайт с десятками иконок на многих страницах — внешний SVG-спрайт.
  2. Приложение на React, Vue или Svelte — inline SVG в компонентах.
  3. Лендинг с несколькими иконками — inline SVG прямо в разметке.
  4. Старый проект на иконочном шрифте — переписывать всё сразу не обязательно: добавьте aria-hidden и текстовые подписи, а новые иконки подключайте через SVG.

Для старта удобно взять иконки интерфейса в линейном стиле: они построены на сетке 24×24 и окрашиваются через currentColor.

Итог

Иконочные шрифты решали задачи тех лет, когда SVG поддерживался плохо. Сегодня спрайт и inline SVG дают лучшую доступность, чёткость и контроль над цветом при сопоставимой скорости, а шрифт разумно оставить только для поддержки старого кода.