Ideal SVG exports
The following article is a random collection of opinions on how design tools should export SVGs. Do you agree? Feel free to let me know if you think something is missing or incorrect.
The XML declaration and namespace should be included in the header, especially if SVG 1.1 or newer is being used. I know skipping it saves some space, and doing so probably won’t cause issues, but it’s only an additional 88 bytes. If you’d like compact files, space can be saved other ways.
<?xml version="1.1" encoding="utf-8"?>
<svg viewBox="0 0 30 30" xmlns="http://www.w3.org/2000/svg" version="1.1">
...
</svg>
It should be optional to include the width and height in the SVG tag, so it’s possible to create images that resize to fit their container, or images that maintain a set size. Omitting the width and height is the same as setting them both to 100%.
<!-- Resizes to fit container -->
<svg viewBox="0 0 30 30" xmlns="http://www.w3.org/2000/svg" version="1.1">
<!-- Maintains fixed size -->
<svg width="30" height="30" viewBox="0 0 30 30" xmlns="http://www.w3.org/2000/svg" version="1.1">
I don‘t need to know which tool created an SVG. I’d prefer the exported file was completely absent of comments like the one below. I realise this could be handy for debugging, but it feels more like marketing to me. Skip it.
<!-- Generator: Adobe Illustrator 26.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
By default, layer names should not be inserted as IDs or data attributes. Including layer names as IDs makes SVGs larger, harder to edit, and there’s a potential risk of information being unwillingly shared. There are situations where it can be handy, so providing an option is good.
<!-- This just makes SVGs larger and harder to edit -->
<rect id="Rectangle_1" data-name="Rectangle 1" x="10" y="10" width="10" height="10"/>
If a value is entered into a design tool, the same value should appear in the SVG, assuming the output isn’t intentionally scaled, transformed, or rounded. It feels strange to mention this, but some tools get it wrong.
<!-- This shouldn’t happen if 10 was set as width and height -->
<rect x="10" y="10" width="9.999999" height="9.999999"/>
Rounding on export should be controllable. For production assets you’d like to keep as small as possible, having a 3 or so decimal places of precision might be enough. For transporting artwork at the highest quality possible between tools, 7+ or a way to disable rounding entirely might be needed.
<!-- Control over rounding precision is important -->
<rect x="10.001" y="10.001" width="10" height="10"/>
Positions and sizes should be resolved to node elements, and transforms should not be used, unless rotate or skew are included to preserve a primitive shape.
<!-- This is nice -->
<rect x="10" y="10" width="10" height="10"/>
<!-- This is not as nice -->
<rect width="10" height="10" transform="translate(10 10)"/>
Where possible, primitives should be used. This means rectangles and rounded rectangles should be <rect>, circles should be <circle>, and ellipses should be <ellipse>. Paths should only be used for things that can not be primitive shapes.
<!-- This is nice -->
<rect x="10" y="10" width="10" height="10" rx="1.1"/>
<!-- This is not as nice -->
<path d="M20,11.1c0,-0.607 -0.493,-1.1 -1.1,-1.1l-7.8,0c-0.607,0 -1.1,0.493 -1.1,1.1l0,7.8c0,0.607 0.493,1.1 1.1,1.1l7.8,0c0.607,0 1.1,-0.493 1.1,-1.1l0,-7.8Z"/>
I prefer hex values over named colours (“hotpink”, “cyan” etc) for tool generated SVGs. There’s nothing wrong with named colours, and they can sometimes be shorter, but I would rather the exporting be consistent across all colours.
Colours must also be converted to sRGB, if the design tool or document is in another colour space. SVGs can only currently be sRGB, and if colours aren’t converted, they’ll probably look incorrect.
I’d like the choice between using CSS styles and inline styles. Both can be good, depending on the situation. CSS styles shouldn’t be wrapped in <defs>.
<!-- This is good -->
<style>
.c { fill: #ff69b4; }
</style>
<rect class="c" x="10" y="10" width="10" height="10"/>
<!-- This is also good -->
<rect fill="ff69b4" x="10" y="10" width="10" height="10"/>
For path commands, it’d be nice to have a choice between relative and absolute coordinates, with the default being absolute. Bonus points awarded for a third option that automatically uses the method that creates the smallest string. If you ever need to convert path commands between relative and absolute, Lea Verou’s converter is excellent.
<!-- Relative coordinates -->
<path d=M9,9c-1,1,-9,1,-9,1c0,0,0,-8,1,-9s9,-1,9,-1c0,0,0,8,-1,9z/>
<!-- Absolute coordinates -->
<path d=M9,9C8,10,0,10,0,10C0,10,0,2,1,1S10,0,10,0C10,0,10,8,9,9Z/>
It’s nice to have the ability to keep text editable, contained within text tags. It’s also nice to be able to convert text to paths. Converting text to paths typically creates a much larger file, but it also means text renders correctly, even if the font is not available. It’s only appropriate for single words or short phrases though.
<!-- Text -->
<text x="10" y="10">a</text>
<!-- Text converted to a path -->
<path d="M14.08984,16l-.08398-.73145h-.03613c-.32373,.45557-.94727,.86328-1.7749,.86328-1.17529,0-1.7749-.82764-1.7749-1.66699,0-1.40332,1.24707-2.1709,3.48975-2.15869v-.12012c0-.47949-.13184-1.34326-1.31885-1.34326-.54004,0-1.10352,.16797-1.51123,.43164l-.24023-.69531c.47998-.31201,1.17529-.51562,1.90723-.51562,1.7749,0,2.20654,1.21094,2.20654,2.37451v2.1709c0,.50342,.02393,.99512,.09619,1.39111h-.95947Zm-.15625-2.9624c-1.15137-.02393-2.4585,.18018-2.4585,1.30713,0,.68359,.45605,1.00781,.99561,1.00781,.75537,0,1.23535-.47998,1.40332-.97168,.03564-.10791,.05957-.22803,.05957-.33594v-1.00732Z"/>
Inner and outer strokes are not yet supported in SVGs. Only centered strokes are possible. This means inner and outer strokes need to be outlined when exported, or masked with a clipping path, which adds complexity.
Attempting to offset a path to convert an inner or outer stroke into a centered stroke doesn’t yield the same result in many scenarios. Even closed paths consisting only of straight line segments can not always be replicated by offsetting the path and using a centered stroke. This just isn’t a viable technique and it should not be used.
It’d be great to have a choice between minified SVGs where everything’s as compact as possible, and beautified SVGs that contain line breaks and indenting, which make debugging and further editing easier.
Published 12 April 2022.