How to Customize SVGs using Next.js and Tailwind CSS
Tags: nextjs, tailwindcss, svg, react
Published: 2023-10-18 21:40:35

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

```xml
<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.

```javascript
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;
```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8bxsgnlcdgajz0zgrom9.png)

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:

```javascript
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:

```javascript
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;
```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3rect0cyikyo307oew3l.png)

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.