Grants are available to support local in-person meetups around the world.
Manual:Coding conventions/SVG
![]() | This page documents a MediaWiki development guideline, crafted over time by developer consensus (or sometimes by proclamation from a lead developer) |
This page describes the coding conventions used within files of the MediaWiki codebase written in SVG. See also the general conventions that apply to all programming & markup languages, including SVG.
On per-project base we make use of SVGO as optimisation tool, see automated optimisation below. Another helpful tool for further manual optimisation is SVGOMG. It provides a visual before/after comparison.
Code structure [edit source]
Minimal code as possible with readability in mind is the premise.
Example for simple optimised file – subtract.svg from OOUI:
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
<title>
subtract
</title>
<path d="M4 9h12v2H4z"/>
</svg>
Example for slightly more complex, optimised file – BetaFeatures screenshot template:
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="264" height="162" viewBox="0 0 264 162">
<title>
BetaFeatures screenshot template
</title>
<defs>
<clipPath id="jagged-edge">
<path d="M0 0v152l12 10 12-10 12 10 12-10 12 10 12-10 12 10 12-10 12 10 12-10 12 10 12-10 12 10 12-10 12 10 12-10 12 10 12-10 12 10 12-10 12 10 12-10V0z"/>
</clipPath>
</defs>
<g fill="#eaecf0" clip-path="url(#jagged-edge)">
<path id="background" fill="#fff" d="M0 0h264v162H0"/>
<path id="logo" d="M11 22c0-8 6-14 14-14s14 6 14 14-6 14-14 14-14-6-14-14M38 45v-5H13v5h25"/>
<path id="sidebar" d="M38 163V58H13v106h25"/>
<path id="personal-tools" d="M233 5h26v6h-26V5zM209 5h22v6h-22zM185 5h22v6h-22zM162 5h13v6h-13zM177 5h6v6h-6zM154 5h6v6h-6z"/>
<path id="search-input" d="M258 16v4h-92v-4h92m1-1h-94v6h94v-6z"/>
<path id="search-icon" d="M168 17h2v2h-2z"/>
<path id="article" d="M252 162V29H48v133z"/>
<path id="border" d="M0 0v162h264V0zm1 1h262v150.533l-11 9.166-12-10-12 10-12-10-12 10-12-10-12 10-12-10-12 10-12-10-12 10-12-10-12 10-12-10-12 10-12-10-12 10-12-10-12 10-12-10-12 10-11-9z"/>
</g>
</svg>
We will explain the different coding conventions in the following section.
Automated optimisation (SVGO)[edit source]
A standard set of conventions can be enforced by help of SVGO. If your original SVGs are well-formed, you should be able to automatically optimise them. As some SVGO default plugins (options) might result in unexpected appearance with more complex SVGs, we differentiate between safe, considerably less-safe and unsafe plugins. When using unsafe plugins it's recommended to verify before and after diffing per file to ensure visual quality.
Safe plugins:
Mentioning only plugins, that are changed from default setting or that might be counter-intuitive:
- Sorting attributes 'sortAttrs'
Enable by setting totrue
; disabled by default - Remove DOCTYPE 'removeDoctype'
Using a DOCTYPE in SVGs is considered harmful by SVG standards authors as of SVG 2 Working Draft; enabled by default - Remove or cleanup
enable-background
attribute when possible 'cleanupEnableBackground'
Deprecated attribute, only supported by IE/Edge; enabled by default
See SVGO Readme for other enabled, safe plugins.
Plugins to consider carefully:
- Round/rewrite number lists 'convertPathData'
Might cause imprecise rendering; enabled by default - Remove unused and minify used IDs 'cleanupIDs'
Might negatively affect readability in more complex SVGs; enabled by default - Remove raster images 'removeRasterImages'
As general rule dangerous, could cause data loss; disabled by default
Unsafe rules to disable (don't use!):
- Remove XML processing instructions 'removeXMLProcInst', aka XML declaration
<?xml version="1.0" encoding="UTF-8"?>
Issues when viewed as standalone file in some editors, also possible issues with MIME type interpretation
Example: If the SVG doesn't start with an XML declaration, then it's MIME type will be detected astext/plain
rather thanimage/svg+xml
by libmagic and consequently, MediaWiki's CSSMin CSS minifier. libmagic's default database currently requires that SVGs contain an XML declaration; disable by setting tofalse
; enabled by default - Remove
<title>
'removeTitle'
Problematic for accessibility reasons; set tofalse
; enabled by default - Remove
<desc>
'removeDesc'
Problematic for accessibility reasons; set tofalse
; enabled by default - Remove
viewBox
attribute 'removeViewBox'
Results in troublesome appearance in some browsers, therefore both,width
/height
andviewbox
should be featured; set tofalse
; enabled by default - Remove dimensions
width
/height
whenviewbox
is available 'removeDimensions'
As above; set tofalse
; disabled by default
Exemplified safe configuration[edit source]
Note that this is for svgo v1.x; v2.x takes different CLI arguments:
$ svgo path/to/image.svg --disable={cleanupIDs,convertPathData,removeDesc,removeTitle,removeViewBox,removeXMLProcInst} --enable='sortAttrs' --pretty --final-newline
Use pretty
output for human readable code and in the process indent code by tabs.
Exemplified safe configuration (.svgo.config.js)[edit source]
Update Jan 2022: NPM run scripts enabled SVGO configuration (phab:T246321).
/**
* SVGO Configuration
* Compatible to v2.4.0+
* Recommended options from:
* https://www.mediawiki.org/wiki/Manual:Coding_conventions/SVG#Exemplified_safe_configuration
*/
module.exports = {
plugins: [
{
// Set of built-in plugins enabled by default.
name: 'preset-default',
params: {
overrides: {
cleanupIDs: false,
removeDesc: false,
removeTitle: false,
removeViewBox: false,
// If the SVG doesn't start with an XML declaration, then its MIME type will be detected as "text/plain" rather than "image/svg+xml" by libmagic and, consequently, MediaWiki's CSSMin CSS minifier.
// libmagic's default database currently requires that SVGs contain an XML declaration:
// https://github.com/threatstack/libmagic/blob/master/magic/Magdir/sgml#L5
removeXMLProcInst: false
}
}
},
'removeRasterImages',
'sortAttrs'
],
// Set whitespace according to Wikimedia Coding Conventions.
// @see https://github.com/svg/svgo/blob/v2.8.0/lib/stringifier.js#L41 for available options.
js2svg: {
eol: 'lf',
finalNewline: true,
// Configure the indent to tabs (default 4 spaces) used by '--pretty' here.
indent: "\t",
pretty: true
},
multipass: true
}
Exemplified safe configuration (Gruntfile.js)[edit source]
svgmin: { options: { js2svg: { indent: '\t', pretty: true }, plugins: [ { cleanupIDs: false }, { removeDesc: false }, { removeRasterImages: true }, { removeTitle: false }, { removeViewBox: false }, { removeXMLProcInst: false }, { sortAttrs: true } ] } }
Manual optimisation[edit source]
Beyond automated optimising SVGs there are further steps to consider:
- Remove
standalone="no"
from XML processing instruction, as it's default - Remove
version
attribute from<svg>
tag, as all browsers ignore it - Lowercase (for better gzipping) and shorten hex color values, if possible, e.g.
#fff
instead of#FFFFFF
. - Attributes that are the same for a group of elements can be applied to a common parent
<g>
instead. - Rely on defaults like
fill="#000"
andstroke-width="1"
. - The
<path d="…"/>
syntax is almost always shorter than the syntax of basic shapes like<polygon>
or even<rect>
. The only possible exceptions are<circle>
,<ellipse>
, and rounded<rect rx="…">
, as converting them to paths typically results in sequences of long floating point numbers. - Merge
<path d="…"/>
elements where applicable. - Remove redundant
ry="…"
attribute when identical torx="…"
as renderer must consider both values identical when one's missing. - Remove not needed
fill-rule="…"
andclip-rule="…"
. These rules only have an effect on certain paths, e.g. when a path intersects itself. - Look for IEEE rounding errors like
0.999999999
or1.000000001
. Such numbers take up space without providing any additional information. They can almost always be cut off without visually changing anything. - Work with a non-fractional pixel grid while drawing, and align as much points as possible on this grid. These points have a much higher chance of being represented as short integer numbers in the resulting code.
- Pick a non-fractional grid so that it matches the features of an existing image, and scale or redraw shapes so that as many points as possible fall on the grid. The result might be misaligned and can be cropped using
viewBox="<left> <top> <width> <height>"
.
If you want to dig even deeper, there are more optimisations to compress delivery, such as:
- auto-closing paths (aka removing
z
for certain shapes), - use relative commands when creating paths (instead of absolute commands, e.g. "m" for "move by", instead of "M" for "move to"),
- optimising for compression backreferences