Change Gradient Colors in SVG in C#

Quick Answer

To change SVG gradient colors in C#, load the file with SVGDocument, select a <linearGradient> or <radialGradient> with QuerySelector(), update its <stop> elements with SetAttribute(), and save the edited SVG. If a shape should use another gradient, set fill or stroke to url(#gradientId). To export the result, pass the edited document to Converter.ConvertSVG().

This article shows how to edit gradient colors in an existing SVG file using Aspose.SVG for .NET. It focuses on applied recoloring workflows: finding <linearGradient> and <radialGradient> definitions, changing stop-color values, replacing fill="url(#id)" references, saving the updated SVG, and rendering the result to PNG.

This page is about changing gradients that already exist in an SVG document. If you need to create gradients from scratch, see SVG Gradients – SVG Code and C# Examples.

You will learn how to:

Aspose.SVG APIs Used

The examples use the Aspose.SVG DOM API to edit SVG markup and the converter API to render the edited result:

APIUsed for
SVGDocumentLoads and saves the SVG document
ElementRepresents selected gradients, stops, and painted shapes
QuerySelector()Selects one gradient or shape by CSS selector
QuerySelectorAll()Selects all gradient stops or all elements that reference a gradient
GetAttribute()Reads id, offset, stop-color, fill, stroke, or style values
SetAttribute()Updates gradient stops and paint server references
ImageSaveOptionsConfigures PNG, JPG, WebP, BMP, TIFF, or GIF output
Converter.ConvertSVG()Exports the edited SVG document to an image file

How SVG Gradient Colors Work

SVG gradients are reusable paint servers. A <linearGradient> or <radialGradient> element usually lives inside <defs>, has an id, and contains child <stop> elements:

1<linearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="0%">
2    <stop offset="10%" stop-color="lightsalmon" />
3    <stop offset="50%" stop-color="teal" />
4    <stop offset="90%" stop-color="lightpink" />
5</linearGradient>

A visible shape does not store the actual gradient colors. It references the gradient by ID:

1<ellipse fill="url(#grad1)" />

This means that a gradient recoloring workflow usually has two separate tasks:

