14

I want to use svg icons in my page. The designers I work with use Sketch to design the image and export the result in svg. Sketch adds various id tags to the exported code (note the id="Page-1", id="My-Star" and id="Star-1" attributes):

<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
        <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
            <g id="My-Star" stroke="#979797" fill="#D8D8D8">
                <polygon id="Star-1" points="11.9860934 18.5835921 5.4876995 22 6.7287823 14.763932 1.47147118 9.63932023 8.73689646 8.58359214 11.9860934 2 15.2352904 8.58359214 22.5007157 9.63932023 17.2434045 14.763932 18.4844873 22 "></polygon>
            </g>
        </g>
    </svg>

I include the svg directly in the html. By doing this, I introduce the same id multiple times. Besides the invalid html that is a result of this way of working, I need to style the svg elements based on ids. This is a bad practice.

I use css to style the svgs, take a look at an example

The question:
Is there a way to replace the ids with classes when exporting svgs from Sketch? Is there some plugin or setting I can give to the designers? If not, what is the optimal workflow in receiving svg assets from designers and using it in the page?

Alexandr_TT
  • 13,635
  • 3
  • 27
  • 54
Peter Goes
  • 459
  • 4
  • 12

5 Answers5

4

I highly recommend adding svgo to your workflow if you're dealing with SVGs exported via Sketch. Not only will the tool eliminate unused IDs (you're still on the hook for manually resolving IDs that are used by the SVG), it will also optimize the SVG better than the default SVG export.

If you're doing this often, adding SVGO to your dev/build process (see examples); if you just want to take it for a test run, however, there's also a web-based GUI: https://jakearchibald.github.io/svgomg/

Angelique
  • 906
  • 7
  • 15
  • 1
    Alternatively, the designers could install the official SVGO plugin for Sketch. https://www.sketch.com/extensions/plugins/svgo-compressor/ – felideon Jun 18 '20 at 15:37
0

Looks like there is no good solution others than asking designers to use unique group names.

The group names become group ids in the generated SVG.

Nishant
  • 4,659
  • 2
  • 27
  • 43
0

I didn't find any solution in Sketch itself, but I found a simple walk-around using PHP. In Sketch, I name each group or path that I want as class starting with a . dot, eg .person, and export the file. Obviously the group still has id=".person"

And then I load the .svg into page using PHP and replace all IDs that start by a dot by class: <?php echo str_replace('id=".', 'class="', file_get_contents( 'sample.svg' )); ?>

I know it's not ideal but works in my case.

Jan Zikmund
  • 646
  • 9
  • 19
0

I fixed it by adding a different prefix to the IDs included on each SVG. To avoid glitches, it hides the SVGs until the prefixes are added to the IDs.

CSS:

    svg {
        opacity: 0;
        transition: opacity .5s ease-in-out;
    }
    svg.svg-visible {
        opacity: 1;
    }

JS:

    function replaceAll(str, find, replace) {
      var escapedFind=find.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1");
      return str.replace(new RegExp(escapedFind, 'g'), replace);
    }
    
    var svgCounter = 0;
    
    [].forEach.call(document.querySelectorAll('svg'), function(el) {
      var contentReplaced = replaceAll(el.innerHTML,'id="','id="n' + svgCounter); 
      contentReplaced = replaceAll(contentReplaced,'url(#','url(#n' + svgCounter);
      contentReplaced = replaceAll(contentReplaced,'xlink:href="#','xlink:href="#n' + svgCounter);
      el.innerHTML = contentReplaced;
      el.classList.add('svg-visible');
      svgCounter++;
    })

You can also make it cleaner using PHP:

    function inlinesvg($module, $svg) {
        $id = 'svg-' . substr(md5(uniqid(mt_rand(), true)) , 0, 8);
        $file_contents = file_get_contents('./assets/img/'.$module.'/'.$svg.'.svg');
        $file_contents = str_replace('id="','id="' . $id, $file_contents);
        $file_contents = str_replace('url(#','url(#' . $id, $file_contents);
        $file_contents = str_replace('xlink:href="#','xlink:href="#' . $id, $file_contents);
        echo $file_contents;
    }
shaedrich
  • 5,457
  • 3
  • 26
  • 42
-1

I ran into the same problem, so made a plugin. With this plugin, all ids in svg exported from slices are namespaced in BEM style.

https://github.com/Knowre-Dev/svg-namespacing

  • 1
    Looking at the code of your plugin, you replace the _content_ of the `id` attribute. But the `id` attribute remains in the file. That means that when you have multiple identical svgs in your html document, you end up with multiple occurrences of the same id. I was looking for a way replace the `id` attribute with a `class`attribute, but keep its content. Your plugin did give me a starting point of writing my own plugin. So thank you for that! – Peter Goes Aug 03 '16 at 07:39