Add support for inlining multiple SVG images on page without ID collisions

Created on 3 May 2023, over 1 year ago
Updated 18 June 2023, over 1 year ago

Problem/Motivation

SVGs are particularly useful to run inline, allowing mouseover style changes, etc. However, many SVGs exported by various programs reuse classes and IDs internally, and these collide with bad results.

Steps to reproduce

Here is an example of part of an SVG causing us trouble:

<svg id="background_Image" data-name="background Image" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 439.71 82.27">
  <defs>
    <style>
      .cls-1 {
        fill: url(#New_Gradient_Swatch_5);
      }

      .cls-2 {
        fill: url(#New_Gradient_Swatch_5-2);
      }

      .cls-3 {
        fill: url(#New_Gradient_Swatch_4);
      }
    </style>
    <linearGradient id="New_Gradient_Swatch_5" data-name="New Gradient Swatch 5" x1="35.02" y1="40.42" x2="35.02" y2="173.46" gradientUnits="userSpaceOnUse">
      <stop offset="0" stop-color="#9ad4f3"/>
      <stop offset=".45" stop-color="#52b9e7"/>
      <stop offset="1" stop-color="#009ad9"/>
    </linearGradient>
    <linearGradient id="New_Gradient_Swatch_5-2" data-name="New Gradient Swatch 5" y1="45.35" x2="35.02" y2="69.97" xlink:href="#New_Gradient_Swatch_5"/>
    <linearGradient id="New_Gradient_Swatch_4" data-name="New Gradient Swatch 4" x1="35.02" y1="41.71" x2="35.02" y2="5.2" gradientUnits="userSpaceOnUse">
      <stop offset="0" stop-color="#ffd74f"/>
      <stop offset="1" stop-color="#f68f1e"/>
    </linearGradient>
  </defs>
  <g class="glyphBlue">
    <path class="cls-1" d="m35.02,72.72c4.44,0,8.74.59,12.83,1.69l6.65-24.8c-6.21-1.66-12.74-2.55-19.48-2.55s-13.26.89-19.48,2.55l6.65,24.8c4.09-1.09,8.39-1.69,12.83-1.69Z"/>
    <path class="cls-2" d="m35.02,72.72c4.44,0,8.74.59,12.83,1.69l6.65-24.8c-6.21-1.66-12.74-2.55-19.48-2.55s-13.26.89-19.48,2.55l6.65,24.8c4.09-1.09,8.39-1.69,12.83-1.69Z"/>
  </g>
  <g class="glyphBurst">
    <path class="cls-3" d="m11.72,35.35l-3.98-14.87,14.37-15.73-10.38,30.59ZM47.93,4.75l10.38,30.6,3.98-14.87-14.36-15.73ZM6.6,16.21l7.72-11.12c-3.42.6-6.79,1.35-10.11,2.23l2.38,8.9Zm19.56,24.84l2.62-34.37L12.66,38.83l1.21,4.52c3.99-1.07,8.09-1.84,12.29-2.29Zm30.01,2.29l1.21-4.51L41.26,6.68l2.61,34.37c4.2.45,8.31,1.23,12.3,2.29Zm-14.56-2.51l-6.59-33.23-6.6,33.23c2.18-.17,4.38-.27,6.6-.27s4.42.09,6.6.27ZM55.71,5.08l7.73,11.13,2.38-8.9c-3.32-.88-6.69-1.63-10.11-2.23Z"/>
  </g></svg>

... and we need to place this on the page twice. We have another SVG also placed on the page twice, which re-uses the .cls-1, .cls-2, .cls-3 classes with different definitions.

The first image on the page renders the .glyphBurst section correctly, but the .glyphBlue does not render with the gradients -- instead it picks up a solid color from the other SVG on the page.

The second image on the page cannot find the "#New_Gradient_Swatch_4" for the GlyphBurst, presumably because it now sees it twice on the page, so it doesn't render it at all. The glyphBlue here also renders the solid color from the other SVG.

Proposed resolution

When inlining SVGs, rewrite internal classes and IDs to include a per-instance hash of some kind.

More info:

https://stackoverflow.com/questions/52403282/how-to-handle-duplicate-ids...

https://www.antonball.dev/blog/2020-06-15-svg-id-collision/

Remaining tasks

User interface changes

API changes

Data model changes

✨ Feature request
Status

Active

Version

2.2

Component

Code

Created by

πŸ‡ΊπŸ‡ΈUnited States freelock Seattle

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @freelock
  • πŸ‡ͺπŸ‡¨Ecuador jwilson3

    This is an interesting idea. Drupal 10.1 now has a new feature that might make implementing the logic for unique ids a bit easier New clean_unique_id Twig filter β†’ .

    I can foresee potential unexpected behaviors if a given id is present in a file more than once, but I guess that would be a problem that the person who uploaded the faulty SVG would be responsible for identifying and fixing.

Production build 0.71.5 2024