Что такое иконки и SVG
Иконка — это небольшое графическое изображение, которое передаёт смысл быстрее текста: «корзина», «поиск», «настройка», «поделиться». В вебе иконки используют, чтобы:
- ускорить восприятие интерфейса;
- сэкономить место на экране;
- сделать интерфейс понятным без чтения;
- поддержать визуальную иерархию.
SVG (Scalable Vector Graphics) — это формат векторной графики на основе XML. В отличие от растровых форматов (PNG, JPEG), SVG не состоит из пикселей, а описывает изображение через команды: линии, кривые, заливки, контуры.
Ключевые свойства SVG для веба:
- Масштабируемость без потери качества. Иконку 16×16 можно увеличить до 256×256 — она останется чёткой.
- Текстовая природа. SVG — это XML-документ: его можно редактировать в текстовом редакторе, сжимать, оптимизировать.
- Стилизация и анимация. Цвета, толщина линий, прозрачность и анимации можно задавать через CSS и JavaScript.
- Малый вес для простых фигур. Простые иконки в SVG часто весят меньше, чем PNG аналогичного качества.
- Доступность. К SVG можно добавить текстовые описания для скринридеров.
Именно из-за этих свойств SVG стал стандартом для иконок в современных веб-проектах.
Варианты подключения SVG в HTML
SVG можно добавить в HTML-страницу несколькими основными способами:
- Inline SVG — разметка SVG вставляется прямо в HTML.
<img>— SVG подключается как внешний файл, как обычное изображение.<object>— SVG загружается как отдельный документ в отдельном контексте.
Выбор способа определяет, что можно делать с иконкой: стилизовать через CSS, анимировать, управлять через JavaScript, использовать спрайты и кэшировать.
Inline SVG
Разметка SVG вставляется прямо в HTML-код страницы:
<button type="submit"> <svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> <path d="M8 0l2 6h6l-5 4 2 6-5-4-5 4 2-6-5-4h6z"/> </svg> В избранное </button>
Что даёт
- Полный доступ через CSS. Можно задавать
fill,stroke,stroke-widthи другие свойства. ЗначениеcurrentColorпозволяет наследовать цвет текста родительского элемента:cssbutton:hover svg { fill: #e63946; }
- Полный доступ через JavaScript. Можно манипулировать отдельными элементами SVG (
<path>,<circle>), добавлять и удалять узлы, менять атрибуты:javascriptconst star = document.querySelector('svg path'); star.addEventListener('click', () => { star.setAttribute('fill', '#gold'); });
- Анимация через CSS и SMIL. Можно анимировать отдельные части SVG:
html
<svg width="24" height="24" viewBox="0 0 24 24"> <circle cx="12" cy="12" r="10" fill="none" stroke="#333" stroke-width="2"> <animate attributeName="r" values="10;8;10" dur="2s" repeatCount="indefinite"/> </circle> </svg>
- Нет дополнительных HTTP-запросов. SVG загружается вместе с HTML, отдельный файл не нужен.
Ограничения
- Увеличивает размер HTML. Большая иконка — это разметка, которую браузер парсит как часть документа. Сотни иконок замедляют обработку страницы.
- Дублирование. Если одна иконка используется в десяти местах, её разметка повторяется десять раз — если только не использовать
<use>. - Кэширование. Inline SVG не кэшируется отдельно от HTML. Браузер не может переиспользовать его на других страницах.
Использование с <use>
Чтобы не дублировать разметку, SVG-символы можно определить один раз и ссылаться на них через <use>:
<!-- Определение символов (можно скрыть через CSS) --> <svg xmlns="http://www.w3.org/2000/svg" style="display:none"> <symbol id="icon-star" viewBox="0 0 16 16"> <path d="M8 0l2 6h6l-5 4 2 6-5-4-5 4 2-6-5-4h6z"/> </symbol> <symbol id="icon-heart" viewBox="0 0 16 16"> <path d="M8 14s-6-4-6-8a3 3 0 016-1 3 3 0 016 1c0 4-6 8-6 8z"/> </symbol> </svg> <!-- Использование --> <button type="button"> <svg width="16" height="16" fill="currentColor"> <use href="#icon-star"/> </svg> В избранное </button> <button type="button"> <svg width="16" height="16" fill="currentColor"> <use href="#icon-heart"/> </svg> Нравится </button>
Это устраняет дублирование, сохраняя при этом доступ через CSS и JavaScript. Определение символов можно вынести в отдельный файл:
<svg width="16" height="16"> <use href="icons.svg#icon-star"/> </svg>
Однако при подключении внешнего файла через <use> теряется доступ к стилизации внутренних элементов через CSS (из-за ограничений Same-origin и теневого DOM).
<img>
SVG подключается как внешний файл через тег <img>:
<img src="icon.svg" width="16" height="16" alt="Звезда">
Что даёт
- Кэширование. Браузер кэширует файл отдельно. Если иконка используется на двадцати страницах, она загружается один раз.
- Простота. Та же модель, что и для растровых изображений. Атрибут
altобеспечивает доступность. - Чистый HTML. Разметка страницы не перегружается встроенной SVG-разметкой.
- Адаптивность. SVG масштабируется без потери качества:
css
img.icon { width: 24px; height: 24px; }
Ограничения
- Нет доступа через CSS. Стилизация внутренних элементов SVG (
fill,stroke) из CSS страницы невозможна. Цвет и другие свойства задаются внутри самого SVG-файла. - Нет доступа через JavaScript. DOM-дерево SVG недоступно скриптам страницы.
- Нет интерактивности. Анимации SMIL внутри SVG работают не во всех браузерах при подключении через
<img>. CSS-анимации внутри файла не выполняются в Firefox при загрузке через<img>. - Токен
currentColorне работает. SVG, загруженный через<img>, изолирован.currentColorне наследует цвет текста родительского элемента.
Когда подходит
<img> — выбор для статичных иконок фиксированного цвета, которые не меняют вид в зависимости от состояния интерфейса:
<img src="logo.svg" width="120" height="40" alt="Логотип компании">
<object>
SVG подключается как внешний документ через тег <object>:
<object type="image/svg+xml" data="icon.svg" width="16" height="16" aria-label="Звезда" role="img"> </object>
Что даёт
- Доступ через CSS и JavaScript. SVG загружается как отдельный документ. Скрипты и стили основной страницы могут обращаться к его содержимому через
contentDocument:javascriptconst obj = document.querySelector('object'); obj.addEventListener('load', () => { const svg = obj.contentDocument.querySelector('svg'); svg.style.fill = '#e63946'; });
css/* Через CSS — только если SVG и страница на одном домене */ object { width: 24px; height: 24px; }
- Поддержка анимаций. CSS- и SMIL-анимации внутри SVG работают при загрузке через
<object>, в отличие от<img>. - Кэширование. Как и
<img>, файл кэшируется отдельно.
Ограничения
- Same-origin. Доступ к содержимому через
contentDocumentработает только если SVG и HTML-страница находятся на одном домене. При загрузке с CDN доступ к DOM закрывается политикой безопасности. - Запасное содержимое. Если браузер не поддерживает SVG (актуально для устаревших систем), внутри
<object>можно разместить fallback:html<object type="image/svg+xml" data="icon.svg" width="16" height="16"> <img src="icon.png" width="16" height="16" alt="Звезда"> </object>
- Семантика и доступность.
<object>— не изображение. Для скринридеров нужно указыватьrole="img"иaria-label, иначе содержимое может быть проигнорировано или прочитано некорректно. - Сложность стилизации. Управление цветом и другими свойствами требует JavaScript и обработки события
load. Это сложнее, чем inline SVG, где достаточно CSS.
Когда подходит
<object> — выбор для интерактивных SVG-анимаций или визуализаций, которые нужно загрузить из внешнего файла и управлять ими через скрипт:
<object type="image/svg+xml" data="chart.svg" width="800" height="400" role="img" aria-label="График продаж за год"> </object>
Сравнение способов
| Параметр | Inline SVG | <img> |
<object> |
|---|---|---|---|
| CSS-стилизация | Полная | Нет | Через contentDocument |
| JavaScript-доступ | Полный | Нет | Через contentDocument |
| Анимация CSS/SMIL | Да | Ограничена | Да |
currentColor |
Работает | Не работает | Работает внутри SVG |
| Кэширование | Нет | Да | Да |
| Размер HTML | Увеличивает | Нет | Нет |
| HTTP-запросы | Нет | Да | Да |
| Доступность | Через aria-* |
Атрибут alt |
role="img" + aria-label |
| Fallback | Не нужен | Атрибут alt |
Вложенный контент |
Дополнительные способы
CSS background-image
SVG можно подключить через CSS:
.icon-star { width: 16px; height: 16px; background: url('icon.svg') no-repeat center / contain; }
<span class="icon-star" role="img" aria-label="Звезда"></span>
Это декоративный способ. Скринридеры не воспринимают фоновое изображение как значимый контент, поэтому подходит только для иконок без смысловой нагрузки — декоративные элементы оформления.
CSS можно управлять цветом, если SVG закодирован в data-URL:
.icon-star { background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23333'%3E%3Cpath d='M8 0l2 6h6l-5 4 2 6-5-4-5 4 2-6-5-4h6z'/%3E%3C/svg%3E") no-repeat center / contain; }
Цвет зашифрован в URL (%23333 — #333). Изменить его из CSS без перезаписи всего background невозможно. Это делает метод негибким.
Data URI
SVG можно встроить в src тега <img> через data-URI:
<img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiI+PGRlZnM+PC9kZWZzPjwvc3ZnPg==" width="16" height="16" alt="Звезда">
Или без base64, в текстовом виде:
<img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23333'%3E%3Cpath d='M8 0l2 6h6l-5 4 2 6-5-4-5 4 2-6-5-4h6z'/%3E%3C/svg%3E" width="16" height="16" alt="Звезда">
Преимущество — нет HTTP-запроса. Недостаток — размер HTML увеличивается, кэширование невозможно, редактирование неудобно. Data URI потерял актуальность после внедрения HTTP/2, где множественные запросы мультиплексируются в одном соединении.
Критерии выбора
Inline SVG — когда:
- Иконка меняет цвет в зависимости от состояния (
hover,active,disabled). - Иконка анимируется через CSS или JavaScript.
- Иконка используется на небольшом числе страниц.
- Нужно управление отдельными элементами SVG.
<img> — когда:
- Иконка статичная, цвет не меняется.
- Иконка используется на многих страницах — важно кэширование.
- Нужен простой
altдля доступности. - HTML должен оставаться чистым.
<object> — когда:
- Нужна внешняя SVG-анимация с управлением через скрипт.
- SVG-файл большой и не должен раздувать HTML.
- Нужен fallback для устаревших браузеров.
CSS background — когда:
- Иконка чисто декоративная и не несёт смысловой нагрузки.
- Иконка не требует интерактивности или изменения цвета.
Практические рекомендации
Оптимизация SVG-файлов. Перед использованием внешних файлов пропускайте их через SVGO или аналогичные инструменты: удаляются метаданные, комментарии, неиспользуемые определения, лишние пробелы. Размер файла уменьшается на 30–60%.
Атрибут viewBox. Всегда указывайте viewBox в SVG, даже если задаёте фиксированные width и height. Без viewBox масштабирование через CSS работает некорректно:
<svg viewBox="0 0 16 16" width="16" height="16"> ... </svg>
Атрибут role="img". Для inline SVG, которые несут информацию, указывайте role="img" и aria-label. Без этого скринридер может читать содержимое SVG как набор элементов:
<svg role="img" aria-label="Добавить в избранное" width="16" height="16"> <path d="..."/> </svg>
Декоративные иконки, рядом с которыми есть текст, помечаются aria-hidden="true":
<button type="button"> <svg aria-hidden="true" width="16" height="16"> <path d="..."/> </svg> В избранное </button>
Единообразие. Выберите один основной способ подключения иконок в проекте. Смешение inline SVG, <img> и <object> без системы усложняет поддержку и стилизацию.
