The Great SVG RetCon

A presentation by
Amelia Bellamy-Royds
(@AmeliasBrain)

at
Exchange.js
(Edmonton, 6 October 2016)

These slides: ameliabr.github.io/great-svg-retcon

Image from MovieMistakes.com, comparing two screenshots from The Avengers, with Captain America's damaged uniform circled in one shot, and the same part of his uniform circled, undamaged, in the second shot. Text says: The Avengers, Damaged suit repairs itself after battle.
From The Avengers, as captured for MovieMistakes.com by THGhost

Retroactive: Because sometimes you need to fix the past.

Screenshot from Back to the Future, showing mad-scientist Doc and teenaged Marty McFly, standing outside at night, both looking up in concern at something behind the camera.
Back to the Future
Agents of Shield promo poster, featuring Clark Gregg's Agent Coulson front and center.
Marvel's Agents of Shield
Film still of Agent Coulson's death scene in The Avengers.
The Avengers

RetCon-ing the Web

Screenshot of browser yellow-screen warning for XML well-formedness errors.
Screenshot of browser pink-box warning for XML validity errors.

What you say to old browsers:

<picture>
<source media="(min-width: 650px)" srcset="images/kitten-large.png" />
<source media="(min-width: 465px)" srcset="images/kitten-medium.png" />
<img src="images/kitten-small.png" alt="a cute kitten" />
</picture>

What they hear:

<blah>
<blah-blah />
<blah-blah />
<img src="images/kitten-small.png" alt="a cute kitten" />
</blah>

Markup

SVG is XML
SVG is a document model, which can be expressed in XML or HTML markup

Stand-alone SVG files are XML!

Animated screenshot of browser yellow-screen warning for XML validation errors, versus the same file displaying perfectly well with a .html extension.

Use your browser's parser to clean up sloppy HTML markup

Animated screenshot showing horrific SVG-in-HTML markup (from a how-short-can-you-make-this-code competition) being converted to valid XML using Firefox dev tools

(Or just use MS Edge's Save Picture As… option)

Don't use XML prefixes for SVG or HTML elements in HTML markup.

For namespaced attributes, only use:

  • xlink:href
  • xml:lang

Clean up extra XML bloat before pasting into HTML!

<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 15.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
<!ENTITY ns_extend "http://ns.adobe.com/Extensibility/1.0/">
<!ENTITY ns_ai "http://ns.adobe.com/AdobeIllustrator/10.0/">
<!ENTITY ns_graphs "http://ns.adobe.com/Graphs/1.0/">
<!ENTITY ns_vars "http://ns.adobe.com/Variables/1.0/">
<!ENTITY ns_imrep "http://ns.adobe.com/ImageReplacement/1.0/">
<!ENTITY ns_sfw "http://ns.adobe.com/SaveForWeb/1.0/">
<!ENTITY ns_custom "http://ns.adobe.com/GenericCustomNamespace/1.0/">
<!ENTITY ns_adobe_xpath "http://ns.adobe.com/XPath/1.0/">
]>
<svg version="1.1" id="Ebene_1" xmlns:x="&ns_extend;" xmlns:i="&ns_ai;" xmlns:graph="&ns_graphs;"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="566.93px"
height="283.46px" viewBox="0 0 566.93 283.46" enable-background="new 0 0 566.93 283.46" xml:space="preserve">
<switch>
<foreignObject requiredExtensions="&ns_ai;" x="0" y="0" width="1" height="1">
<i:pgfRef xlink:href="#adobe_illustrator_pgf">
</i:pgfRef>
</foreignObject>
<g i:extraneous="self">
<!-- actual SVG stuff used by browser is here -->
</g>
</switch>
<!-- more Adobe proprietary blobs were here -->
</svg>

Namespaces always matter when scripting!

