← Назад к вопросам

Как работал с SVG иконками?

2.0 Middle🔥 192 комментариев
#Soft Skills и рабочие процессы

Комментарии (2)

🐱
claude-haiku-4.5PrepBro AI3 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Работа с SVG иконками

Это важная часть фронтенда. SVG иконки масштабируемы, оптимальны и гибки в стилизации.

1. Встроенный SVG (inline)

<!-- Копируем SVG код прямо в HTML -->
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor">
  <path d="M5 12h14M12 5v14" stroke-width="2" stroke-linecap="round"/>
</svg>

Особенности:

  • Полный контроль над SVG
  • Можно стилизовать CSS
  • Нет дополнительного запроса
  • Большой HTML если много иконок
  • Можно анимировать

Когда использовать:

  • Динамические иконки с анимацией
  • Иконки которые нужно менять по состоянию

2. SVG файл как img

<img src="/icons/menu.svg" alt="Меню" width="24" height="24" />

Особенности:

  • Простой способ
  • Кэшируется браузером
  • Отдельный запрос
  • Нельзя стилизовать CSS
  • Нельзя анимировать
  • Может быть медленнее

Когда использовать:

  • Статические иконки
  • Разные иконки на разных страницах

3. SVG как background

.icon {
  width: 24px;
  height: 24px;
  background-image: url('/icons/menu.svg');
  background-size: contain;
  background-repeat: no-repeat;
}

Особенности:

  • Кэшируется браузером
  • Нельзя стилизовать содержимое SVG
  • Можно менять размер через background-size
  • Нельзя анимировать содержимое

Когда использовать:

  • Фоновые декоративные элементы
  • Простые иконки без анимации

4. SVG спрайт (РЕКОМЕНДУЕТСЯ)

<!-- sprite.svg -->
<svg style="display: none;">
  <defs>
    <symbol id="icon-menu" viewBox="0 0 24 24">
      <path d="M5 12h14M2 6h20M2 18h20" stroke="currentColor" stroke-width="2"/>
    </symbol>
    
    <symbol id="icon-close" viewBox="0 0 24 24">
      <path d="M18 6L6 18M6 6l12 12" stroke="currentColor" stroke-width="2"/>
    </symbol>
    
    <symbol id="icon-search" viewBox="0 0 24 24">
      <circle cx="11" cy="11" r="8" stroke="currentColor" stroke-width="2"/>
      <path d="m21 21-4.35-4.35" stroke="currentColor" stroke-width="2"/>
    </symbol>
  </defs>
</svg>

<!-- Использование спрайта -->
<svg class="icon icon-menu" width="24" height="24">
  <use xlink:href="#icon-menu"></use>
</svg>

<svg class="icon icon-close" width="24" height="24">
  <use xlink:href="#icon-close"></use>
</svg>

<svg class="icon icon-search" width="24" height="24">
  <use xlink:href="#icon-search"></use>
</svg>

<style>
  .icon {
    width: 24px;
    height: 24px;
    stroke: currentColor; /* наследует цвет текста */
  }
  
  .icon-menu {
    stroke: blue;
  }
  
  .icon-close {
    stroke: red;
  }
  
  .icon:hover {
    stroke: green;
  }
</style>

Особенности:

  • Одна загрузка спрайта
  • Можно стилизовать CSS
  • Экономит трафик
  • Стандартный подход
  • Хорошая производительность

5. Font Icon (не рекомендуется)

<!-- Был популярен (Font Awesome, Bootstrap Icons) -->
<i class="fas fa-heart"></i>

Проблемы:

  • Требует загрузку шрифта
  • Может быть медленнее SVG
  • Сложнее кастомизировать
  • Проблемы с выравниванием

SVG лучше чем шрифты!

6. React компонент Icon

// Icon.jsx
export function Icon({ id, width = 24, height = 24, stroke = 'currentColor', ...props }) {
  return (
    <svg width={width} height={height} {...props}>
      <use xlinkHref={`#${id}`} stroke={stroke} />
    </svg>
  );
}

// Использование
import { Icon } from './Icon';

function Header() {
  return (
    <header>
      <Icon id="icon-menu" />
      <Icon id="icon-search" stroke="blue" />
      <Icon id="icon-user" width={32} height={32} />
    </header>
  );
}

7. Icon Component с инлайн SVG

// MenuIcon.jsx
export function MenuIcon({ size = 24, color = 'currentColor' }) {
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none">
      <path 
        d="M5 12h14M2 6h20M2 18h20" 
        stroke={color} 
        strokeWidth="2"
      />
    </svg>
  );
}

// Использование
import { MenuIcon } from './MenuIcon';

function Button() {
  return <button><MenuIcon size={20} color="blue" /></button>;
}

8. Лучший подход: Icon библиотека

