CSS Techniques for Icon Styling
CSS provides powerful tools for styling icons without modifying source files. Understanding these techniques lets you adapt icons to different contexts, implement themes, and add interactivity while keeping your icon assets clean and reusable.
Styling Inline SVG Icons
Inline SVGs offer the most styling flexibility. You can target any element within the SVG using standard CSS selectors.
Basic Color Styling
/* Set fill color */
.icon path {
fill: #333;
}
/* Set stroke color */
.icon path {
stroke: #333;
stroke-width: 2;
fill: none;
}
/* Using currentColor */
.icon {
color: #333;
}
.icon path {
fill: currentColor;
}The currentColor approach is especially powerful because icons inherit their parent's text color automatically.
CSS Custom Properties for Theming
CSS variables make icon theming straightforward:
:root {
--icon-primary: #333;
--icon-secondary: #666;
--icon-accent: #0066cc;
}
[data-theme="dark"] {
--icon-primary: #fff;
--icon-secondary: #aaa;
--icon-accent: #66b3ff;
}
.icon-primary {
fill: var(--icon-primary);
}
.icon-secondary {
fill: var(--icon-secondary);
}Theme changes propagate to all icons instantly without JavaScript manipulation.
Sizing with CSS
Control icon dimensions flexibly:
/* Fixed size */
.icon {
width: 24px;
height: 24px;
}
/* Relative to font size */
.icon {
width: 1em;
height: 1em;
}
/* Responsive sizing */
.icon {
width: clamp(16px, 4vw, 32px);
height: clamp(16px, 4vw, 32px);
}Using em units lets icons scale with surrounding text automatically.
Interactive States
Icons often need state-based styling:
.icon-button {
color: var(--icon-default);
cursor: pointer;
}
.icon-button:hover {
color: var(--icon-hover);
}
.icon-button:active {
color: var(--icon-active);
transform: scale(0.95);
}
.icon-button:focus-visible {
outline: 2px solid var(--focus-ring);
outline-offset: 2px;
}
.icon-button:disabled {
color: var(--icon-disabled);
cursor: not-allowed;
}CSS Transitions
Smooth state changes with transitions:
.icon {
transition: color 0.2s ease, transform 0.2s ease;
}
.icon:hover {
color: var(--accent);
transform: scale(1.1);
}
/* Transition individual SVG elements */
.icon path {
transition: fill 0.2s ease, stroke 0.2s ease;
}CSS Animations
Create engaging animations with keyframes:
Rotation Animation
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
.icon-loading {
animation: spin 1s linear infinite;
}Pulse Animation
@keyframes pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.5; }
}
.icon-notification {
animation: pulse 2s ease-in-out infinite;
}Bounce Animation
@keyframes bounce {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-4px); }
}
.icon-arrow:hover {
animation: bounce 0.6s ease infinite;
}Animating SVG Elements
Target individual paths within SVGs for complex animations:
/* Checkmark draw-in effect */
.icon-check path {
stroke-dasharray: 100;
stroke-dashoffset: 100;
transition: stroke-dashoffset 0.3s ease;
}
.icon-check.visible path {
stroke-dashoffset: 0;
}
/* Morphing between states */
.icon-menu line {
transition: transform 0.3s ease;
transform-origin: center;
}
.icon-menu.open line:nth-child(1) {
transform: rotate(45deg) translate(0, 6px);
}
.icon-menu.open line:nth-child(2) {
opacity: 0;
}
.icon-menu.open line:nth-child(3) {
transform: rotate(-45deg) translate(0, -6px);
}CSS Filters
Apply visual effects without modifying icons:
/* Drop shadow */
.icon {
filter: drop-shadow(2px 2px 2px rgba(0,0,0,0.2));
}
/* Color inversion for dark mode */
[data-theme="dark"] .icon {
filter: invert(1);
}
/* Brightness adjustment */
.icon:hover {
filter: brightness(1.2);
}
/* Grayscale for disabled */
.icon:disabled {
filter: grayscale(1) opacity(0.5);
}Alignment and Positioning
Align icons with text and other elements:
/* Inline with text */
.icon-inline {
vertical-align: middle;
margin-right: 0.5em;
}
/* Flexbox alignment */
.button-with-icon {
display: inline-flex;
align-items: center;
gap: 0.5em;
}
/* Grid alignment */
.icon-grid {
display: grid;
grid-template-columns: repeat(auto-fill, 48px);
gap: 1rem;
}Responsive Icon Behavior
Adapt icons to different screen sizes:
/* Size adjustments */
.icon {
width: 24px;
}
@media (min-width: 768px) {
.icon {
width: 28px;
}
}
/* Show/hide labels */
.icon-label {
display: none;
}
@media (min-width: 768px) {
.icon-label {
display: inline;
}
}Handling External SVGs
For SVGs loaded via <img>, styling options are limited. Alternatives:
- Use inline SVG - Full CSS control
- Use <object> - Can style with external CSS
- CSS mask-image - Color monochrome icons
/* CSS mask approach */
.icon-mask {
background-color: currentColor;
-webkit-mask-image: url('icon.svg');
mask-image: url('icon.svg');
-webkit-mask-size: contain;
mask-size: contain;
}Performance Considerations
Keep styling performant:
- Avoid complex filters on many icons simultaneously
- Use
transformandopacityfor animations (GPU-accelerated) - Limit animated icons on screen at once
- Use
will-changesparingly for animation hints