Skip to main content

Як змінити колір у файлі svg?

Колір у SVG задається через атрибути fill (заливка фігури) і stroke (обводка). Обидва можна вказати прямо в розмітці, через CSS або JavaScript, але який спосіб спрацює залежить від того, як SVG потрапив на сторінку.

Теорія

TL;DR

  • fill фарбує внутрішню частину фігури, stroke фарбує її межу
  • CSS на SVG працює лише якщо SVG вбудований прямо в HTML
  • Зовнішні SVG через <img> ізольовані браузером - CSS туди не дістається
  • currentColor змушує фігуру успадковувати значення color від найближчого предка
  • Правило вибору: inline SVG + CSS для темізації, <img> для ізоляції, <object> для часткового контролю

Швидкий приклад

html
<!-- Прямий атрибут - працює скрізь --> <circle fill="red" stroke="blue" stroke-width="2" /> <!-- CSS на inline SVG - лише коли SVG у HTML --> <style> circle { fill: green; } </style> <svg><circle r="40" cx="50" cy="50" /></svg> <!-- currentColor - іконка наслідує колір тексту батьківського елемента --> <div style="color: navy;"> <svg width="24" height="24" viewBox="0 0 24 24"> <path fill="currentColor" d="M12 2L15 10H23L17 15L19 23L12 18L5 23L7 15L1 10H9L12 2Z" /> </svg> </div> <!-- Зірка відображається в кольорі navy -->

Inline SVG-елементи - це DOM-вузли. Браузер зчитує fill і stroke або з атрибутів елемента, або з обчисленого CSS. Для зовнішніх SVG через <img> це не діє.

Межа зовнішнього SVG

Коли ти завантажуєш SVG через <img src="icon.svg">, браузер вважає його непрозорим зображенням. Внутрішній DOM цього SVG не є частиною батьківського документа. CSS-селектори зі сторінки туди не проникають. Це межа безпеки браузера, а не обмеження, яке можна обійти вищою специфічністю.

Якщо потрібні динамічні кольори на зовнішньому SVG, є три варіанти:

  • Вбудувати SVG inline прямо в HTML тегом <svg>
  • Використати <object data="icon.svg"> (CSS-фільтри спрацюють на самому елементі <object>, але не на внутрішніх елементах SVG)
  • Використати <use> з посиланням на inline <symbol>

Коли який метод підходить

  • Прямі атрибути fill/stroke для статичних кольорів або коли ти контролюєш вихідний SVG-файл
  • CSS на inline SVG для hover-станів, темізації, темного режиму і адаптивних змін кольору
  • currentColor для систем іконок, де іконки мають відповідати кольору тексту навколо
  • JavaScript для змін кольору в реальному часі на основі даних або дій користувача

Типові помилки

Помилка 1: CSS для SVG завантаженого через <img>

html
<style> svg circle { fill: red; } </style> <img src="chart.svg" /> <!-- Коло залишається оригінального кольору. Правило до нього не дістається. -->

Браузер не розбирає внутрішню структуру SVG, коли воно завантажене як зображення. Вирішення: вбудуй SVG inline або використай <object>.

Помилка 2: Атрибут fill перемагає CSS

html
<style> circle { fill: blue; } </style> <svg> <circle fill="red" cx="50" cy="50" r="40" /> <!-- Відображається ЧЕРВОНИМ. Атрибут перемагає. --> </svg>

SVG-атрибути поводяться як inline-стилі і мають вищу специфічність ніж зовнішні CSS-правила. Це перше, що варто перевіряти коли зміна кольору через CSS не дає ефекту. Або видали атрибут fill з SVG, або використай !important: circle { fill: blue !important; }.

Помилка 3: color замість fill

html
<style> svg { color: red; } </style> <svg><circle cx="50" cy="50" r="40" /></svg> <!-- Коло не червоне -->

