Иконки и SVG: что это и как подключать — inline SVG, img, object (HTML)

Что такое иконки и 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-код страницы:

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 позволяет наследовать цвет текста родительского элемента:
    css
    button:hover svg {
      fill: #e63946;
    }
  • Полный доступ через JavaScript. Можно манипулировать отдельными элементами SVG (<path>, <circle>), добавлять и удалять узлы, менять атрибуты:
    javascript
    const 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>:

html
<!-- Определение символов (можно скрыть через 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. Определение символов можно вынести в отдельный файл:

html
<svg width="16" height="16">
  <use href="icons.svg#icon-star"/>
</svg>

Однако при подключении внешнего файла через <use> теряется доступ к стилизации внутренних элементов через CSS (из-за ограничений Same-origin и теневого DOM).


<img>

SVG подключается как внешний файл через тег <img>:

html
<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> — выбор для статичных иконок фиксированного цвета, которые не меняют вид в зависимости от состояния интерфейса:

html
<img src="logo.svg" width="120" height="40" alt="Логотип компании">

<object>

SVG подключается как внешний документ через тег <object>:

html
<object type="image/svg+xml" data="icon.svg" width="16" height="16"
        aria-label="Звезда" role="img">
</object>

Что даёт

  • Доступ через CSS и JavaScript. SVG загружается как отдельный документ. Скрипты и стили основной страницы могут обращаться к его содержимому через contentDocument:
    javascript
    const 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-анимаций или визуализаций, которые нужно загрузить из внешнего файла и управлять ими через скрипт:

html
<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:

css
.icon-star {
  width: 16px;
  height: 16px;
  background: url('icon.svg') no-repeat center / contain;
}
html
<span class="icon-star" role="img" aria-label="Звезда"></span>

Это декоративный способ. Скринридеры не воспринимают фоновое изображение как значимый контент, поэтому подходит только для иконок без смысловой нагрузки — декоративные элементы оформления.

CSS можно управлять цветом, если SVG закодирован в data-URL:

css
.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:

html
<img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiI+PGRlZnM+PC9kZWZzPjwvc3ZnPg==" 
     width="16" height="16" alt="Звезда">

Или без base64, в текстовом виде:

html
<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 работает некорректно:

html
<svg viewBox="0 0 16 16" width="16" height="16">
  ...
</svg>

Атрибут role="img". Для inline SVG, которые несут информацию, указывайте role="img" и aria-label. Без этого скринридер может читать содержимое SVG как набор элементов:

html
<svg role="img" aria-label="Добавить в избранное" width="16" height="16">
  <path d="..."/>
</svg>

Декоративные иконки, рядом с которыми есть текст, помечаются aria-hidden="true":

html
<button type="button">
  <svg aria-hidden="true" width="16" height="16">
    <path d="..."/>
  </svg>
  В избранное
</button>

Единообразие. Выберите один основной способ подключения иконок в проекте. Смешение inline SVG, <img> и <object> без системы усложняет поддержку и стилизацию.

Добавить комментарий