Duotone SVG Icons: Manage Opacity & Color with CSS
Duotone SVG icons create visual depth by dividing a single graphic into primary and secondary layers. This article explains how developers use dedicated CSS classes and custom properties to control the color, opacity, and inheritance of these distinct SVG paths. By separating the visual layers within the vector markup, you can dynamically adapt icons across themes, hover states, and design systems without altering the underlying SVG code.
SVG Structure and Layer Separation
The foundation of a duotone icon relies on separating elements into
distinct SVG <path> or <g> (group)
elements. Instead of hardcoding fill attributes directly
inside the markup, each layer is assigned a specific class name.
<svg viewBox="0 0 24 24" class="icon-duotone">
<path class="icon-primary" d="..." />
<path class="icon-secondary" d="..." />
</svg>Separating paths allows stylesheets to target individual vector components independently.
Controlling Secondary Opacity
Secondary layer transparency creates the signature duotone look. This
effect is achieved in CSS using either the standard opacity
property or the SVG-specific fill-opacity property on the
secondary class.
.icon-duotone .icon-secondary {
opacity: 0.4;
}Using opacity applies transparency to the entire
targeted element, including any borders, while fill-opacity
isolates transparency strictly to the fill area. Using CSS variables
makes this value easily adjustable across components:
.icon-duotone {
--icon-secondary-alpha: 0.4;
}
.icon-duotone .icon-secondary {
opacity: var(--icon-secondary-alpha);
}Color
Management via currentColor and CSS Variables
By default, duotone icons often inherit the surrounding text color
using fill: currentColor. When applied to both layers, the
secondary layer automatically produces a lighter tint of the primary
color due to its reduced opacity:
.icon-duotone .icon-primary,
.icon-duotone .icon-secondary {
fill: currentColor;
}To create multi-color duotone effects, developers use CSS custom properties to assign distinct color values to each class:
.icon-duotone {
--duotone-primary: #1e293b;
--duotone-secondary: #3b82f6;
}
.icon-duotone .icon-primary {
fill: var(--duotone-primary);
}
.icon-duotone .icon-secondary {
fill: var(--duotone-secondary);
}Handling Dynamic States and Themes
Because all visual attributes are mapped to CSS classes, interactive
states such as :hover, :focus, or dark mode
variations can be modified globally or locally:
/* Swapping opacity and colors on hover */
.button:hover .icon-duotone .icon-secondary {
opacity: 0.8;
fill: var(--duotone-primary);
}
/* Inverting emphasis in dark mode */
[data-theme="dark"] .icon-duotone {
--duotone-primary: #f8fafc;
--duotone-secondary: #94a3b8;
--icon-secondary-alpha: 0.6;
}Targeting SVG layers through CSS classes ensures high flexibility, reduces redundant markup, and keeps design logic centralized within stylesheets.