(xmlns attribute doesn't, though)

But, innerHTML triggers the parser.

  var ns = {svg: "http://www.w3.org/2000/svg",
xlink: "http://www.w3.org/1999/xlink"};
var u = createElementNS(ns.svg, "use");
u.setAttributeNS(ns.xlink, "href", "#icon");
  var wrapper = document.createElement("div");
wrapper.innerHTML = "<svg><use xlink:href='#icon'/></svg>"
var u = wrapper.querySelector("use");

Styles

SVG styles can be defined with CSS properties or XML attributes
SVG styles can be are defined with CSS properties, some of which have presentation or XML attributes

Any supported CSS syntax should be supported in SVG.

.icon {
fill: currentColor;
fill: var(--icon-color, currentColor);
}
svg *:link {
text-decoration: underline overline;
}
@supports (text-decoration-style: wavy) {
svg *:link {
text-decoration: wavy underline;
}
}

Geometry

Geometric structure is defined in SVG markup

Changing geometry changes the drawing.

Changing styles just adds a little flair…

Three simplistic SVG drawings: first is a Cat face; second is a copy of the cat face in which the ears have been elongated and the whiskers have been shortened to create a Rabbit face; third is a copy of the cat face, colored purple and with extra thick lines, but still unmistakably a cat face.
Geometric Document structure is defined in SVG markup; geometry is defined by geometric styles or their presentation attributes

But… attributes ≠ styles

Same attribute names, on different elements, with different effects:

SVG rectangle and ellipse, with the rx and ry dimensions marked out

Same attribute names, on different elements, with different defaults:

The same SVG, but with the ry attribute removed. The rectangle now has symmetrical corner curves, but the ellipse has disappeared.  Unless you're viewing this on a future browser that has actually implemented the new SVG 2 rules.

SVG geometry properties (that can be set with CSS)

Property Elements with presentation attribute Elements with ordinary attribute only
width rect, image, foreignObject, svg, symbol, use pattern, mask, filter, and filter effect (fe*) elements
height
x All above, plus text, tspan, hatch, meshgradient, cursor
y
cx circle, ellipse radialGradient
cy
r circle
rx ellipse, rect (none)
ry
d path hatchpath

Transforms

The SVG coordinate system can be manipulated with the transform attribute
Many copies of a card-suit club shape, colored in alternating shades of green, repeated at different translations in the image to create a forest effect. Many copies of a card-suit spade shape, rotated around different points to create a complex pattern. Many copies of a a card-suit heart shape, at different scales, centered over one another in alternating colors.
The SVG cCoordinates system can be manipulated with the transform and transform-origin attribute properties, or with a transform presentation attribute

SVG layout, & SVG transforms, are based on a coordinate system.

CSS doesn't always have a coordinate system.

For an off-center shape in a centered SVG coordinate system…

<svg viewBox="-35 -35 70 70">
<polygon points="-10,-10 0,-15 5,-30 10,-15,
20,-10 10,-5 5,10, 0,-5" />
</svg>

You get different transform-box sizes and different box origins:

Side-by-side diagrams labelled view-box and fill-box, showing the identical polygon and axis lines, as described, but different annotations for the width, height, and 0,0 point of the box.
The SVG cCoordinates system can be manipulated with the transform, and transform-origin and transform-boxattribute properties, or with a transform presentation attribute

Examples of equivalent transforms, old versus new syntax

SVG 1.1 CSS Transforms
translate( 16, 0 ) translate( 16px, 0 )
translate( 12pt, 0 )
translateX( 16px )
rotate( 90 ) rotate( 90deg )
rotate( 0.25turn )
rotateZ( 90deg )
scale( 2 ) scale( 2 )
scale( 1, -1 ) scaleY( -1 )

3D Transforms are fun! (but very buggy)

On the right, the text: Team Web — HTML, CSS, JS & SVG. On the left, shield-shaped logos for each of the languages.  If your browser supports it, the logos rotate in 3D space, as if they are on sides of a cube, each one taking a turn in front.  If 3D transformations are not supported, the logos are smaller, laid out in a square.

Fallback layout uses the transform attribute:

This is an animated screenshot of the fallback layout: on the left, 4 logos in a square, fading in and out in turn.  On the right, the text is unchanged: Team Web — HTML, CSS, JS & SVG.

There's much more…

  • paint-order (good support) and z-index (no support)
  • CSS-crossover graphical effects (filters, masking, clip-paths)
  • Blend modes instead of filters
  • Wrapping text in a shape!
  • SVG-in-OpenType fonts (old SVG Fonts are dead)
  • Proper keyboard support
  • Better accessibility guidance
  • Unified approach to Web Animations, CSS or SMIL-like elements (not completely dead)
  • Overhauled SVG DOM. Many features removed. Replacements pending…
  • New paint servers: mesh gradients and hatches
  • Context paint, to coordinate line markers and multi-shape icons
  • Coming soon: SVG paint servers for CSS elements, filled & stroked CSS text, CSS images and multiple layers for SVG fill & stroke