Основы SVG — Примеры

Пример 1 — Иконка, которая не масштабируется

Иконка отрисовывается в одном и том же размере независимо от CSS, и увеличение размера шрифта у родителя ничего не меняет. Назовите атрибут, который задаёт координатное пространство, и сделайте так, чтобы иконка масштабировалась как текст.

<span class="icon"><svg width="24" height="24">…</svg></span>
.icon { font-size: 2rem; }
.icon svg { width: 1em; height: 1em; }   /* на рисунок не влияет */

Решение

<span class="icon">
  <svg viewBox="0 0 24 24" aria-hidden="true" focusable="false">…</svg>
</span>
.icon { font-size: 2rem; }
.icon svg { inline-size: 1em; block-size: 1em; color: currentColor; }

Без viewBox рисунок остаётся привязанным к тому собственному размеру, в котором его экспортировали: изменение размеров элемента его не масштабирует, а обрезает или размывает. Внутреннюю координатную сетку — здесь 24 на 24 единицы — viewBox отображает на отрисованный прямоугольник. Поэтому любую иконку в системе можно масштабировать до любого размера в пикселях, не трогая данные пути. Размер в em заставляет иконку следовать размеру шрифта вокруг, так что читатель, который увеличил базовый размер текста, получает пропорциональную иконку. Цвет заливки при этом определяет цвет текста родителя через currentColor — без правила для каждого экземпляра.

Пример 2 — Одна встроенная иконка дважды, с двумя одинаковыми id

Иконку вставили в два компонента. Градиент, определённый внутри неё, теперь ссылается не на тот элемент во второй копии, а её цвет задан жёстко, поэтому тёмная тема выглядит сломанной. Разберитесь в обеих причинах и исправьте доставку.

<svg viewBox="0 0 24 24" width="24" height="24">
  <defs><linearGradient id="g1">…</linearGradient></defs>
  <path d="M4 12h16" fill="#0f766e" stroke="#0f766e" />
</svg>
<!-- вставлено снова в другом компоненте: <linearGradient id="g1"> дважды в одном документе -->

Решение

export function SearchIcon({ title }) {
  return (
    <svg viewBox="0 0 24 24" aria-hidden="true" focusable="false">
      <path d="M4 12h16" fill="currentColor" stroke="currentColor" />
      {title ? <title>{title}</title> : null}
    </svg>
  );
}
<SearchIcon />
<span className="text-brand-700"><SearchIcon /></span>

Встраивание помещает SVG в документ как поддерево DOM, поэтому его id глобальны для документа: две копии одного градиента делают каждую ссылку неоднозначной, и вторая иконка молча заимствует определение первой. Если сделать иконку компонентом, id либо исчезнут совсем, либо окажутся ограничены областью, а единый источник сохранит набор согласованным. Вторую неисправность устраняет currentColor: жёстко заданный hex не может следовать теме, поэтому иконка выделяется в тёмном режиме. Заодно один файл начинает обслуживать обе темы без дублирования. А <title> выводится только тогда, когда иконка несёт информацию, а не служит декором.