347 lines
12 KiB
ReStructuredText
347 lines
12 KiB
ReStructuredText
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:
|
|
|
|
.. code:: html
|
|
|
|
<path d=" M5,5 L1,1z ">
|
|
|
|
can be cut down to this:
|
|
|
|
.. code:: html
|
|
|
|
<path d="M5,5 L1,1z">
|
|
|
|
Similarly, this polygon:
|
|
|
|
.. code:: html
|
|
|
|
<polygon points=" 0,0 4,4 4,0 "/>
|
|
|
|
can be cut down to this:
|
|
|
|
.. code:: 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:
|
|
|
|
.. code:: xml
|
|
|
|
<g transform="translate(-62, -310)"><shape transform="translate(60, 308)"/></g>
|
|
|
|
can be cut down to:
|
|
|
|
.. code:: 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/>`__
|