Основы 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> выводится только тогда, когда иконка несёт информацию, а не служит декором.