Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to handle duplicate IDs for inline SVGs?

Tags:

css

php

svg

I am using the same SVG multiple times on a webpage. The SVGs are inserted on the server side with PHP like this:

<?php echo file_get_contents("myimage.svg"); ?>

The SVG contains a gradient, which should have different colors on different instances of the SVG.

An HTML document delivered by the server may look like the following snippet. The same SVG has been inserted twice:

#image1 .stop1 { stop-color: #FDF39C }
#image1 .stop2 { stop-color: #FE8A77 }
#image2 .stop1 { stop-color: #64E8EA }
#image2 .stop2 { stop-color: #A79CFC }
<div id="image1">
  <svg width="256" height="256" viewBox="0 0 256 256">
    <defs>
      <linearGradient id="gradient1">
        <stop class="stop1" offset="0%"/>
        <stop class="stop2" offset="100%"/>
      </linearGradient>
    </defs>
    <circle fill="url(#gradient1)" cx="128" cy="128" r="100" />
  </svg>
</div>
<div id="image2">
  <svg width="256" height="256" viewBox="0 0 256 256">
    <defs>
      <linearGradient id="gradient1">
        <stop class="stop1" offset="0%"/>
        <stop class="stop2" offset="100%"/>
      </linearGradient>
    </defs>
    <circle fill="url(#gradient1)" cx="128" cy="128" r="100" />
  </svg>
</div>

The problem is that both instances of the SVG display the gradient defined in the first SVG. Here is a comparison of the actual vs the intended result:

enter image description here

The reason for this is that the gradients of both inline SVGs have the same ID gradient1, because the same SVG which contains that ID is inserted twice on the server. The circle elements' fill is set to url(#gradient1) in both cases, which the browser simply links to the first occurence of that ID, which is the gradient definition in the first SVG. This behavior is correct, but for my case this is a problem.

The question is: How do I avoid duplicate ids? I worked with SVG injection using SVGInject, and this solved the problem by making the IDs unique. SVGInject simply adds a random string to the end of IDs, for example changing gradient1 to gradient1-h4w7xo82.

However, I do not see a solution when inserting the SVGs with PHP. Can you help?

like image 784
VickyB Avatar asked Sep 19 '18 10:09

VickyB


1 Answers

Convert the svg file into php so you can pass the gradientId parameter into it.

<?php
  header('Content-Type: image/svg+xml');

  echo '<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="256" height="256" viewBox="0 0 256 256">
    <defs>
      <linearGradient id="' . $gradientId . '">
        <stop class="stop1" offset="0%"/>
        <stop class="stop2" offset="100%"/>
      </linearGradient>
    </defs>
    <circle fill="url(#' . $gradientId . ')" cx="128" cy="128" r="100" />
  </svg>';
?>
like image 142
gazdagergo Avatar answered Oct 20 '22 14:10

gazdagergo