331 lines
12 KiB
Markdown
331 lines
12 KiB
Markdown
# SVG Guidelines
|
|
|
|
## Pros and cons of SVG for images
|
|
|
|
When used as a document format there is usually a compelling reason that
|
|
makes SVG the only solution. When used as an [image
|
|
format](https://developer.mozilla.org/en-US/docs/Web/SVG/SVG_as_an_Image),
|
|
it is sometimes less obvious whether it would be best to use SVG or a
|
|
raster image format for any given image. The vector format SVG and
|
|
raster formats like PNG both have their place. When choosing whether or
|
|
not to use SVG it is best to understand the advantages and disadvantages
|
|
of both.
|
|
|
|
File size
|
|
|
|
: Whether SVG or a raster format will produce a smaller file for a
|
|
given image depends very much on the image. For example, consider an
|
|
image of a path with a gradient fill. The size of an SVG of this
|
|
image will be the same regardless of the dimensions of the image. On
|
|
the other hand the size of a raster file of the same image will
|
|
likely vary tremendously depending on the dimensions of the image
|
|
since the larger the dimensions the more pixel data the file needs to
|
|
store. At very small dimensions (the extreme case being 1px x 1px)
|
|
the raster file will likely be much smaller than the SVG file since
|
|
it only needs to store one pixel of data. At large dimensions the
|
|
raster file may be much larger than the SVG file.
|
|
|
|
Scalability, with caveats
|
|
|
|
: One of the primary advantages of SVG is that as it is scaled it does
|
|
not pixelate. However, this is not to say that it always does away
|
|
with the need to have a collection of raster images for display at
|
|
different scales. This can be particularly true for icons. While SVG
|
|
may scale well enough for flat-ish icons without a lot of detail, for
|
|
icons that try to pack in a lot of detail graphic artists generally
|
|
[want to be able to pixel
|
|
tweak](https://www.pushing-pixels.org/2011/11/04/about-those-vector-icons.html).
|
|
|
|
Performance
|
|
|
|
: While SVG provides a lot of flexibility in terms of scaling,
|
|
themability, etc. this flexibility depends on doing computations for
|
|
SVG images at the time they're displayed, rather than at the time the
|
|
author creates them. Consider an image that involves some complex
|
|
gradients and filters. If saved as a raster image then the work to
|
|
rasterize the gradients and filters takes place on the authors
|
|
computer before the result is stored in the raster file. This work
|
|
doesn't need to be redone when the image is displayed on someone
|
|
else's computer. On the other hand, if the image is saved as an SVG
|
|
image then all this work needs to be done each time the SVG is
|
|
displayed on someone else's computer. This isn't to say that SVG
|
|
images are always slower than raster equivalents. In fact it can be
|
|
faster to send vector information from an SVG to a user's GPU than it
|
|
is to extract raster data from an equivalent raster image. And even
|
|
when an SVG image is slower than a raster equivalent, the difference
|
|
is usually not noticeable. However, just don't fall into the trap of
|
|
thinking that SVGs are faster than equivalent raster images, or vice
|
|
versa. Once again, "it depends".
|
|
|
|
## Authoring guidelines
|
|
|
|
A lot of SVG files (particularly those generated by SVG editors) ship
|
|
without being cleaned up and can contain a ton of junk that bloats the
|
|
file size and slows down rendering. In general the best way to combat
|
|
this is to first run SVG files through a linter such as
|
|
[svgo](https://github.com/svg/svgo) (see the Tools section below).
|
|
However, when authoring SVGs by hand here are some best practices to
|
|
help keep them lightweight. These rules are based on some real examples
|
|
seen in Mozilla's code.
|
|
|
|
### Basics
|
|
|
|
- Two spaces indenting
|
|
- No useless whitespaces or line breaks (see below for more details)
|
|
- Adding a license header
|
|
- Use double quotes
|
|
|
|
### Whitespace and line breaks
|
|
|
|
#### Whitespace
|
|
|
|
In addition to trailing whitespace at the end of lines, there are a few
|
|
more cases more specific to SVGs:
|
|
|
|
- Trailing whitespaces in attribute values (usually seen in path
|
|
definitions)
|
|
- Excessive whitespace in path or polygon points definition
|
|
|
|
#### Whitespace examples
|
|
|
|
This path:
|
|
|
|
```html
|
|
<path d=" M5,5 L1,1z ">
|
|
```
|
|
|
|
can be cut down to this:
|
|
|
|
```html
|
|
<path d="M5,5 L1,1z">
|
|
```
|
|
|
|
Similarly, this polygon:
|
|
|
|
```html
|
|
<polygon points=" 0,0 4,4 4,0 "/>
|
|
```
|
|
|
|
can be cut down to this:
|
|
|
|
```html
|
|
<polygon points="0,0 4,4 4,0"/>
|
|
```
|
|
|
|
#### Line breaks
|
|
|
|
You should only use line breaks for logical separation or if they help
|
|
make the file readable. You should avoid line breaks between every
|
|
single element or within attribute values. It's recommended to put the
|
|
attributes on the same line as their tag names, if possible. You should
|
|
also put the shortest attributes first, so they are easier to spot.
|
|
|
|
### Unused tags and attributes
|
|
|
|
#### Editor metadata
|
|
|
|
Vector editors (Inkscape, Adobe Illustrator, Sketch) usually add a bunch
|
|
of metadata in SVG files while saving them. Metadata can mean many
|
|
things, including:
|
|
|
|
- The typical "Created with *editor*" comments
|
|
- Non-standard editor specific tags and attributes (`sketch:foo`,
|
|
`illustrator:foo`, `sopodi:foo`, …)
|
|
- The [XML
|
|
namespace](https://developer.mozilla.org/en-US/docs/Web/SVG/Namespaces_Crash_Course)
|
|
definition that comes with the latter (`xmlns:sketch`,
|
|
`xmlns:sopodi`, …)
|
|
|
|
#### Other metadata
|
|
|
|
In addition to non-standard editor metadata, standard compliant metadata
|
|
also exists. Typical examples of this are `<title>` and `<desc>`
|
|
tags. Although this kind of data is supported by the browser, it can
|
|
only be displayed when the SVG is opened in a new tab. Plus, in most of
|
|
the cases, the filename is quite descriptive So it's recommended to
|
|
remove that kind of metadata since it doesn't bring much value.
|
|
|
|
You shouldn't include DOCTYPEs in your SVGs either; they are a source of
|
|
many issues, and the SVG WG recommends not to include them. See [SVG
|
|
Authoring
|
|
guidelines](https://jwatt.org/svg/authoring/#doctype-declaration).
|
|
|
|
#### Avoid the use of CDATA sections
|
|
|
|
[CDATA
|
|
sections](https://developer.mozilla.org/en-US/docs/Web/API/CDATASection)
|
|
are used to avoid parsing some text as HTML. Most of time, CDATA isn't
|
|
needed, for example, the content in `<style>` tags doesn't need to be
|
|
wrapped in a CDATA section as the content inside the tag is already
|
|
correctly parsed as CSS.
|
|
|
|
#### Invisible shapes
|
|
|
|
There are two kinds of invisible shapes: The off-screen ones and the
|
|
uncolored ones.
|
|
|
|
The offscreen shapes are hard to spot, even with an automated tool, and
|
|
are usually context aware. Those kinds of shapes are visible but off the
|
|
[SVG view
|
|
box](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/viewBox).
|
|
Here's [an
|
|
example](https://hg.mozilla.org/mozilla-central/diff/9fb143f3b36a/browser/themes/shared/heartbeat-star-lit.svg)
|
|
of a file with offscreen shapes.
|
|
|
|
On the other hand, the uncolored ones are easier to spot, since they
|
|
usually come with styles making them invisible. They must meet two
|
|
conditions: they must be devoid of any fill (or a transparent one) or
|
|
stroke.
|
|
|
|
#### Unused attributes on root `<svg>` element
|
|
|
|
The root `<svg>` element can also host many useless attributes. Here's
|
|
an
|
|
[example](https://hg.mozilla.org/mozilla-central/diff/2d38fecce226/browser/components/loop/content/shared/img/icons-10x10.svg)
|
|
taking into account the list below:
|
|
|
|
- `version`
|
|
- `x="0"` and `y="0"`
|
|
- `enable-background` (unsupported by Gecko and now deprecated by the
|
|
Filter Effects specification)
|
|
- `id` (id on root element has no effect)
|
|
- `xmlns:xlink` attribute when there are no `xlink:href` attributes
|
|
used throughout the file
|
|
- Other unused [XML
|
|
Namespace](https://developer.mozilla.org/en-US/docs/Web/SVG/Namespaces_Crash_Course)
|
|
definitions
|
|
- `xml:space` when there is no text used in the file
|
|
|
|
#### Other
|
|
|
|
- Empty tags, this may be obvious, but those are sometimes found in
|
|
SVGs
|
|
- Unreferenced ids (usually on gradient stops, but also on shapes or
|
|
paths)
|
|
- `clip-rule` attribute when the element *is not* a descendant of a
|
|
`<clipPath>`
|
|
- `fill-rule` attribute when the element *is* a descendant of a
|
|
`<clipPath>`
|
|
- Unreferenced/Unused clip paths, masks or defs
|
|
([example](https://hg.mozilla.org/mozilla-central/diff/2d38fecce226/toolkit/themes/shared/reader/RM-Plus-24x24.svg))
|
|
|
|
### Styling
|
|
|
|
#### Styling basics
|
|
|
|
- Privilege short lowercase hex for colors
|
|
- Don't use excessive precision for numeric values (usually comes from
|
|
illustrator)
|
|
- Use descriptive IDs
|
|
- Avoid inline styles and use class names or SVG attributes
|
|
|
|
##### Styling examples
|
|
|
|
Here are some examples for excessive number precision:
|
|
|
|
- 5.000000e-02 → 0.05 (as seen
|
|
[here](https://hg.mozilla.org/mozilla-central/diff/2d38fecce226/browser/themes/shared/devtools/images/tool-network.svg#l1.31))
|
|
- -3.728928e-10 → 0 (as seen
|
|
[here](https://hg.mozilla.org/mozilla-central/diff/2d38fecce226/browser/themes/shared/aboutNetError_alert.svg#l1.12))
|
|
- translate(0.000000, -1.000000) → translate(0, -1) (as seen
|
|
[here](https://hg.mozilla.org/mozilla-central/diff/2d38fecce226/browser/themes/shared/heartbeat-icon.svg#l1.13))
|
|
|
|
As for descriptive IDs:
|
|
|
|
- For gradients: SVG_ID1 → gradient1 (as seen
|
|
[here](https://hg.mozilla.org/mozilla-central/diff/2d38fecce226/browser/themes/shared/aboutNetError_alert.svg#l1.12))
|
|
|
|
#### Use of class names
|
|
|
|
- Avoid using a class if that class is only used once in the file
|
|
- If that class only sets a fill or a stroke, it's better to set the
|
|
fill/stroke directly on the actual shape, instead of introducing a
|
|
class just for that shape. You can also use SVG grouping to avoid
|
|
duplicating those attributes
|
|
- Avoid introducing variants of the same file (color/style variants),
|
|
and use sprites instead (with class names)
|
|
|
|
#### Default style values
|
|
|
|
There's usually no need to set the default style value unless you're
|
|
overriding a style. Here are some commonly seen examples:
|
|
|
|
- `style="display: none;"` on `<defs>` elements (a `<defs>`
|
|
element is hidden by default)
|
|
- `type="text/css"` on `<style>` elements
|
|
- `stroke: none` or `stroke-width: 0`
|
|
|
|
### SVG grouping
|
|
|
|
#### Style grouping
|
|
|
|
Group similarly styled shapes under one `<g>` tag; this avoids having
|
|
to set the same class/styles on many shapes.
|
|
|
|
#### Avoid excessive grouping
|
|
|
|
Editors can sometimes do excessive grouping while exporting SVGs. This
|
|
is due to the way editors work.
|
|
|
|
##### Nested groups
|
|
|
|
Avoid multiple-level nesting of groups, these make the SVG less
|
|
readable.
|
|
|
|
##### Nested transforms
|
|
|
|
Some editors use `<g>` tags to do nested transforms, which is usually
|
|
not needed. You can avoid this by doing basic algebra, for example:
|
|
|
|
```xml
|
|
<g transform="translate(-62, -310)"><shape transform="translate(60, 308)"/></g>
|
|
```
|
|
|
|
can be cut down to:
|
|
|
|
```xml
|
|
<shape transform="translate(-2,-2)"/>
|
|
```
|
|
|
|
because: -62+60 = -310+308 = -2
|
|
|
|
### Performance tips
|
|
|
|
These rules are optional, but they help speeding up the SVG.
|
|
|
|
- Avoid using a `<use>` tag when that `<use>` tag is being
|
|
referenced only once in the whole file.
|
|
- Instead of using CSS/SVG
|
|
[transforms](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/transform),
|
|
apply directly the transform on the path/shape definition.
|
|
|
|
### Tools
|
|
|
|
Tools can help to clean SVG files. Note, however that some of the rules
|
|
stated above can be hard to detect with automated tools since they
|
|
require too much context-awareness. To this date, there doesn't seem to
|
|
be a tool that handles all of the above. However, there are some
|
|
utilities that cover parts of this document:
|
|
|
|
- Mostly complete command line tool: <https://github.com/svg/svgo>
|
|
|
|
- Alternatives to SVGO:
|
|
|
|
- <https://github.com/RazrFalcon/svgcleaner>
|
|
- <https://github.com/scour-project/scour>
|
|
|
|
- GUI for command line tool (use with "Prettify code" and "Remove
|
|
`<title>`" options on): <https://jakearchibald.github.io/svgomg/>
|
|
|
|
- Good alternative to SVGO/SVGOMG:
|
|
<https://petercollingridge.appspot.com/svg-editor>
|
|
|
|
- Fixes the excessive number precision:
|
|
<https://simon.html5.org/tools/js/svg-optimizer/>
|
|
|
|
- Converts inline styles to SVG
|
|
attributes: <https://www.w3.org/wiki/SvgTidy>
|
|
|
|
- RaphaelJS has a couple of utilities that may be useful:
|
|
[raphael.js](https://dmitrybaranovskiy.github.io/raphael/)
|