How to Use prefers-color-scheme in Standalone SVGs
Integrating the prefers-color-scheme media query
directly into standalone SVG files allows icons, logos, and
illustrations to dynamically switch between light and dark modes without
requiring external CSS or JavaScript. This article covers how to embed
internal styles, use CSS custom properties within SVG elements, and
ensure your standalone SVGs respond correctly when loaded in web
browsers or across different display contexts.
Embedding Media Queries in SVGs
SVGs support internal stylesheet declarations via the
<style> tag placed inside the
<defs> or directly inside the root
<svg> element. Because standalone SVG assets operate
in their own isolated document context, the media queries inside the SVG
evaluate against the system preferences of the user’s operating system
or browser.
Here is a basic structure for an SVG that changes its fill color based on the user’s system theme:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="100" height="100">
<style>
.theme-shape {
fill: #111827; /* Default: Light Mode */
}
@media (prefers-color-scheme: dark) {
.theme-shape {
fill: #f9fafb; /* Dark Mode */
}
}
</style>
<circle class="theme-shape" cx="50" cy="50" r="40" />
</svg>Using CSS Custom Properties for Scalability
For complex illustrations containing multiple elements, managing
colors using CSS variables (custom properties) keeps the code
maintainable. You can assign default values at the :root
level and override them inside the dark mode media query.
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="100" height="100">
<style>
:root {
--bg-color: #ffffff;
--primary-color: #2563eb;
--text-color: #1f2937;
}
@media (prefers-color-scheme: dark) {
:root {
--bg-color: #1f2937;
--primary-color: #60a5fa;
--text-color: #f9fafb;
}
}
.background { fill: var(--bg-color); }
.accent { fill: var(--primary-color); }
.label { fill: var(--text-color); font-family: sans-serif; font-size: 12px; }
</style>
<rect class="background" width="100" height="100" rx="10" />
<circle class="accent" cx="50" cy="40" r="20" />
<text class="label" x="50" y="80" text-anchor="middle">Theme</text>
</svg>Methods for Displaying Theme-Aware SVGs
Standalone SVGs containing internal media queries respond differently depending on how they are embedded into an HTML document:
- Standard
<img>tags: Modern browsers allow embedded SVGs inside standard<img src="icon.svg">tags to evaluateprefers-color-schemecorrectly. - Direct Browser Navigation: Opening the SVG directly via its URL will trigger the media query according to browser and OS settings.
<picture>and<source>Alternative: If you need separate assets rather than internal switching, the HTML<picture>element can serve different standalone files usingmedia="(prefers-color-scheme: dark)".- CSS Backgrounds: Using the SVG as a
background-image: url('icon.svg')in CSS will also respect the internal color scheme queries in modern browser engines.
Technical Constraints and Best Practices
- No External Resources: Standalone SVGs loaded via
<img>tags run in secure, isolated contexts. They cannot fetch external CSS files via<link>or@import. All CSS rules must reside inside the internal<style>block. - Avoid Hardcoded Attributes: Ensure presentation
attributes such as
fill="..."orstroke="..."on specific SVG path elements do not override the CSS rules defined in the<style>block. Use CSS classes instead of inline XML attributes for styled components. - Light-First Fallback: Always define the default styles outside any media queries. This guarantees proper rendering in legacy environments or tools that do not support CSS media features.