I’ve always felt like when it comes to using icons in CSS, we can do better than font icons and sprite sheets. Wouldn’t it be better if we could just specify the icons we want to use in our SASS directly, and have them inlined when compiled?
With the native SASS compiler there aren’t really any options to extend the functionality, but with the newer Dart SASS compiler, we can specify our own custom functions for use in our SASS code right in our webpack configuration. Those functions could be used to generate SVG data URI’s in the resulting CSS.
When I was developing my updated website, I decided to do just that with Material Design Icons, and take it to the next level by adding rotation and scaling options. This post is about how I accomplished all that.
// Parse the name and get any extra parameters. const nameValue = name.getValue(); const [named, ...params] = nameValue.split(/\s+/);
// Parse any extra parameters. const width = 24; const height = 24; const transforms = []; const props = { rotate: (deg, x = 0.5, y = 0.5) => { const xo = width * +x; const yo = height * +y; transforms.push( `rotate(${deg}${xo}${yo})` ); }, scale: (x, y = null) => { y = y === null ? x : y; const xo = (1 - +x) * width * 0.5; const yo = (1 - +y) * height * 0.5; transforms.push( `translate(${xo}${yo})`, x === y ? `scale(${x})` : `scale(${x}${y})` ); } }; while (params.length) { const [type, ...args] = params.shift().split(':'); const prop = props[type]; if (!prop) { thrownewError(`Unknown type: ${type} in ${nameValue}`); } prop(...args); }
// Create the XML code and the data URI url code. const xml = mdiSvg( named, { width, height, fill: color.toString() }, { transform: transforms.length ? transforms : null } ); returnnew sass.types.String(`url("${svgToTinyDataUri(xml)}")`); } };
Now create the main JS and SCSS files. In the SCSS file we create a thin wrapper around the custom function which helps with autocomplete in some editors.
Every use of the function outputs a copy of the SVG data, optionally with some extra transform data. Gzip is good at compressing repeating strings, so this is not a huge issue, however defining the icons in reusable classes can keep the code even smaller.
Comments