Peter Goes
Peter Goes

Reputation: 499

How to handle Sketch exported SVG with ids

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?

Upvotes: 15

Views: 4719

Answers (5)

Daniel Campagne
Daniel Campagne

Reputation: 1

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;
    }

Upvotes: 0

Angelique
Angelique

Reputation: 936

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/

Upvotes: 5

Jan Zikmund
Jan Zikmund

Reputation: 686

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.

Upvotes: 0

Nishant
Nishant

Reputation: 5089

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.

Upvotes: 0

Kim Seungha
Kim Seungha

Reputation: 29

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

Upvotes: -1

Related Questions