jpkleemans / vite-svg-loader

Vite plugin to load SVG files as Vue components
MIT License
554 stars 58 forks source link

ID Conflict on Defs #101

Closed AngeloSchulerPiletti closed 1 year ago

AngeloSchulerPiletti commented 1 year ago

Hello, everyone.

I am facing the following issue (which I am still not a 100% sure it's related to vite-svg-loader):


Context

I have this icon:

<svg viewBox="0 0 319 139" fill="none" xmlns="http://www.w3.org/2000/svg">
  <path d="M80 96V0L0 96H80Z" fill="url(#paint0_linear_2268_23508)"/>
  <defs>
    <linearGradient id="paint0_linear_2268_23508" x1="40" y1="0" x2="40" y2="96" gradientUnits="userSpaceOnUse">
      <stop stop-color="#6AFF35" stop-opacity="0"/>
      <stop offset="1" stop-color="#6AFF35"/>
    </linearGradient>
  </defs>
</svg>

But, the code I see on build (on the browser) it's actually:

<svg viewBox="0 0 319 139" fill="none" xmlns="http://www.w3.org/2000/svg" class="icon self-start w-full max-lg:max-w-[354px] lg:col-start-6 lg:col-end-13" data-v-4fce6f9d="" data-v-9befdb10="">
   <path d="M80 96V0L0 96h80Z" fill="url(#a)"></path>
   <defs>
      <linearGradient id="a" x1="40" y1="0" x2="40" y2="96" gradientUnits="userSpaceOnUse">
         <stop stop-color="#6AFF35" stop-opacity="0"></stop>
         <stop offset="1" stop-color="#6AFF35"></stop>
      </linearGradient>
   </defs>
</svg>

I am rendering this icon in a Nuxt 3 application inside a dynamic component like this:

<script setup lang="ts">
import { defineAsyncComponent } from 'vue';
import { IconsTypes } from '~/types/icons.types';

export interface Props {
  name: string;
  type?: IconsTypes;
}

const props = withDefaults(defineProps<Props>(), {
  type: 'outline',
});

const IconComponent = defineAsyncComponent(
  () => import(`../../assets/icons/${props.type}/${props.name}.svg`)
);
</script>

<template>
  <component
    :is="IconComponent"
  />
</template>


Problem

As you can see, the built SVG had its defs linearGradient id changed, it causes a conflict with other icons' defs ids and makes the linearGradient to not work.

How it should be:

image

How it is:

Nothing is shown because it's transparent instead of the gradient.


What I think can be a solution

I believe that an option to make the vite-svg-loader ignore the id attribute would be great for this.

Final words

Again, I am not a 100% sure if this library is the cause of the problem, but I am sure it has to do with the id attribute of the SVG.

I will try to make a PR, and fix it.

Thank you for your attention

AngeloSchulerPiletti commented 1 year ago

Hello, again.

I just forked the repository and noticed it had a dependency with SVGO.

There is nothing to do with this library, everything it's working. But you need to add this configuration to avoid any id conflict.

vite.config.js

svgLoader({
   svgoConfig: {
       plugins: [
           'prefixIds',
       ]
   }
}),

This plugin works adding prefix IDs and classes with the SVG filename or an arbitrary string which avoid most of the conflicts.

Riyenz commented 6 months ago

Hello, again.

I just forked the repository and noticed it had a dependency with SVGO.

There is nothing to do with this library, everything it's working. But you need to add this configuration to avoid any id conflict.

vite.config.js

svgLoader({
   svgoConfig: {
       plugins: [
           'prefixIds',
       ]
   }
}),

This plugin works adding prefix IDs and classes with the SVG filename or an arbitrary string which avoid most of the conflicts.

This works for me