JMM’s notes on

Scalable Vector Graphics (SVG)

SVG is one of my favorite web technologies. It’s a great way to make stylable, accessible, and interactive graphics. It’s not only human-readable, it’s easily programmatically modified using the DOM API, which lets you make data visualizations fairly easily (also check out d3.js).

Misc

textPath vertical and horizontal alignment and offsets

Just a note for myself since I couldn’t really google this. When you put text on a path, how do you shift its horizontal and vertical position?

You shift the horizontal position by putting a startOffset attribute on the <textPath> element (e.g. startOffset=50%). To move it in the vertical direction, you can set the dy attribute of an internal <tspan> element.

<text
     xml:space="preserve"
     x="1"
     y="0"
     dominant-baseline="hanging"><textPath
       xlink:href="#somepath"
       startOffset="50%"
       ><tspan
            style="text-align:center;letter-spacing:0px;text-anchor:middle"
	    dy="10">This text is kinda moved off the path</tspan></textPath></text>

This is documented pretty well in the textPath attributes section of the SVG2 spec.

External style sheets

You can either use a CSS @import rule, or use an HTML link element in (often in <defs>, but not necessarily) like so:

<link
    xmlns="http://www.w3.org/1999/xhtml"
    rel="stylesheet"
    href="/some-style.css"
    type="text/css" />

Inline icons

Sometimes you want icons to be the same size as surrounding text. I think the way to do this is to use text-relative heights like 1em.

<p>Hello <svg xmlns="http://www.w3.org/2000/svg" height="1em" width="1em" viewBox="0 0 10 10"><circle cx="5" cy="5" r="5" fill="blue"/></svg>.</p>

This gives:

Hello .

contenteditable Text

contenteditable="true" doesn’t seem to work on SVG <text> elements, at least in pure SVG contexts. For one printable template I had to use a <foreignObject> with a <xhtml:textarea> because it also didn’t seem to work on a plain <xhtml:div>.

Another workaround is to have the SVG enclosed in an XHTML context, where the XHTML context is contenteditable, like so:

<p contenteditable="true">
       This text is HTML <svg:svg xmlns:svg="http://www.w3.org/2000/svg" viewBox="0 0 100 25" width="100" height="25"><svg:g font-size="12" fill="blue" stroke="red" stroke-width="1"><svg:text x="0" y="12">This text is SVG</svg:text></svg:g></svg:svg>
      </p>

This text is HTML This text is SVG

Other miscellaneous

Very short notes for myself.

  • Use nested <svg/> elements for a coordinate transform.
  • If you define width="8.5in" height="11in" in inches (or similar measure), it doesn’t get resized with zoom in Firefox.

Filters

Text readability filter

This just adds a white blurred background behind text to make text easier to read when the background otherwise doesn’t have enough contrast.

<filter style="color-interpolation-filters:sRGB">
  <feFlood flood-opacity="1" flood-color="rgb(255,255,255)" result="flood" />
  <feMorphology in="SourceGraphic" operator="dilate" radius="1" result="result1" />
  <feComposite in="flood" in2="result1" operator="in" result="composite1" />
  <feGaussianBlur in="composite1" stdDeviation="1" result="blur" />
  <feOffset dx="0" dy="0" result="offset" />
  <feComposite in="SourceGraphic" in2="offset" operator="over" result="composite2" />
</filter>

Patterns

Here’s an example of a pattern for lined paper, kind of close to college rule, but not exactly:

<pattern
       width="96"
       height="96"
       patternUnits="userSpaceOnUse"
       patternContentUnits="userSpaceOnUse"
       id="collegerule1"
       viewBox="0,0,96,96">
      <g id="collegerulegroup">
        <rect style="opacity:1;vector-effect:none;fill:white;fill-opacity:1;stroke:none" width="96" height="96" x="0" y="0" />
        <path style="fill:none;stroke:#99c1f1;stroke-width:0.53333333;opacity:0.4" d="M 0,0 h 96" id="blueline1"/>
	<use x="0" y="0" xlink:href="#blueline1" transform="translate(0,24)" />
        <use x="0" y="0" xlink:href="#blueline1" transform="translate(0,48)" />
        <use x="0" y="0" xlink:href="#blueline1" transform="translate(0,72)" />
        <use x="0" y="0" xlink:href="#blueline1" transform="translate(0,96)" />
      </g>
    </pattern>

The <g id="collegerulegroup"> isn’t necessary, but helpful if you want to edit it in Inkscape by swapping it with a <use x="0" y="0" xlink:href="#collegerulegroup" />.

To use a pattern: style="fill:url(#collegerule1)".

Patterns don’t always seem as crisp as <use> elements.

Questions

Questions I have about SVG that I’ll try to figure out later

Wishlist

Some features I hope SVG gains

Mesh gradients
Instead of just interpolating colors linearly, mesh gradients let you interpolate between several points on a polygon. This is a feature that appears (IIRC) in SVG 2. Inkscape (see my Inkscape notes) has support for this. However, when exporting Inkscape has to use a mesh gradient JavaScript polyfill that renders the mesh gradient to a bitmap canvas.
Non-rectangular patterns
I forget what this is actually called, but it’d be nice to have patterns that aren’t just repeated rectangles. Perhaps some other kinds of tiling that makes repetition less evident.