Определите графику один раз в SVG-элементе <symbol>, а затем ссылайтесь на его идентификатор с помощью <use> внутри каждого видимого SVG. Задайте каждому экземпляру собственный размер, а CSS пусть управляет расположением остальных элементов страницы. Структура документа SVG.
Это руководство предназначено для тех, кто редактирует HTML-страницу на Mac и хочет разместить одну и ту же небольшую графику рядом с несколькими текстовыми метками. В полном примере используются синтетические плитки, обычный HTML и CSS. Фреймворк, JavaScript, загруженные изображения и этап сборки не нужны.
Как один символ создает несколько видимых графических элементов?
<symbol> — это графический шаблон. Сам по себе он не отображается; видимый экземпляр создает ссылка <use>. Разместите определение в документе один раз, а затем добавьте небольшую SVG-обертку там, где нужна графика. По документации MDN, оба элемента широко поддерживаются. MDN: symbol.
Важно различать отказ от повторения исходных путей и отказ от работы по отрисовке в браузере. В HTML содержится одно определение пути, но браузер по-прежнему создает отрисованный экземпляр для каждого <use>. MDN описывает это как клонирование в недоступный DOM. Повторное использование упрощает поддержку исходного кода, но не превращает несколько видимых элементов графики в один объект отрисовки. MDN: use.
Для страницы с метками и значками оставьте метки в HTML и выделите каждому значку собственную SVG-обертку. WHATWG относит SVG в HTML к встроенному, текстовому и потоковому содержимому, поэтому такие обертки можно размещать среди обычного содержимого страницы. Стандарт HTML: SVG.
Создайте полную страницу с одним определением и тремя экземплярами
В текстовом редакторе на Mac создайте файл с именем svg-reuse.html. Вставьте в него весь документ ниже, сохраните файл и откройте его в настольном браузере. Оставьте расширение .html и сохраните файл как обычный текст, а не как документ с форматированием.
В примере с помощью единственного <path> определены две диагональные плитки. Три ссылки показывают ту же геометрию в разных размерах и цветах. В каждой ссылке используется href="#demo-tiles"; обычная href — актуальная форма, а xlink:href считается устаревшим. MDN: атрибуты use.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Reusable tile symbol</title>
<style>
body {
margin: 2rem;
font-family: system-ui, sans-serif;
color: #263445;
}
.symbol-bank {
position: absolute;
width: 0;
height: 0;
overflow: hidden;
}
.samples {
display: flex;
flex-wrap: wrap;
gap: 1.5rem;
}
.sample {
display: flex;
align-items: center;
gap: 0.75rem;
padding: 1rem;
border: 1px solid #cbd5df;
}
.icon {
display: block;
width: 24px;
height: 24px;
flex: none;
}
.icon-large { width: 48px; height: 48px; }
.icon-medium { width: 32px; height: 32px; }
.blue { color: #2457a7; }
.purple { color: #7140a0; }
</style>
</head>
<body>
<svg class="symbol-bank" width="0" height="0" aria-hidden="true">
<symbol id="demo-tiles" viewBox="0 0 24 24"
preserveAspectRatio="xMidYMid meet">
<path fill="currentColor"
d="M4 4H10V10H4Z M14 14H20V20H14Z"></path>
</symbol>
</svg>
<main>
<h1>Tile samples</h1>
<div class="samples">
<div class="sample">
<svg class="icon" width="24" height="24"
viewBox="0 0 24 24" aria-hidden="true">
<use href="#demo-tiles" width="24" height="24"></use>
</svg>
<span>Small tiles</span>
</div>
<div class="sample blue">
<svg class="icon icon-large" width="48" height="48"
viewBox="0 0 24 24" aria-hidden="true">
<use href="#demo-tiles" width="24" height="24"></use>
</svg>
<span>Large tiles</span>
</div>
<div class="sample purple">
<svg class="icon icon-medium" width="32" height="32"
viewBox="0 0 24 24" aria-hidden="true">
<use href="#demo-tiles" width="24" height="24"></use>
</svg>
<span>Medium tiles</span>
</div>
</div>
</main>
</body>
</html>
В результате должны появиться три образца с рамками, содержащие одинаковые диагональные плитки. Первый использует цвет текста страницы, второй — синий, третий — фиолетовый. Размеры их SVG-областей — 24, 48 и 32 пикселя CSS. Чтобы проверить перенос образцов, сузьте окно браузера.
Здесь видимые фигуры служат декором, поскольку содержание передают соседние метки. Поэтому для SVG-оберток указано aria-hidden="true". Это исключает их из дерева доступности, не скрывая визуально. Используйте этот атрибут для декоративной графики; не применяйте его к изображению, которое передает информацию, отсутствующую в тексте. MDN: aria-hidden.
Какие настройки управляют компоновкой страницы и SVG?
Есть три отдельные задачи: расположить HTML-компоненты, задать размер каждой области SVG и вписать рисунок в эту область. Изменение настройки для одной задачи может не повлиять на две другие.
| Задача | Настройка в примере | Что изменить |
|---|---|---|
| Расположить образцы на странице | Для .samples используются flexbox и перенос строк |
Здесь измените интервалы или перенос |
| Выровнять графику по метке | Для .sample используются flexbox и align-items: center |
Здесь измените выравнивание компонента |
| Задать размер отображаемой области SVG | .icon и классы размеров |
Здесь измените ширину и высоту CSS |
| Определить координаты рисунка | viewBox="0 0 24 24" |
Измените это значение, если изменились границы рисунка в координатах |
| Задать внутренний размер ссылочного символа | У <use> ширина и высота равны 24 |
Для этого примера оставьте их согласованными с внутренней областью координат |
| Пропорционально вписать рисунок | preserveAspectRatio="xMidYMid meet" |
Изменяйте это только при необходимости другого способа вписывания |
Flexbox располагает непосредственные дочерние элементы гибкого контейнера. Поэтому внешний контейнер размещает образцы, а каждый внутренний — SVG рядом с меткой. Flexbox работает в одном измерении за раз; пространство между перенесенными строками распределяется независимо. Для макета с согласованными строками и столбцами подойдет CSS Grid. MDN: Основные понятия flexbox.
Внутри SVG для <use> действует другая модель компоновки. Значения x и y смещают графику в системе координат SVG. Они не задают расстояние между HTML-компонентами. Ширина и высота элемента могут задать размер области просмотра ссылочного символа, но не служат универсальным способом масштабирования напрямую указанного пути или группы. W3C: компоновка повторно используемой графики.
Почему у крупного экземпляра внутренние размеры по-прежнему равны 24?
Значение viewBox внешнего SVG описывает область координат размером 24 на 24. Область CSS может иметь размер 48 на 48 пикселей, а внутренние координаты при этом не меняются. Элемент <use> заполняет внутреннюю область 24 на 24, а внешний SVG масштабирует ее до большего отображаемого размера. По определению MDN, viewBox задается четырьмя числами: минимальная координата x, минимальная координата y, ширина и высота. MDN: viewBox.
Для наглядного расчета именно этого рисунка область размером 48 пикселей отображает 24 единицы координат с коэффициентом 48 / 24 = 2. Геометрия плиток занимает координаты от 4 до 20, поэтому общий размер отрисованной фигуры составит (20 - 4) × 2 = 32 пикселей. Оставшееся пространство приходится на намеренно предусмотренные поля внутри рисунка.
Вот почему увеличение ширины значка в CSS не обязательно заставляет отрисованную фигуру заполнить всю эту ширину. Перед тем как менять поля страницы для компенсации, проверьте границы геометрии внутри viewBox.
Что происходит, если область SVG имеет прямоугольную форму?
При xMidYMid meet рисунок равномерно масштабируется, остается по центру и целиком вписывается в доступную область просмотра. Поэтому квадратный рисунок в широком прямоугольнике оставляет по бокам свободное пространство. none допускает искажение; slice сохраняет пропорции, но позволяет части viewBox выходить за границы области просмотра. Используйте meet, если вся графика должна оставаться видимой. MDN: preserveAspectRatio.
Как задать каждому экземпляру собственный цвет?
Для пути указано fill="currentColor". Ключевое слово берет значение color элемента, поэтому один и тот же рисунок может принимать цвет окружающего текста. В примере изменение правила .blue или .purple меняет и метку, и плитки. MDN: ключевое слово currentColor.
Это работает благодаря наследованию стилей каждым экземпляром. Модель повторного использования SVG передает созданному содержимому стили, унаследованные от элемента <use>. Цвет, заданный непосредственно для исходного пути, имеет приоритет над унаследованной заливкой от родительского элемента. Если каждому экземпляру нужно задавать отдельный цвет, не фиксируйте цвет в общей геометрии. W3C: область действия и наследование стилей.
Не рассчитывайте, что селектор вроде .blue path сможет добраться до созданного пути через видимую обертку. Созданное содержимое относится к теневому дереву повторного использования, поэтому отношения предков отличаются от обычной вложенности HTML. Задайте color для обертки или ее контейнера, а в исходной геометрии оставьте currentColor. W3C: область действия и наследование стилей.
Что проверить, если повторно используемый символ отображается неправильно?
Начните со ссылки и проверьте связанные элементы по очереди. Так можно отличить отсутствующую графику от графики неправильного размера или положения и выбирать настройки для конкретной причины.
- Проверьте цель ссылки. Убедитесь, что
href="#demo-tiles"совпадает сid="demo-tiles"определения. Этот идентификатор должен быть уникальным в дереве документа. W3C: атрибут id. - Проверьте размеры видимой обертки. Класс
.symbol-bankс нулевыми размерами должен находиться только на контейнере определения. Каждому видимому экземпляру, как и.icon, нужна область ненулевого размера. - Проверьте границы координат. Убедитесь, что рисунок укладывается в заданный
viewBox. Неожиданное пустое пространство может быть вызвано неиспользуемыми координатами рисунка. MDN: viewBox. - Проверьте тип ссылочного элемента. Если вы заменили символ прямой ссылкой на путь, изменение ширины и высоты
<use>не масштабирует его тем же способом. Для этого шаблона верните символ и егоviewBox. MDN: use. - Проверьте объявления цветов. Прежде чем добавлять новые селекторы экземпляров, поищите фиксированные цвета в исходнике.
- Проверьте контейнер страницы. Если графика отображается правильно, но расположена слишком далеко от метки, измените зазор CSS или выравнивание компонента. MDN: Основные понятия flexbox.
Чтобы добавить пример на существующую страницу, один раз вставьте хранилище символов, объедините CSS и копируйте в дополнительные компоненты только видимую SVG-обертку. Для небольшого документа были выполнены структурные проверки: сбалансированность элементов, уникальность идентификаторов и наличие трех ссылок на одно определение пути; эти проверки не подтверждают правильность отрисовки в браузере. Откройте страницу в браузерах Mac, которые собираетесь поддерживать, и проверьте размер, интервалы и цвет результата.
Чтобы изменить общий рисунок, отредактируйте единственное определение пути. Чтобы изменить один экземпляр, задайте размер его обертки или унаследованный цвет. Разделение этих задач помогает повторно использовать графику и предсказуемо управлять расположением каждого экземпляра.
Источники
- Структура документа — SVG 2 — W3C.
- Стандарт HTML для веб-разработчиков: SVG — WHATWG.
<symbol>— MDN Web Docs.<use>— MDN Web Docs.- Основные понятия flexbox — MDN Web Docs.
- viewBox — MDN Web Docs.
- preserveAspectRatio — MDN Web Docs.
- Тип CSS
<color>— MDN Web Docs. - ARIA: атрибут aria-hidden — MDN Web Docs.