Логотип Workflow

Article

Structuring Grouping Reusing

Structuring, Grouping & Reusing

(Структура, группировка и переиспользование)

Чем больше становится ваш SVG-файл, тем сложнее в нем ориентироваться. Если вы рисуете сложную иллюстрацию или создаете систему иконок, просто накидывать <path> друг за другом — плохая идея.

В этом уроке мы разберем принцип DRY (Don't Repeat Yourself) в SVG: как группировать элементы, создавать шаблоны и переиспользовать их, не дублируя код.


1. Тег <g>: Группировка

Тег <g> (group) — это аналог <div> в HTML или «Папки» в графических редакторах. Он не отрисовывает ничего сам по себе, но объединяет вложенные элементы.

Зачем нужен:

  1. Организация кода: Логическое разделение (например, <g id="head">, <g id="arm">).
  2. Массовая трансформация: Можно сдвинуть, повернуть или уменьшить всю группу целиком.
  3. Наследование стилей: Атрибуты, заданные группе (например, fill или stroke), применяются ко всем вложенным элементам (если у них не заданы свои).
<svg width="200" height="200" viewBox="0 0 200 200">
  <!-- Группа "Лицо": все элементы внутри будут красными и сдвинуты -->
  <g id="face" fill="crimson" transform="translate(50, 50)">
    <!-- Глаза (цвет наследуется от группы) -->
    <circle cx="20" cy="20" r="10" />
    <circle cx="80" cy="20" r="10" />
    <!-- Рот (переопределяем цвет на белый) -->
    <rect x="20" y="60" width="60" height="10" fill="white" />
  </g>
</svg>

2. Тег <defs>: Склад ресурсов

<defs> (definitions) — это специальная область для хранения объектов. Всё, что находится внутри <defs>, не отображается на холсте автоматически. Это «склад» шаблонов, градиентов, фильтров или фигур, которые мы планируем использовать позже.

Это основа для оптимизации: вы определяете сложный объект один раз, а потом просто ссылаетесь на него.

<svg width="0" height="0">
  <defs>
    <!-- Этот круг не виден, пока мы его не позовем -->
    <circle id="my-template" cx="10" cy="10" r="10" fill="teal" />
  </defs>
</svg>

3. Тег <use>: Клонирование

Тег <use> достает объект из <defs> (или любого другого места по id) и отрисовывает его копию в нужном месте.

Преимущества:

  • Уменьшение размера файла (код фигуры не дублируется).
  • Единый источник правды (меняете фигуру в <defs> — меняются все копии).
<svg width="300" height="100" viewBox="0 0 300 100">
  <defs>
    <circle id="coin" r="20" fill="gold" stroke="orange" stroke-width="2" />
  </defs>

  <!-- Используем монетку 3 раза в разных местах -->
  <use href="#coin" x="50" y="50" />
  <use href="#coin" x="150" y="50" />
  <!-- Можно добавить трансформацию к копии -->
  <use href="#coin" x="250" y="50" transform="scale(0.8)" />
</svg>

Примечание: В старых примерах кода вы можете встретить xlink:href. В современном SVG достаточно писать просто href.


4. Тег <symbol>: Золотой стандарт иконок

<symbol> — это продвинутая версия группы, созданная специально для переиспользования.

Главные отличия от <g> и <defs>:

  • Как и <defs>, содержимое <symbol> не отображается само по себе.
  • Киллер-фича: У <symbol> есть свой собственный атрибут viewBox.

Это позволяет создавать SVG-спрайты (системы иконок). Неважно, как нарисована иконка внутри символа, вы можете вставить её через <use> и задать ей любые размеры (width и height), и она идеально впишется благодаря своему viewBox.

Пример SVG-спрайта

<svg style="display: none;">
  <!-- Определение иконки "Дом" -->
  <symbol id="icon-home" viewBox="0 0 24 24">
    <path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z"/>
  </symbol>

  <!-- Определение иконки "Настройки" -->
  <symbol id="icon-settings" viewBox="0 0 24 24">
    <path d="M19.14 12.94c.04-.3.06-.61.06-.94... (длинный путь) ..."/>
  </symbol>
</svg>

Использование на странице

<!-- Большая иконка дома -->
<svg class="icon"><use href="#icon-home" width="50" height="50"/></svg>

<!-- Маленькая иконка настроек -->
<svg class="icon"><use href="#icon-settings" width="20" height="20"/></svg>

5. Shadow DOM и проблемы со стилизацией

Когда вы используете <use>, браузер создает Shadow DOM (Теневую модель документа). Это означает, что копия элемента изолирована от остальной страницы.

Проблема:

Вы не можете через CSS обратиться к внутренностям клона.

Например, такой CSS не сработает для изменения цвета пути внутри <use>:

/* Не сработает */
use path {
  fill: blue;
}

Решение 1: Наследование (Inheritance)

Стили, заданные самому тегу <use>, наследуются внутрь Shadow DOM.

Чтобы это работало, внутри исходного символа не должно быть атрибута fill (или он должен быть currentColor).

Исходник:

<symbol id="star" viewBox="0 0 24 24">
  <!-- Убираем fill="black", ставим fill="currentColor" или вообще удаляем -->
  <path d="..." fill="currentColor" /> 
</symbol>

Использование:

<svg class="icon-red"><use href="#star" /></svg>
<svg class="icon-blue"><use href="#star" /></svg>

CSS:

.icon-red { color: red; } /* currentColor возьмет это значение */
.icon-blue { fill: blue; } /* Или так */

Решение 2: CSS Переменные

CSS переменные (Custom Properties) проникают сквозь границу Shadow DOM.

<symbol id="robot">
  <rect fill="var(--main-color, black)" />
</symbol>
svg { --main-color: purple; }

Итог

  • <g> — для группировки частей одного рисунка (двигать вместе, красить вместе).
  • <defs> — для хранения градиентов и масок.
  • <symbol> + <use> — стандарт для иконочных систем. Позволяет управлять viewBox каждой иконки отдельно.
  • Используйте currentColor в путях иконок, чтобы легко перекрашивать их через CSS при использовании <use>.

Quiz

Проверьте, что вы усвоили

Авторизуйтесь чтоб пройти тесты