How to Customize SVGs using Next.js and Tailwind CSS
renan leonel
Posted on October 18, 2023
This article aims to demonstrate how to customize SVG images using Next.js and Tailwind, without the need for external configurations or the use of auxiliary libraries like svgr/webpack.
For this tutorial, we're using the following image: https://www.flaticon.com/free-icon-font/checkbox_3917076?related_id=3917076
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Capa_1" x="0px" y="0px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve" width="512" height="512">
<g>
<path d="M405.333,0H106.667C47.786,0.071,0.071,47.786,0,106.667v298.667C0.071,464.214,47.786,511.93,106.667,512h298.667 C464.214,511.93,511.93,464.214,512,405.333V106.667C511.93,47.786,464.214,0.071,405.333,0z M426.667,172.352L229.248,369.771 c-16.659,16.666-43.674,16.671-60.34,0.012c-0.004-0.004-0.008-0.008-0.012-0.012l-83.563-83.541 c-8.348-8.348-8.348-21.882,0-30.229s21.882-8.348,30.229,0l83.541,83.541l197.44-197.419c8.348-8.318,21.858-8.294,30.176,0.053 C435.038,150.524,435.014,164.034,426.667,172.352z" />
</g>
</svg>
The default behavior of Next.js with the <Image>
tag does not allow changing the fill
property of the SVG. This becomes an issue when we need to change the color of an SVG image during mouse hover, for example, using Tailwind CSS classes like fill-white
or bg-white
. This approach doesn't work because we're not directly changing the fill
property of the <svg>
, and as of the writing of this article (Next 13.5.4)
, the <Image/>
tag doesn't support changes to the fill of SVGs.
import Image from 'next/image';
import checkbox from '../../public/icons/checkbox.svg';
const Home = () => {
return (
<main className='h-screen bg-zinc-800 flex items-center justify-center'>
<Image
src={checkbox}
alt='checkbox'
className='w-20 h-20 fill-white'
/>
</main>
);
}
export default Home;
To solve this issue, we need to create a component for the SVG, removing style properties from the SVG tag, such as width
, height
, and primarily fill
. These properties will be passed to the SVG through the className
property of the component. Here's how to do it:
import { twMerge } from 'tailwind-merge';
interface CheckboxProps {
className?: string;
}
const Checkbox = ({ className }: CheckboxProps) => {
return (
<svg
xmlns='http://www.w3.org/2000/svg'
version='1.1'
id='Capa_1'
x='0px'
y='0px'
viewBox='0 0 512 512'
width='512'
height='512'
className={twMerge('w-20 h-20', className)}
>
<g>
<path d='M405.333,0H106.667C47.786,0.071,0.071,47.786,0,106.667v298.667C0.071,464.214,47.786,511.93,106.667,512h298.667 C464.214,511.93,511.93,464.214,512,405.333V106.667C511.93,47.786,464.214,0.071,405.333,0z M426.667,172.352L229.248,369.771 c-16.659,16.666-43.674,16.671-60.34,0.012c-0.004-0.004-0.008-0.008-0.012-0.012l-83.563-83.541 c-8.348-8.348-8.348-21.882,0-30.229s21.882-8.348,30.229,0l83.541,83.541l197.44-197.419c8.348-8.318,21.858-8.294,30.176,0.053 C435.038,150.524,435.014,164.034,426.667,172.352z' />
</g>
</svg>
);
};
export default Checkbox;
Finally, our page.tsx
file will look like this:
import Image from 'next/image';
import Checkbox from '@/components/svg/Checkbox';
import checkbox from '../../public/icons/checkbox.svg';
const Home = () => {
return (
<main className='h-screen bg-zinc-800 flex items-center justify-center gap-6'>
<Image
src={checkbox}
alt='checkbox'
className='w-20 h-20 fill-white'
/>
<Checkbox className='fill-white hover:fill-red-600' />
</main>
);
};
export default Home;
Now, we can customize our SVG according to external application states and user actions, such as hover. It's a simple solution, but not very intuitive, as Next.js' <Image/>
tag doesn't handle this kind of scenario effectively.
Posted on October 18, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.