Question
How can I change the fill color of an SVG path with CSS when the SVG is loaded using an <img> element?
<img src="logo.svg" alt="Logo" class="logo-img">
.logo-img path {
fill: #000;
}
The logo.svg file has a native fill color of white (#fff). I expected this CSS to change its paths to black, but it does not work. Why does this happen, and what is the correct way to style the SVG?
Short Answer
You will learn why CSS selectors cannot reach <path> elements inside an SVG loaded through <img>, and when to use inline SVG, currentColor, SVG-specific styles, or an image filter instead.
Concept
An SVG can be used in several ways on a web page. The way you embed it determines whether your page's CSS can style its internal elements.
When you write:
<img src="logo.svg" alt="Logo">
The browser treats logo.svg as an external image document. Your HTML page can style the <img> element itself—its width, height, border, and similar properties—but the SVG's internal <path>, <circle>, and <rect> elements are not part of your page's DOM.
Therefore, this selector cannot match anything:
.logo-img path {
fill: #000;
}
It means “find a path inside an element with the logo-img class.” But an <img> element has no child elements in the HTML document. The SVG file is loaded separately.
To style SVG shapes from your page CSS, the usual solution is to put the SVG markup directly in the HTML as an inline SVG. Then its <path> elements are real DOM elements that CSS can select.
This matters because SVGs are often used as icons, logos, status indicators, and controls whose colors need to react to themes, hover states, or component styles.
Mental Model
Think of an <img> element as a framed photograph. You can resize the frame or add a border around it, but you cannot use your page's CSS to repaint an object inside the photograph.
An inline <svg> is more like a drawing placed directly on your page. Its individual shapes—such as <path> elements—are available for CSS to select and recolor.
Syntax and Examples
With an external SVG image, you can style the image box, but not the paths inside it:
<img src="logo.svg" alt="Logo" class="logo-img">
.logo-img {
width: 48px;
height: 48px;
}
/* Does not work: there is no path in the HTML DOM below img. */
.logo-img path {
fill: #000;
}
To style the path, use inline SVG instead:
<svg class="logo-icon" viewBox="0 0 24 24" role="img" aria-label="Logo">
<path d="M4 4h16v16H4z"></path>
</svg>
.logo-icon {
width: 48px;
height: 48px;
}
.logo-icon path {
fill: #000;
}
A flexible icon pattern is to use currentColor in the SVG. currentColor means “use the element's CSS color value.”
<svg class="logo-icon" viewBox="0 0 24 24" aria-hidden="true">
<path fill="currentColor" d="M4 4h16v16H4z"></path>
</svg>
.logo-icon {
color: #000;
}
.logo-icon:hover {
color: #2563eb;
}
The path changes because its fill follows the SVG element's color.
Step by Step Execution
Consider this inline SVG:
<svg class="status-icon" viewBox="0 0 20 20" aria-hidden="true">
<circle cx="10" cy="10" r="8" fill="currentColor"></circle>
</svg>
.status-icon {
color: seagreen;
width: 20px;
height: 20px;
}
Execution sequence:
- The browser parses the
<svg>and its<circle>as elements in the page DOM. - The
.status-iconrule matches the<svg>and sets itscolortoseagreen. - The circle has
fill="currentColor". currentColorresolves to the inheritedcolorvalue:seagreen.- The browser draws the circle in seagreen.
If the same SVG were loaded with <img src="status-icon.svg">, a selector from the parent page could style the <img> box, but it could not select the circle within the SVG file.
Real World Use Cases
- Theme-aware icons: Use
currentColorso navigation icons automatically match light or dark text. - Buttons: Change an inline SVG icon color when a button is hovered, focused, disabled, or selected.
- Status indicators: Show success, warning, and error colors with the same SVG shape.
- Brand assets: Keep a fixed multicolor company logo as an
<img>when it does not need page-controlled styling. - Generated UI components: Render inline SVG markup in a component when the application needs to control
fill,stroke, size, or animation.
Real Codebase Usage
In production code, developers usually choose one of these patterns based on the icon's needs:
Inline SVG with currentColor
This is common for single-color UI icons.
<button class="delete-button" type="button">
<svg class="button-icon" viewBox="0 0 24 24" aria-hidden="true">
<path fill="currentColor" d="M7 4h10l1 2h3v2H3V6h3zm1 6h8v10H8z"></path>
</svg>
Delete
</button>
.delete-button {
color: #b91c1c;
}
.delete-button:hover {
color: #7f1d1d;
}
CSS classes for multiple SVG parts
For an illustration or icon with several independently styled pieces, add classes directly to the SVG elements.
<svg class="chart-icon" viewBox="0 0 24 24" aria-hidden="true">
<path class="chart-icon__bar" d="M3 12h4v9H3z"></path>
<path class="chart-icon__bar" d="M10 7h4v14h-4z"></path>
<path class="chart-icon__bar" d="M17 3h4v18h-4z"></path>
</svg>
.chart-icon__bar {
fill: #2563eb;
}
Keep fixed assets as <img>
Use <img> for static logos and illustrations that should remain self-contained. It has simple semantics through alt text and keeps the page markup smaller.
For reusable application icons, teams often create an icon component that consistently sets viewBox, accessibility attributes, size, and currentColor behavior.
Common Mistakes
Assuming <img> contains SVG child elements
This does not work:
.logo-img path {
fill: #000;
}
<img> is a replaced element, not a container for the SVG DOM. Use inline SVG if you need to target path.
Forgetting that an SVG has a hard-coded fill
If an inline SVG path contains fill="#fff", it may override a less specific stylesheet rule depending on the CSS rules involved. Prefer a deliberate style rule or use currentColor for colorable icons.
<!-- Flexible for theming -->
<path fill="currentColor" d="..."></path>
Styling color without using currentColor
Setting color does not automatically change SVG fills.
.icon {
color: black;
}
For this to affect the drawing, the SVG needs fill="currentColor", stroke="currentColor", or a CSS rule such as .icon path { fill: currentColor; }.
Using fill when the icon is drawn with stroke
Some SVGs are outlines rather than solid shapes.
<path stroke="currentColor" fill="none" d="M4 12h16"></path>
Change stroke, not fill, for this type of icon.
Removing useful accessibility text
If an SVG communicates meaning, give it an accessible name, such as role="img" with aria-label, or provide visible text. If it is only decorative next to text, use aria-hidden="true".
Comparisons
| Embedding method | Can page CSS target internal paths? | Best use case |
|---|---|---|
<img src="icon.svg"> | No | Static logos and images with alt text |
Inline <svg>...</svg> | Yes | UI icons, hover states, theming, and animation |
CSS background-image: url(icon.svg) | No | Decorative backgrounds |
| SVG file with its own internal CSS | Only within that SVG file | Self-contained SVG artwork |
| SVG property | Use it for |
|---|---|
fill | Solid interiors of shapes |
stroke | Lines and outlines |
color | A source value for currentColor |
currentColor | Making fill or stroke follow CSS text color |
Cheat Sheet
<!-- External SVG: CSS cannot select its internal path -->
<img src="icon.svg" alt="Settings">
<!-- Inline SVG: CSS can select its path -->
<svg class="icon" viewBox="0 0 24 24" aria-hidden="true">
<path fill="currentColor" d="..."></path>
</svg>
.icon {
width: 1.5rem;
height: 1.5rem;
color: #111827;
}
.icon:hover {
color: #2563eb;
}
/* Alternative to fill="currentColor" */
.icon path {
fill: currentColor;
}
<img>can be resized and positioned, but its SVG internals cannot be selected by page CSS.- Use inline SVG when individual shapes must be styled.
- Use
fillfor filled icons andstrokefor outline icons. - Use
currentColorto connect an SVG's color to CSScolor. - Include a
viewBoxso inline SVG scales correctly.
FAQ
Why does .logo-img path not work?
The SVG loaded by <img> is an external image document. Its <path> is not a child element in your HTML page, so the selector cannot match it.
Can I change an external SVG color using only CSS?
Not by directly selecting its paths from the parent page. You can use a CSS filter for limited recoloring, but inline SVG is the reliable choice when exact styling is needed.
Should I use fill or color for SVG icons?
Use fill to paint a filled shape. Use color together with fill="currentColor" or stroke="currentColor" when you want the icon to follow its CSS text color.
What if my SVG is an outline icon?
Use stroke instead of fill, provided the SVG path is drawn with a stroke.
Can an SVG file contain its own styles?
Yes. A standalone SVG can include style rules or attributes that apply within that SVG file. Those rules are separate from the CSS in the HTML page that uses it as an <img>.
Is inline SVG accessible?
Yes, when used appropriately. Decorative icons should usually have aria-hidden="true". Meaningful SVGs need an accessible name, such as an aria-label.
Is <img> still useful for SVG files?
Yes. It is a good choice for static, self-contained logos and illustrations, especially when you need alt text and do not need to style internal shapes.
Mini Project
Description
Build a small set of themeable inline status icons. The project demonstrates why inline SVG is appropriate when an application needs the same icon structure to display different colors for success, warning, and error states.
Goal
Create three status icons whose SVG colors are controlled entirely by CSS.
Requirements
- Use inline SVG markup rather than img elements.
- Create success, warning, and error icon variants.
- Use currentColor for each icon path.
- Set the variant colors with CSS classes.
- Add a hover color change to one variant.
Keep learning
Related questions
Angular ngClass Conditional Class Binding Explained
Learn how to use Angular ngClass for conditional classes, fix common binding mistakes, and understand why this template error happens.
Apply CSS to an iframe: Same-Origin Styling in HTML
Learn why parent-page CSS does not style iframe content, how same-origin rules work, and practical ways to style embedded pages safely.
Apply Multiple CSS Transforms: rotate() and translate()
Learn how to combine multiple CSS transform functions such as rotate() and translate(), understand transform order, and avoid overwritten rules.