Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Як змінити колір у файлі svg?». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**Колір у SVG** задається через атрибути `fill` (заливка фігури) і `stroke` (обводка). ```html <circle fill="red" stroke="blue" stroke-width="2" /> ``` CSS працює лише на вбудованих SVG. Зовнішні SVG завантажені через `<img>` ізольовані браузером і не бачать стилів сторінки. `fill="currentColor"` дозволяє іконці успадковувати значення `color` від батьківського елемента. **Ключове:** атрибут `fill` має вищу специфічність ніж CSS-правила і перевизначає їх, якщо не видалити атрибут або не використати `!important`.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення**Колір у 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-розмітці.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.