Playing with SVGs
Advanced Customization and Gradient Hacks in React
SVG is one of my favourite formats for images in apps. It’s clean, scalable, and customisable
Need the same icon to work on both light and dark backgrounds? We usually change the color in iconsets. But what about site logos or custom icons downloaded from Figma? Do we make the user download multiple files just to handle a complex gradient change?

Instead, we should identify the hard-coded values in the SVG. If you read the SVG code, you’ll notice that the colour often comes from a block of linearGradient code. Specifically, the stop-color attribute. This might vary for other SVGs, so look out for fill and stroke parameters. They may contain direct colours or point to another element using the url function. If a url is used, locate the <defs> element with the corresponding ID (Image shows path pointing to <defs> with ID “g1“

Strategy 1: The Custom Component (CSS Variables)
How do we do this with a single SVG file in React?
First, save the SVG as a component rather than importing it as an image.
You need to replace the static ID (like "g1") with a unique, dynamic ID. This is crucial because we are referencing a DOM element in the fill by its ID. It will always take the value of the first occurrence in the DOM, so if different instances need different colours, they require a unique ID. Also, don’t miss the hash (#) symbol when writing the url access string.
Finally, assign CSS variables to the
stopColorattribute. I prefer adding a default fallback value to the variables for safety, likevar(--color, "#455673").
You can now use a single SVG component for multiple variations.



Strategy 2: The "External Defs" Trick (For Icon Sets)
What about icon sets like Hugeicons? Often, gradient features are locked behind "Pro" tiers, or the library simply doesn't support them.
We can bypass this by defining a gradient in a separate, invisible SVG and referencing it in the icon's stroke.
Step 1: Create a Gradient Definition Component
This component renders an invisible SVG (height=0, width=0) that serves purely as a container for your gradient definition.
const SVGDefinition = ({ id, className }) => {
return (
<svg
className="absolute inline h-0 w-0"
aria-hidden="true" // Good for accessibility since this is invisible
>
<defs>
<linearGradient
id={id}
x1="0" y1="0" x2="0" y2="100%" // gradient
gradientUnits="userSpaceOnUse"
className={className} // If using Tailwind classes for colors
>
{/* Use stopColor (camelCase) */}
<stop offset="0%" stopColor="var(--gradient-from)" />
<stop offset="100%" stopColor="var(--gradient-to)" />
</linearGradient>
</defs>
</svg>
);
};
Step 2: Apply it to the Icon
Place the definition alongside your icon, then override the icon's stroke style to point to your new gradient ID.
const Component = () => {
const gradientId = 'unique_gradient_id'; // Descriptive variable name
return (
<span className="relative">
<SVGDefinition id={gradientId} />
<IconFromIconset
style={{
// React inline styles require quotes and comma separation
stroke: `url(#${gradientId}) !important`,
}}
/>
</span>
);
}

Why this works
The url(#id) syntax in SVG doesn't care where the ID live. It just looks for a matching ID anywhere in the DOM. By injecting our own <defs> nearby, we can "paint" the third-party icon with our custom gradient.
Notes:
The defined gradient needs to be position absolute with
width:0andheight:0. This ensures it doesn’t take up any physical space on your page.If this gradient is a primary brand colour used everywhere, you can simply add this definition to the top of your body tag to reduce overhead. You wouldn't need a wrapper in that case, just use the icon with the adjusted stroke value.
I have tested this approach on size, stroke widths, fill, and filter attributes. Let me know if you find something intersting or have any feedback :D
References:
https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Element/defs#/
https://developer.mozilla.org/ru/docs/Web/SVG/Reference/Element/linearGradient#/
https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/stop-color#/
Previously published on Medium

