Reputation: 499
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 id
s. 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 id
s with class
es 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
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
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
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
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
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