If you want to have shadows on your SVG icons, the options can be tough to apply. They require injecting shadows into the SVG logic, making it tough to work with third party icons.

The solution I found is to

We can then use any SVG and layer them. And then we can use native CSS styling.

<button>
	<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-box">
		<path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"></path>
		<polyline points="3.27 6.96 12 12.01 20.73 6.96"></polyline>
		<line x1="12" y1="22.08" x2="12" y2="12"></line>
	</svg>

	<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-box background">
		<path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"></path>
		<polyline points="3.27 6.96 12 12.01 20.73 6.96"></polyline>
		<line x1="12" y1="22.08" x2="12" y2="12"></line>
	</svg>
</button>

Now we need to align the buttons so they are on top of each other

.foreground {
	position: absolute;
}

From this point you have the basic alignment and the DOM Rendering likes this. You can then move the shadow out and color it.

.background {
	color: black;
	transform: translate(1px, 1px);
}

But you may notice the background pops out. Solutions to this may be dependant on your scenerios but a little z-index on the foreground is enough to pop it forward.

.foreground {
	z-index: 1;
	position: absolute;
}

This format allows you to do transformations on the button and it will keep alignment.

button {
	transform: rotate(16deg) scale(1.3);
}

The downside is the way this works the SHADOW is the actual dependent size here. If you change the size of the shadow or want pixel perfect accuracy then it will be farther off.

The way around this is if you use transform functions, the original dom size will not change outside of this element.

.background {
	transform:scale(1.5);
}
.background {
	transform: rotate(16deg) scale(2) translate(2px, 2px); 
	opacity: .4;
}

And then we can do all sorts of animations.

@keyframes spin{
	from {
	 	transform: rotate(0);
	}

	to {
		transform: rotate(360deg);
	}
}

.animate-button {
	animation: spin 2s linear infinite;
}

Key Components

Size

width="24" and height="24" and viewBox="0 0 24 24". These define the size of the rendered components in different ways. Applying css styling to the size of the component may need to consider all these variables.

stroke="currentColor" this is a key detail that allows you to set the stroke color using the current the color.

button {
	color: red;
}

Conclusion

By using this technic you get a simple way to handle icon shadowing using simple CSS.

All Together

/* Foreground */
button > svg:nth-child(1) {
	position: absolute;
	z-index: 1;
	color: inherit;
}

/* Shadow/background layer */
button > svg:nth-child(2) {
	color: black;	
	transform: translate(1px, 1px);
}

Sources

Related