// lib/icons.jsx
const icons = {
  menu: (props) => (
    <svg {...props} viewBox="0 0 24 24">
      <path d="M5 12h14M2 6h20M2 18h20" stroke="currentColor" strokeWidth="2" />
    </svg>
  ),
  
  close: (props) => (
    <svg {...props} viewBox="0 0 24 24">
      <path d="M18 6L6 18M6 6l12 12" stroke="currentColor" strokeWidth="2" />
    </svg>
  ),
  
  search: (props) => (
    <svg {...props} viewBox="0 0 24 24">
      <circle cx="11" cy="11" r="8" stroke="currentColor" strokeWidth="2" />
      <path d="m21 21-4.35-4.35" stroke="currentColor" strokeWidth="2" />
    </svg>
  )
};

export function Icon({ name, size = 24, color = 'currentColor', className = '' }) {
  const IconComponent = icons[name];
  
  if (!IconComponent) {
    console.warn(`Icon "${name}" not found`);
    return null;
  }
  
  return (
    <IconComponent 
      width={size} 
      height={size} 
      color={color}
      className={className}
      fill="none"
    />
  );
}

// Использование
<Icon name="menu" size={24} />
<Icon name="close" size={20} color="red" />

9. Оптимизация SVG файлов

# Используй SVGO для оптимизации
npm install -g svgo

svgo input.svg -o output.svg
# Или оптимизируй все файлы
svgo *.svg -o optimized/

Что оптимизирует:

  • Удаляет лишние атрибуты
  • Минифицирует пути
  • Удаляет комментарии
  • Сокращает размер на 30-50%

10. Примеры из практики

Иконка с анимацией

function LoadingIcon() {
  return (
    <svg width="24" height="24" viewBox="0 0 24 24">
      <circle 
        cx="12" cy="12" r="10" 
        stroke="currentColor" 
        strokeWidth="2"
        fill="none"
        style={{
          animation: 'spin 1s linear infinite',
          transformOrigin: '50% 50%'
        }}
      />
      <style>{`
        @keyframes spin {
          to { transform: rotate(360deg); }
        }
      `}</style>
    </svg>
  );
}

Иконка с hover эффектом

function FavoriteIcon({ isFavorite, onToggle }) {
  return (
    <button onClick={onToggle} className="favorite-btn">
      <svg 
        width="24" height="24" 
        viewBox="0 0 24 24"
        className={isFavorite ? 'favorite-active' : ''}
      >
        <path 
          d="M20 4.6l-5.5 5.5L12 2 6.5 10.1 1 4.6v14.8c0 2 1.6 3.6 3.6 3.6h12.8c2 0 3.6-1.6 3.6-3.6V4.6z"
          stroke="currentColor"
          strokeWidth="2"
          fill="none"
        />
      </svg>
    </button>
  );
}

<style>
  .favorite-btn svg {
    stroke: gray;
    transition: all 0.3s ease;
  }
  
  .favorite-btn svg.favorite-active {
    stroke: red;
    fill: red;
  }
  
  .favorite-btn:hover svg {
    transform: scale(1.2);
  }
</style>

Адаптивные иконки

function ResponsiveIcon() {
  return (
    <svg 
      width="100%" 
      height="100%" 
      viewBox="0 0 24 24"
      style={{ maxWidth: '24px', maxHeight: '24px' }}
    >
      <path d="M5 12h14" stroke="currentColor" strokeWidth="2" />
    </svg>
  );
}

/* Адаптируется к контейнеру благодаря viewBox */

11. Инструменты для создания иконок

- Figma (проектирование)
- Adobe Illustrator (профессиональное)
- Inkscape (бесплатное)
- IconMoon (генератор спрайтов)
- Icomoon (готовые иконки)
- Feather Icons (минималистичные)
- Heroicons (красивые иконки)
- Material Design Icons (много иконок)

12. Чеклист при работе с SVG

[ ] SVG оптимизирован (SVGO)
[ ] viewBox установлен (для масштабирования)
[ ] stroke/fill явно указаны
[ ] currentColor для наследования цвета
[ ] width/height для фиксированного размера
[ ] alt текст для img тега
[ ] aria-label для доступности
[ ] Не забыл закрыть пути (</path>)
[ ] Проверил на разных браузерах
[ ] Испытал на производительность

Итого

Мой подход к SVG иконкам:

  1. Для простого случая: встроенный SVG в HTML
  2. Для множества иконок: SVG спрайт
  3. Для React приложения: Icon компонент с библиотекой
  4. Для анимации: инлайн SVG с CSS/JS анимацией

СВГ лучше чем:

  • Font Icons (быстрее, гибче)
  • PNG иконки (масштабируемые)
  • DataURI (отдельный запрос лучше)

Советы:

  • Используй currentColor для наследования цвета
  • Оптимизируй файлы SVGO
  • Устанавливай viewBox для масштабируемости
  • React компоненты для переиспользования
  • Спрайты для производительности