I’ve been working on something of a legacy project for a client of late, and about 5pm yesterday QA raised a bug. In the spirit of Sara Soueidan’s recent invocation to “Just Write”, I thought I’d write it up in case it’s helpful for anyone else.
At some point in the history of the project in question, it was updated to use SVG spritesheets in lieu of custom icon fonts. To do this, the author had used gulp-svg-sprite which, among other things, spits out the dimensions of the individual files into a CSS file for later use.
This has worked fine, right up until I created an icon with a gradient and came across a known bug where gradients aren’t handled correctly and therefore don’t work in Firefox. Unfortunately, while the issue has been fixed in the repo, it doesn’t seem to have been made available in a public release at time of writing.
After a bit of poking around, I opted to fix this by replacing gulp-svg-sprite with my usual combination of gulp-svgstore and gulp-svgmin, with a wee bit of custom glue to generate the required CSS file.
Let’s write some code
The usual invocation when using gulp-svgstore is something like this:
If you’re not au fait with gulp, this ingests all SVG files in the specified directory, compiles them
into a single file of SYMBOL
elements and saves the resulting file in output/directory/spritesheet.svg
.
So what about generating the CSS file?
I’m sure there are other ways of doing this but, inspired by an example in the gulp-svgstore documentation, I elected to process the output stylesheet thus:
I’m using through2 (mostly out of habit) to give me a slightly nicer interface for dealing with the inbound/outbound file stream, and Cheerio to parse the SVG and provide a jQuery-like interface for ease of traversal.
Otherwise, the actual process of finding SYMBOL
s and generating individual CSS rules based on their IDs is
relatively simple.
Things to mention
I mentioned gulp-svgmin earlier, but have not included it in either section of code as it’s not really part of the
process in question, but for completeness’ sake, I tend to use it after gulp-svgstore to tidy up the generated code
and remove any unwanted elements/attributes.
In the case of this project, I also used it before gulp-svgstore to try and normalise everything before generating the
spritesheet (because legacy/folk blindly exporting from Illustrator without tidying things up first).
More significantly, I also found that in some cases, gulp-svgstore occasionally strips the viewBox
attribute
from the SYMBOL
element (even if the source SVG file had one). I wasn’t able to work out why (it was late in
the evening and I wanted to go home), so I wound up processing individual files in a separate gulp task:
It’s a slightly different approach, but the overall process is pretty much the same: it just modifies the contents of the individual streams being processed & concatenates the result, rather than doing it all in one place.
Of course, whether or not you need to do it this way will depend on circumstance: I’ve tested the first approach—processing the spritesheet—with a number of other projects I’ve worked on in the past couple years and it’s worked fine each time. I’m assuming there’s something about the way some of the SVGs were generated in this most recent project that required the alternative approach 🤷♂️
Of course, the internet being the internet, there’s almost certainly a node module that does this automatically and I didn’t find it while I was searching last night, but this was an interesting foray into the world of node and gulp so hey.
Maybe this will be useful to someone—share and enjoy :)