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

В первой части этого руководства мы разобрали, как создать собственный иконочный шрифт и использовать его в Angular проекте. Это позволило нам сгенерировать новый шрифт из SVG файлов и настроить автоматический процесс его обновления.

Недостатки иконочных шрифтов

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

Иконочные шрифты — лучшие!

Их очень легко сгенерировать, использовать и кастомизировать. Они имеют широкую поддержку в браузерах, а код выглядит максимально чистым. Лично для меня это всегда первый выбор. Но, как и всё в этом мире, они — не идеальны и самое разочаровывающая часть — они не поддерживают более одного цвета.

Так как они основаны на OpenType / TrueType, они поддерживают только монохромные глифы — по сути, фигура, залитая одним цветом. А браузер применяет свойство color из CSS ко всему глифу целиком.

Если же у вас стоит задача использовать многоцветные иконки, есть два варианта:

  • использовать более продвинутые форматы, например OpenType-SVG или COLR/CPAL, но их поддержка в браузерах пока ограничена;

  • или воспользоваться «двухцветными иконками» (Duotone icons) — подход, который применяет Font Awesome, позволяющий поддерживать два цвета и управлять ими через CSS.


Двухцветные иконки

Двухцветные иконки Font Awesome
Двухцветные иконки Font Awesome

Такое решение — это тот же самый шрифт с иконками, но каждый глиф содержит не одну, а две фигуры, объединённые в одну иконку. Таким образом, вы можете менять font-size и color через псевдоэлементы: before и after, как вы обычно это делаете с одним псевдоэлементом before.

.fa-duotone {    
    font-family: "Font Awesome 6 Duotone";
}
.fa-house::before {
    content: "\f015";
}
.fa-duotone.fa-house::after {
    content: "\f015\f015";
}

Это довольно простая идея, которая выглядит отлично!

Так как я не нашёл сторонних библиотек, которые поддерживают это «из коробки», если вы захотите использовать такой подход, придётся делать всё вручную:

  1. разделить каждую иконку на 2 фигуры;

  2. сгенерировать новый иконочный шрифт из SVG файлов;

  3. модифицировать CSS-стили, чтобы объединить две фигуры в одну иконку с помощью псевдоэлементов.

Это не самое удобное решение, так как оно занимает много времени, и именно поэтому я предлагаю обратить внимание на SVG-спрайты.


SVG-спрайты

Идея использовать один общий спрайт для объединения небольших графических элементов, таких как иконки, не нова. Я помню, лет 15 назад фронтенд-разработчики использовали спрайты для тех же целей, но в другом формате — это было PNG изображение, которое содержало множество мелких графических элементов, и позже их можно было показать в проекте, используя свойство background-position.

Плюс очевиден — пользователю нужно загрузить только один файл вместо множества, что могло значительно ускорить загрузку. Минус — всё приходилось делать вручную:

  • иметь отдельный PSD-файл с иконками;

  • добавлять / перемещать / удалять иконки вручную;

  • показывать изображения только как фоновые, а не через тег <img>;

  • запоминать и вручную указывать позицию каждой иконки в файле.

Исходный код SVG-спрайта
Исходный код SVG-спрайта

С SVG-спрайтом вам не нужно делать ничего из этого! Подход тот же: один файл, много иконок и никаких недостатков. Каждая иконка добавляется в виде тега <symbol> с определённым свойством id, которое затем можно использовать где угодно с помощью тега <use>. И поскольку существует множество сторонних библиотек, которые могут с этим работать, вы можете автоматизировать весь процесс.

И, кстати, я забыл упомянуть: никаких ограничений по цвету или размеру — вы можете использовать любые иконки, какие захотите. Звучит здорово, не так ли?


Структура папок

Чтобы правильно организовать исходные изображения и готовые SVG-спрайты, вам нужно создать две дополнительные папки — icons-sprite и sprites — в /src/assets/.

После этого ваша структура будет выглядеть так:

/src
  /assets
    /fonts
    /icons
    /icons-sprite
    /sprites
  /styles
    /_
    /common
    /components
    /forms
      ├── _btn.scss
    /mixins
    /variables
      ├── _bootstrap.scss
      ├── _palette.scss
      ├── variables.scss
    /vendor
    ├── app.scss
    ├── vendor.scss
  styles.scss

Подготовка изображений

SVG файлы с иконками
SVG файлы с иконками

Никакой специальной подготовки изображений не требуется. Вам просто нужно поместить все исходные SVG иконки в папку /icons-sprite. Эти изображения должны иметь размер и цвет, которые вам нужны в проекте, так как изменять эти параметры позже будет гораздо сложнее.


Пакет Svg2sprite-cli 

Существует несколько отличных сторонних библиотек, которые можно использовать для генерации SVG-спрайта из SVG файлов, но я уже давно использую эту и могу её рекомендовать — Svg2sprite. Так как это CLI-интерфейс соответствующей библиотеки, его нужно установить глобально.

npm i -g svg2sprite-cli

После этого добавьте следующую команду в файл package.json, чтобы можно было сгенерировать SVG-спрайт:

...
"icon:sprite": "svg2sprite ./src/assets/icons-sprite ./src/assets/sprites/icons.svg"
...

Вот и всё!

Теперь, когда вы запускаете команду yarn icon:sprite, она возьмёт все SVG файлы из папки /icons-sprite и создаст спрайт icons.svg.


Пакет Ng-svg-icon-sprite 

Последний шаг — подключить пакет ng-svg-icon-sprite в проекте. Он используется для отображения выбранной иконки из созданного спрайта.

yarn add ng-svg-icon-sprite --dev

Затем добавьте импорт в файл app.config.ts:

import { IconSpriteModule } from 'ng-svg-icon-sprite';

...

@NgModule({
    ...
    providers: [
        importProvidersFrom(
            IconSpriteModule.forRoot({ path: 'assets/sprites/icons.svg' })
        ),
    },
    ...
})

Таким образом, мы задаём единый путь для всех иконок, и вы сможете использовать их в любом месте. Конечно, нужно импортировать этот модуль и в сам компонент:

import { Component } from '@angular/core';
import { IconSpriteModule } from 'ng-svg-icon-sprite';

@Component({
    selector: 'app-hero',
    imports: [IconSpriteModule],
    templateUrl: './hero.component.html',
    styleUrl: './hero.component.scss',
})
export class HeroComponent {}
<svg-icon-sprite [src]="'purchase-done'"></svg-icon-sprite>

Для любых дополнительных параметров, которые можно использовать, пожалуйста, обратитесь к официальной документации.

И в самом конце нужно добавить папку sprites в assets проекта. В файле angular.json внесите изменения начиная с 29-й строки:

    ...
    "assets": [
      "src/assets/fonts/",
      "src/assets/sprites/",
      {
        "glob": "**/*",
        "input": "public"
      }
    ],
    ...

Заключение

Сегодня мы рассмотрели, как создать SVG-спрайт из SVG иконок и интегрировать его в Angular проект. В итоге у вас есть:

  • дополненная структура папок для организации исходных файлов иконок и итогового SVG-спрайта;

  • два дополнительных пакета: Svg2sprite-cli (установлен глобально) и Ng-svg-icon-sprite (добавлен локально в проект);

  • дополнительная команда icon:sprite в package.json, которая генерирует для вас SVG-спрайт.

В следующих статьях мы разберём основные принципы разработки адаптивного дизайна. Следите за обновлениями!

Комментарии (0)