TaskWhat to edit
Change the colors inside a gradientUpdate <stop> elements inside <linearGradient> or <radialGradient>
Make a shape use another gradientUpdate the shape’s fill or stroke attribute to url(#newGradientId)

Source SVG Used in Examples

The examples use linear-gradient.svg and radial-gradient.svg. The linear sample stores stop colors in the style attribute:

1<linearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="0%">
2    <stop offset="10%" style="stop-color:LIGHTSALMON" />
3    <stop offset="50%" style="stop-color:TEAL" />
4    <stop offset="90%" style="stop-color:LIGHTPINK" />
5</linearGradient>

The radial sample stores stop colors as stop-color attributes:

1<radialGradient id="myRG" cx="0.5" cy="0.5" r="0.9" fx="0.5" fy="0.5" spreadMethod="pad">
2    <stop offset="0%" stop-color="BISQUE" />
3    <stop offset="60%" stop-color="CADETBLUE" />
4</radialGradient>

Both forms are valid SVG. The examples below show how to handle each one.

Change Linear Gradient Stop Colors

The following example loads an SVG file, finds a <linearGradient> by ID, and assigns new colors to its stops. It uses the stop order because the sample has three fixed stops. For generated or design-tool SVG files, you can also match stops by their offset values.

 1using Aspose.Svg;
 2using Aspose.Svg.Dom;
 3using System;
 4using System.IO;
 5
 6// Load an SVG file that contains a linear gradient
 7using var document = new SVGDocument(Path.Combine(DataDir, "linear-gradient.svg"));
 8
 9// Find the linearGradient element by ID
10Element gradient = document.QuerySelector("linearGradient#grad1");
11
12if (gradient == null)
13{
14    throw new InvalidOperationException("Gradient 'grad1' was not found.");
15}
16
17string[] newColors =
18{
19    "#1565c0",
20    "#00acc1",
21    "#f9a825"
22};
23
24int index = 0;
25
26// Update each stop in the selected linear gradient
27foreach (Element stop in gradient.QuerySelectorAll("stop"))
28{
29    if (index >= newColors.Length)
30    {
31        break;
32    }
33
34    // Write stop-color as a presentation attribute
35    stop.SetAttribute("stop-color", newColors[index]);
36
37    // Remove a conflicting inline stop-color declaration if the source SVG used style
38    string style = stop.GetAttribute("style");
39    if (!string.IsNullOrWhiteSpace(style) &&
40        style.IndexOf("stop-color", StringComparison.OrdinalIgnoreCase) >= 0)
41    {
42        stop.RemoveAttribute("style");
43    }
44
45    index++;
46}
47
48// Save the SVG file with changed linear gradient colors
49document.Save(Path.Combine(OutputDir, "linear-gradient-recolored.svg"));

This approach keeps the gradient geometry unchanged. Only the colors of the transition are changed.

The figure shows the original linear gradient (a) and the same SVG after changing the <linearGradient> stop colors (b).

Original and recolored linear gradient in SVG

Change Radial Gradient Stop Colors

Radial gradients use the same stop structure as linear gradients. The difference is in the gradient geometry: a radial gradient transitions from a center or focal point outward. To recolor it, find the <radialGradient> and update its child <stop> elements.

 1using Aspose.Svg;
 2using Aspose.Svg.Dom;
 3using System;
 4using System.Collections.Generic;
 5using System.IO;
 6
 7// Load an SVG file that contains a radial gradient
 8using var document = new SVGDocument(Path.Combine(DataDir, "radial-gradient.svg"));
 9
10// Find the radialGradient element by ID
11Element gradient = document.QuerySelector("radialGradient#myRG");
12
13if (gradient == null)
14{
15    throw new InvalidOperationException("Gradient 'myRG' was not found.");
16}
17
18// Map gradient offsets to new stop colors
19var colorsByOffset = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
20{
21    ["0%"] = "#fce1ff",
22    ["60%"] = "#690058"
23};
24
25foreach (Element stop in gradient.QuerySelectorAll("stop"))
26{
27    string offset = stop.GetAttribute("offset")?.Trim();
28
29    if (!string.IsNullOrWhiteSpace(offset) &&
30        colorsByOffset.TryGetValue(offset, out string newColor))
31    {
32        stop.SetAttribute("stop-color", newColor);
33    }
34}
35
36// Save the SVG file with changed radial gradient colors
37document.Save(Path.Combine(OutputDir, "radial-gradient-recolored.svg"));

Matching by offset is useful when the number of stops can change or when you only want to recolor specific positions in the gradient.

The figure shows the original radial gradient (a) and the same SVG after changing radial gradient stop colors by offset (b).

Original and recolored radial gradient in SVG

Replace Stop Colors in All Gradients

For bulk editing, scan all gradient stops and replace only the stop colors that match a source value. This is useful for brand refreshes, template processing, or recoloring assets exported from design tools.

Replace stop-color Attributes

Some SVG files store gradient colors directly on <stop> elements, for example stop-color="BISQUE". In this case, read the stop-color attribute, compare it with the source palette, and write the replacement value back with SetAttribute().

Replace stop-color in Inline Styles

Other SVG files store the same value inside the style attribute, for example style="stop-color:TEAL". In this case, parse the inline CSS declarations and update only the stop-color declaration, leaving other style properties unchanged.

The following complete example handles both forms: stop-color attributes and inline style declarations.

 1using Aspose.Svg;
 2using Aspose.Svg.Dom;
 3using System;
 4using System.Collections.Generic;
 5using System.IO;
 6
 7using var document = new SVGDocument(Path.Combine(DataDir, "linear-gradient.svg"));
 8
 9var palette = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
10{
11    ["LIGHTSALMON"] = "#ff7043",
12    ["TEAL"] = "#0277bd",
13    ["LIGHTPINK"] = "#f06292"
14};
15
16// Select stops inside both linear and radial gradients
17foreach (Element stop in document.QuerySelectorAll("linearGradient stop, radialGradient stop"))
18{
19    string stopColor = stop.GetAttribute("stop-color");
20
21    // Replace stop-color written as an SVG attribute
22    if (!string.IsNullOrWhiteSpace(stopColor) &&
23        palette.TryGetValue(stopColor.Trim(), out string replacement))
24    {
25        stop.SetAttribute("stop-color", replacement);
26    }
27
28    string style = stop.GetAttribute("style");
29    if (string.IsNullOrWhiteSpace(style))
30    {
31        continue;
32    }
33
34    var updatedDeclarations = new List<string>();
35
36    foreach (string declaration in style.Split(';', StringSplitOptions.RemoveEmptyEntries))
37    {
38        string[] parts = declaration.Split(':', 2);
39
40        if (parts.Length != 2)
41        {
42            updatedDeclarations.Add(declaration.Trim());
43            continue;
44        }
45
46        string property = parts[0].Trim();
47        string value = parts[1].Trim();
48
49        if (property.Equals("stop-color", StringComparison.OrdinalIgnoreCase) &&
50            palette.TryGetValue(value, out replacement))
51        {
52            value = replacement;
53        }
54
55        updatedDeclarations.Add($"{property}: {value}");
56    }
57
58    stop.SetAttribute("style", string.Join("; ", updatedDeclarations));
59}
60
61document.Save(Path.Combine(OutputDir, "gradient-stops-replaced.svg"));

Use this pattern when you know the old colors and want to replace them wherever they appear in gradient stops. If you need to inspect the palette first, see Extract SVG Colors in C#.

Replace fill=“url(#id)” with Another Gradient

Sometimes the gradient colors are correct, but a shape references the wrong gradient. In that case, change the paint server reference on the shape instead of editing the stops.

Create a New Gradient Definition

First, create a new <linearGradient> element, assign it a unique id, add <stop> elements, and append the gradient to <defs>. The new gradient becomes available as a reusable paint server.

Update Fill References

Then find shapes that use the old paint server reference and set their fill attribute to the new url(#id) value. The following complete example changes every element that uses fill="url(#grad1)" so it uses fill="url(#newBrandGradient)" instead:

 1using Aspose.Svg;
 2using Aspose.Svg.Dom;
 3using System.IO;
 4
 5using var document = new SVGDocument(Path.Combine(DataDir, "linear-gradient.svg"));
 6
 7string oldGradientRef = "url(#grad1)";
 8string newGradientRef = "url(#newBrandGradient)";
 9
10// Create a new gradient definition.
11const string SvgNamespace = "http://www.w3.org/2000/svg";
12
13Element defs = document.QuerySelector("defs");
14Element newGradient = document.CreateElementNS(SvgNamespace, "linearGradient");
15newGradient.SetAttribute("id", "newBrandGradient");
16newGradient.SetAttribute("x1", "0%");
17newGradient.SetAttribute("y1", "0%");
18newGradient.SetAttribute("x2", "100%");
19newGradient.SetAttribute("y2", "0%");
20
21Element firstStop = document.CreateElementNS(SvgNamespace, "stop");
22firstStop.SetAttribute("offset", "0%");
23firstStop.SetAttribute("stop-color", "#1a237e");
24
25Element secondStop = document.CreateElementNS(SvgNamespace, "stop");
26secondStop.SetAttribute("offset", "100%");
27secondStop.SetAttribute("stop-color", "#26c6da");
28
29newGradient.AppendChild(firstStop);
30newGradient.AppendChild(secondStop);
31defs.AppendChild(newGradient);
32
33// Repoint shapes from the old gradient to the new gradient.
34foreach (Element element in document.QuerySelectorAll("[fill]"))
35{
36    string fill = element.GetAttribute("fill");
37
38    if (!string.IsNullOrWhiteSpace(fill) &&
39        fill.Trim() == oldGradientRef)
40    {
41        element.SetAttribute("fill", newGradientRef);
42    }
43}
44
45document.Save(Path.Combine(OutputDir, "gradient-fill-reference-updated.svg"));

The same idea works for gradient strokes. Search [stroke] and set stroke="url(#newGradientId)".

The figure shows the original SVG using a three-stop gradient fill="url(#grad1)" (a) and the result after repointing the same shapes to a newly created two-stop gradient fill (b).

SVG fill reference updated to a new gradient

Save and Export the Edited SVG to PNG

After editing the SVG document, you can save it as SVG and export the same in-memory document to PNG. The PNG output reflects the new gradient colors and updated paint references.

 1using Aspose.Svg;
 2using Aspose.Svg.Converters;
 3using Aspose.Svg.Dom;
 4using Aspose.Svg.Saving;
 5using System.IO;
 6
 7using var document = new SVGDocument(Path.Combine(DataDir, "radial-gradient.svg"));
 8
 9Element gradient = document.QuerySelector("radialGradient#myRG");
10
11foreach (Element stop in gradient.QuerySelectorAll("stop"))
12{
13    string offset = stop.GetAttribute("offset")?.Trim();
14
15    if (offset == "0%")
16    {
17        stop.SetAttribute("stop-color", "#fffde7");
18    }
19    else if (offset == "60%")
20    {
21        stop.SetAttribute("stop-color", "#283593");
22    }
23}
24
25string svgOutputPath = Path.Combine(OutputDir, "radial-gradient-edited.svg");
26string pngOutputPath = Path.Combine(OutputDir, "radial-gradient-edited.png");
27
28// Save the editable SVG result
29document.Save(svgOutputPath);
30
31// Export the edited SVG document to PNG
32var options = new ImageSaveOptions();
33Converter.ConvertSVG(document, options, pngOutputPath);

Use this workflow when your application needs both an editable vector output and a raster preview or thumbnail.

Common Mistakes and Fixes

ProblemCauseFix
The visible shape did not changeThe code changed fill on a shape that uses fill="url(#id)"Edit the referenced gradient stops, or replace the url(#id) reference
The stop color still looks unchangedA style="stop-color:..." declaration overrides or duplicates the stop-color attributeUpdate the style declaration or remove it after setting stop-color
Only one shape changed unexpectedlySeveral shapes share the same gradient definitionDuplicate or create a new gradient and point only selected shapes to the new url(#id)
The new gradient is not appliedThe id in url(#id) does not match the gradient’s idKeep the reference and gradient ID exactly aligned
A gradient is not found by selectorThe SVG uses a different ID or generated IDs from a design toolInspect the SVG first or query all linearGradient, radialGradient elements
Exported PNG does not show the latest colorsThe file was converted before edits were applied or a different document instance was convertedSave or convert the edited SVGDocument instance after all updates

FAQ

How do I change SVG gradient colors in C#?
Load the SVG with SVGDocument, find the <linearGradient> or <radialGradient> element, select its child <stop> elements, and update their stop-color values with SetAttribute().

How do I edit linearGradient stops?
Select the gradient with a selector such as linearGradient#grad1, then iterate through gradient.QuerySelectorAll("stop"). You can update stops by order, by offset, or by matching the current color.

How do I replace stop-color in SVG?
For stop-color attributes, call stop.SetAttribute("stop-color", newColor). If the SVG stores the value in style="stop-color:...", parse the style attribute and update that declaration as well.

Why does changing fill not change the gradient colors?
When fill is url(#id), it points to a gradient definition. The actual colors are stored in the gradient’s <stop> elements, not in the shape’s fill attribute.

Can several shapes use the same gradient?
Yes. If you edit the shared gradient definition, every shape that references it changes. To recolor only one shape, create a new gradient or duplicate the existing one, then update that shape’s fill or stroke reference.

Can I export the edited gradient SVG to PNG?
Yes. After changing the SVGDocument, create ImageSaveOptions and call Converter.ConvertSVG(document, options, outputPath).

Related Resources