Властивість color впливає на текстові вузли, а не на SVG-фігури. Для фігур потрібен fill: red. Єдиний виняток: якщо фігура має fill="currentColor", тоді color батьківського елемента таки впливає на її колір.

Помилка 4: Неочевидна область дії currentColor

html
<div style="color: blue;"> <svg> <circle fill="currentColor" cx="30" cy="50" r="20" /> <g style="color: red;"> <rect fill="currentColor" x="60" y="30" width="40" height="40" /> <!-- rect - ЧЕРВОНИЙ, circle - СИНІЙ --> </g> </svg> </div>

currentColor приймає значення color від найближчого предка. Це зручно для локалізованого тематичного оформлення, але з першого погляду дивує.

Де зустрічається в реальних проектах

  • Heroicons, Feather Icons - всі іконки мають fill="currentColor" і автоматично підлаштовуються під колір кнопок, посилань і заголовків
  • D3.js, Recharts - fill і stroke на SVG-елементах задаються динамічно на основі даних
  • Styled-components, Emotion - змінні теми передаються в inline SVG через CSS custom properties
  • GSAP, Framer Motion - анімація fill і stroke для морфінгу і переходів кольору

Питання на співбесіді

Q: Чому CSS не працює для SVG завантаженого через <img>?
A: Браузер ізолює зовнішні зображення. DOM цього SVG не є частиною батьківського документа, тому жодні селектори, змінні чи скрипти не можуть до нього дістатись. Це рішення прийнято на рівні безпеки браузера.

Q: Чи можна використовувати CSS custom properties всередині SVG?
A: Так, якщо SVG вбудований inline. <circle fill="var(--brand-color)" /> працює і є чистим способом темізувати систему іконок через одну CSS-змінну. Зовнішні SVG не мають доступу до змінних батьківської сторінки.

Q: Як змінити колір SVG при наведенні?
A: CSS-псевдокласи на inline SVG: svg path:hover { fill: #2563eb; }. Для зовнішнього SVG через <img> практичні варіанти: CSS filter на самому елементі <img>, або заміна src через JavaScript на подію mouseenter.

Q: (Senior) Як зробити підтримку темного режиму для 50 SVG-іконок без дублювання розмітки?
A: Вбудуй всі іконки inline з fill="currentColor". Задай color на елементі-обгортці через CSS custom property: .icon { color: var(--icon-color); }. Визнач змінну для кожного режиму: @media (prefers-color-scheme: dark) { :root { --icon-color: white; } }. Всі іконки оновляться автоматично без змін у розмітці і без JavaScript.

Приклади

Статичний SVG з прямими атрибутами

html
<svg width="100" height="100" viewBox="0 0 100 100"> <circle cx="50" cy="50" r="40" fill="#3b82f6" stroke="#1e40af" stroke-width="4" /> </svg> <!-- Синє коло з темно-синьою обводкою -->

Атрибути обробляються першими, до CSS. Використовуй їх для автономних SVG-файлів або для фігур, колір яких не має змінюватись залежно від контексту.

Інтерактивна кнопка-іконка з currentColor

html
<style> .icon-btn { color: #6b7280; background: none; border: none; cursor: pointer; display: inline-flex; align-items: center; gap: 6px; } .icon-btn:hover { color: #2563eb; } .icon-btn svg { stroke: currentColor; width: 20px; height: 20px; } </style> <button class="icon-btn"> <svg viewBox="0 0 24 24" fill="none" stroke-width="2" stroke-linecap="round"> <circle cx="11" cy="11" r="6" /> <line x1="21" y1="21" x2="16.65" y2="16.65" /> </svg> Пошук </button> <!-- За замовчуванням іконка сіра. При наведенні: і текст, і іконка стають синіми. Одне CSS-правило (color) керує обома. -->

stroke: currentColor на <svg> прив'язує колір іконки до кольору тексту кнопки. Hover, focus, disabled - всі стани кольору працюють від однієї CSS-властивості на кнопці, без жодних змін у SVG-розмітці.

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.

Дочитали статтю?