Question
I want to change the color of an SVG using CSS, but it is not working. I tried applying a fill style, yet the image always stays black.
Here is my code:
<style>
.change-my-color {
fill: green;
}
</style>
<svg>
<image
class="change-my-color"
xlink:href="https://svgur.com/i/AFM.svg"
width="96"
height="96"
src="ppngfallback.png"
/>
</svg>
Why does the SVG remain black, and how can I correctly change its color?
Short Answer
By the end of this page, you will understand why fill does not affect an externally loaded SVG inside an <image> element, and how to correctly style SVG colors using inline SVG, SVG paths, and currentColor. You will also learn common patterns developers use when they need recolorable icons in real projects.
Concept
In SVG, color is often controlled with properties such as fill and stroke.
fillchanges the inside color of shapes.strokechanges the outline color.
However, where the SVG comes from matters.
In your example, the SVG file is loaded through an <image> element:
<svg>
<image xlink:href="icon.svg" />
</svg>
This behaves more like placing an image file inside SVG, not like exposing the internal SVG shapes to CSS. Your CSS can style the <image> element itself, but it cannot reach inside the external SVG file and change the path, circle, or other shape colors.
That is why fill: green; does not recolor the external SVG content.
To change SVG color with CSS, the most common solution is to use inline SVG:
< = =>
Mental Model
Think of an external SVG file inside <image> like a photo in a picture frame.
- You can move the frame.
- You can resize the frame.
- But you cannot repaint the shapes inside the photo with normal CSS.
Inline SVG is like having the actual drawing instructions on the page.
- You can target the shapes directly.
- You can change their color.
- You can animate them.
- You can respond to hover, active, or theme changes.
So the key idea is:
- External SVG in
<image>or<img>= mostly not directly colorable withfill - Inline SVG = directly colorable with CSS
Syntax and Examples
1. Styling inline SVG with fill
<svg class="icon" viewBox="0 0 24 24" width="96" height="96">
<circle cx="12" cy="12" r="10" />
</svg>
.icon {
fill: green;
}
This works because the SVG markup is directly in the HTML.
2. Styling a specific shape inside SVG
<svg viewBox="0 0 24 24" width="96" height="96">
<circle class="icon-shape" cx="12" cy="12" = />
Step by Step Execution
Consider this inline SVG example:
<svg class="icon" viewBox="0 0 24 24" width="50" height="50">
<rect x="4" y="4" width="16" height="16" />
</svg>
.icon {
fill: green;
}
Here is what happens step by step:
- The browser reads the HTML and creates an
<svg>element. - Inside that SVG, it finds a
<rect>shape. - The browser reads the CSS rule for
.icon. - The
<svg>element has classicon, so the rule matches. - The
fill: greenproperty is applied to the SVG. - The
<rect>uses that fill value, so the rectangle is drawn in green.
Real World Use Cases
Recolorable UI icons
Applications often need icons that change color based on state:
- gray when disabled
- blue when active
- red for errors
- green for success
Inline SVG makes this easy.
Dark mode support
A site may switch from light mode to dark mode. Icons should follow the theme color automatically.
Using currentColor lets icons inherit color from surrounding text or components.
Hover and interaction states
Buttons and links often change icon color on hover:
.button {
color: #444;
}
.button:hover {
color: #0a84ff;
}
If the SVG uses currentColor, the icon changes too.
Status indicators
Dashboards often use SVG for:
- warning triangles
- success checkmarks
- error symbols
- loading shapes
These need dynamic coloring based on data.
Data visualizations
Charts and diagrams built with SVG often rely on fill and stroke to show categories, trends, or thresholds.
Real Codebase Usage
In real projects, developers usually choose one of these patterns:
Inline SVG for icons
This is the most common option when icons need to be styled.
<svg class="icon icon-success" viewBox="0 0 24 24">
<path d="M20 6L9 17l-5-5" fill="none" stroke="currentColor" stroke-width="2" />
</svg>
.icon-success {
color: green;
}
currentColor for theme-friendly icons
This pattern avoids hardcoding colors in the SVG.
.nav-link {
color: #555;
}
.nav-link.active {
color: #1d4ed8;
}
The icon follows automatically if it uses fill="currentColor" or .
Common Mistakes
1. Trying to style an external SVG loaded with <img> or <image>
Broken example:
<img class="icon" src="icon.svg" alt="icon">
.icon {
fill: red;
}
Why it fails:
filldoes not recolor the internal shapes of the external file.
How to avoid it:
- use inline SVG when you need CSS-based color changes
2. The SVG file has hardcoded fill values
Broken example:
<svg class="icon" viewBox="0 0 24 24">
<path fill="#000000" d="M12 2L2 22h20z" />
Comparisons
| Approach | Can CSS change SVG color? | Best for | Notes |
|---|---|---|---|
| Inline SVG | Yes | Icons, interactive graphics, themed UI | Most flexible option |
<img src="icon.svg"> | Usually no | Simple display-only images | Easy to use, not good for recoloring |
<svg><image href="icon.svg"></image></svg> | Usually no | Embedding external image content inside SVG | Does not expose inner shapes to CSS |
SVG with currentColor | Yes | Buttons, nav items, text-linked icons | Great for theme and state changes |
Hardcoded fill="#000" inside SVG | Limited |
Cheat Sheet
Quick rules
- Use inline SVG if you want to style color with CSS.
fillcolors the inside of a shape.strokecolors the outline.- External SVGs loaded via
<img>or<image>are usually not recolorable with CSSfill. currentColormakes an SVG follow the element's text color.
Common patterns
Inline SVG with fill:
<svg class="icon" viewBox="0 0 24 24">
<path d="..." />
</svg>
.icon {
fill: green;
}
Inline SVG with currentColor:
<svg class="icon" viewBox=>
FAQ
Why does fill not work on my SVG image?
Because your SVG is being loaded as an external image. CSS cannot usually style the internal shapes of that file.
Can I change the color of an SVG loaded with <img>?
Not directly with normal fill styling. For easy recoloring, use inline SVG instead.
What is the difference between fill and stroke in SVG?
fill colors the inside of shapes, while stroke colors the outline.
What does currentColor do in SVG?
It tells the SVG to use the current text color of its parent or element, which is very useful for theming.
Why is my inline SVG still black?
The SVG may have hardcoded fill="#000" or stroke="#000" attributes that override your CSS.
Should I use href or xlink:href for SVG images?
For modern code, href is generally preferred. Older examples may still use xlink:href.
Mini Project
Description
Build a small status icon panel that displays three SVG icons: success, warning, and error. The goal is to practice using inline SVG and currentColor so each icon can be recolored with simple CSS classes. This mirrors how many real interfaces style icons for alerts, forms, dashboards, and notifications.
Goal
Create a set of inline SVG icons whose colors are controlled entirely through CSS classes.
Requirements
- Display three status items: success, warning, and error.
- Each item must include an inline SVG icon and a text label.
- Use
currentColorso the icon color follows the parent element. - Give each status item a different CSS color.
- Keep the SVG markup valid and scalable with
viewBox.
Keep learning
Related questions
CSS Font Scaling Relative to Container Size: %, em, rem, vw, and Responsive Text
Learn how CSS font scaling really works and how to make text responsive using %, em, rem, vw, clamp(), and media queries.
CSS Parent Selector Explained: Selecting a Parent <li> from an <a>
Learn whether CSS has a parent selector, how :has() works, and practical alternatives for styling a parent li from a child anchor.
CSS Previous Sibling Selector: What Exists and How to Work Around It
Learn whether CSS has a previous sibling selector, why it does not, and practical ways to style earlier elements using CSS alternatives.