Using inline SVG as a hacky image markup language for graphical documents

I’m not sure if the nomenclature issue for complex, not-easily-reducible-to-a-single-alt-text SVGs has been resolved, so I’m calling them “graphical documents” for these examples.

Structuring a comic

This is what I’ve personally been working on in an attempt to bring webcomics out of 1997, since they are almost always published on the Web as bitmaps. Here’s my actual Handlebars template for generating a more accessible (searchable/copypastable/interactable) comic:

<!--[if gt IE 8]><!-->
<svg viewBox="0 0 {{panelset.viewBox.width}} {{panelset.viewBox.height}}"
     width="100%"
     preserveAspectRatio="xMidYMid"
     role="document">
  <defs>
    <style>
      .balloon-shape {
        fill: #fff;
        stroke-width: 5;
      }
      .speaker {
        fill: none;
      }
      .line {
        text-anchor: middle;
      }
    </style>
  </defs>

  <switch role="presentation">
    <g class="svg-content" role="list">
      {{#each panel in panels}}
        <g class="panel" role="listitem">
          <image xlink:href="{{this.art.src}}"
                 class="art"
                 width="{{this.art.width}}" height="{{this.art.height}}"
                 x="{{this.art.x}}"         y="{{this.art.y}}"
                 aria-labelledby="t{{@index}}" aria-describedby="d{{@index}}" role="img">
            <title id="t{{@index}}">{{{this.art.alt}}</title>
            <desc id="d{{@index}}">{{{this.art.desc}}</desc>
          </image>

          {{#each balloon in this.balloons}}
            <g class="balloon char-{{this.charClass}} voice-{{this.voiceClass}}">
              <path class="balloon-shape" role="presentation"
                    d="{{this.pathData}}"/>

              <text class="balloon-text">
                <tspan class="speaker">{{this.character}} {{this.voice}}:</tspan>

                {{#each line in this.lines}}
                  <tspan class="line"
                         x="{{this.x}}" y="{{this.y}}">
                    {{{this.text}}}
                  </tspan>
                {{/each}}
              </text>
            </g>
          {{/each}}
        </g>
      {{/each}}
    </g>

    <foreignObject class="html-fallback" width="0" height="0"><!--<![endif]-->
      {{{htmlFallback}}
    </foreignObject>
  </switch>
</svg>

This template handles old Internet Explorer, other non-SVG capable browsers, the fact that inline SVG is poorly supported by screen-readers, and other nasty “real-world” problems, so if you would appreciate a cleaned-up theoretical example, I can provide one.

I blogged about my efforts to correctly mark up a comic which also contains experiments with inline SVG and general thoughts about the subject.

It also has my current stab at providing the best structure for comic panels, but I’m sure it’s going to cause unsuitable behavior in some screen-reader out there. Need to test. :/

Annotating a complex bitmap

An SVG “harness” is often the best alternative for describing an complex raster image. It’s superior to the much-debated longdesc in an important way: the “descriptive SVG” can impart a highly-visible focus ring over parts of the image when tabbed through, and contains spatial positioning information for assistive technology to make use of.

Users with low/poor vision can benefit today from having focusable highlighted regions that have additional descriptive text, helping them them understand what an object is if they lack sufficient visual capability to see its details.

As an extreme example, imagine annotating The Garden of Earthly Delights by Hieronymus Bosch:

<svg>
  <title>The Garden of Earthly Delights</title>
  <desc>This oil painting by Hieronymous Bosch is a triptych, separated into 3 panels.</desc>
  <image xlink:href="garden.jpg"/>

  <g id="panel-1">
    <title>Left Panel</title>
    <desc>This panel depicts God presenting Eve to Adam in the Garden of Eden.</desc>

    <path d="[path data forming an outline of Adam's depiction]" tabindex="0">
      <title>Adam</title>
      <desc>Adam is a nude, white, brown-haired man sitting on the ground. He gazes with rapture at God.</desc>
    </path>

    <path d="[ditto Eve]" tabindex="0">
      <title>Eve</title>
      <desc>Eve is a nude, white, blonde woman being pulled by the hand by God towards Adam.</desc>
    </path>

    etc...

  </g>

  <g id="panel-2">
    <title>Central Panel</title>
    <desc>This panel depicts a broad panorama of socially engaged nude figures, fantastical animals, oversized fruit and hybrid stone formations.</desc>

    etc...

  </g>

  <g id="panel-3">
    <title>Third Panel</title>
    <desc>This panel depicts a hellscape which portrays the torments of damnation.</desc>

    etc...

  </g>
</svg>

I’m not sure how assistive technologies would present spatial information, but the fact that it would exist inside the SVG data at least allows them to do so. I’ve seen <map> used as a rough equivalent, but the fact that its coordinates don’t scale with the image (due to historical reasons) dooms that approach to obscurity with the Responsive Web Design revolution. (The <picture> community working group has notably put off working on how <map> would interact, largely because nobody cares anymore.)

Salvaging “programmer documentation art”

One commonly-inaccessible situation is when programmers writing technical documentation produce diagrams by way of preformatted text that contains, to a screen-reader, an indistinguishable stew of character sludge. For simple concepts, basic ARIA is sufficient:

<pre role="img" aria-label="Your working directory should now contain the file index.html, robots.txt, and favicon.ico">
/working directory/
                  |-index.html
                  |-robots.txt
                  \-favicon.ico
</pre>

But complicated diagrams are common, like this one from RFC 5755.


      +--------------+
      |              |        Server Acquisition
      |  AC issuer   +<---------------------------+
      |              |                            |
      +--+-----------+                            |
         ^                                        |
         | Client                                 |
         | Acquisition                            |
         v                                        v
      +--+-----------+                         +--+------------+
      |              |       AC "push"         |               |
      |   Client     +<------------------------|    Server     |
      |              | (part of app. protocol) |               |
      +--+-----------+                         +--+------------+
         ^                                        ^
         | Client                                 | Server
         | Lookup        +--------------+         | Lookup
         |               |              |         |
         +-------------->+  Repository  +<--------+
                         |              |
                         +--------------+

                      Figure 1: AC Exchanges

Or this this IETF document (which, fittingly, talks about a PDF alternative for their blasted plaintext format):


                               +-----+  -->
                               | N_4 |------     <--- +-----+
                               +-----+     |    |-----| R_3 |
                                  |    15  |    | 5   +-----+
                                  |50      |    |        |
                +-----+  --->     |        +-----+       | 70
                | N_2 |------     |        | N_3 |       |
                +-----+     |     |        +-----+       |
                 |       15 |     |            | 30      |
                 | 10       |   +-----+  <---  |         |
              @  |          ----|  S  |--------|         |
              @  |       <@@@   +-----+                  |
              V  |                 |   |                 |
                 |              10 |   |                 |
              +-----+              |   V                 |
              | R_2 |          +-----+                   |
              +-----+          |  E  |                   |
            |  |               +-----+                   |
            |  | 40             |  |                     |
            V  |             10 |  |                     |
               |    +-----+     |  V                     |
               -----| R_1 |-----|                        |
                    +-----+                              |
                       |     --->         +-----+        |
                       |------------------|  D  |---------
                               10         +-----+

                       E is primary next-hop of S
                 N_2 and N_3 are U-Turn Neighbors of S
                       N_4 is a Looping Neighbor of S

I tried creating a program that would be able to follow the ASCII flow diagram and spit out an “SVG annotation,” but I’m… not that good of a programmer. It was an effort to make a tool that would take RFCs and produce accessible HTML out of them.

The output would have been a “ghost” SVG where it would be made of invisible semantic elements like the proposed connectors, some rects, and with appropriate titles and descs to identify concepts beyond SVG’s meager vocabulary.

Faking MathML

MathML support remains awful; only Firefox supports it. I’ve toyed with the idea of using SVG to draw and annotate equations where MathML is unsupported as a JavaScript-less, better-performing fallback, like this.

Ideally it would be an interface accepting MathML, TeX, or whatever formats are popular among the scientific/mathmatical community, running it through ConTeXt, converting the result to SVG, and then spitting out a valid MathML-in-HTML5 fragment with an interior SVG fallback for appropriate rendering in non-Firefox browsers.

I’m not sure which of the two would be the designated target for ARIA hooks, but SVG looked like it had more generic structures for repurposing. I might have been better served by a third HTML accessible description with ARIA hooks, but I’d have to see.

A persistent thorn

I know you are already working on this, but I’m really kind of desperate to resolve the “<title> is both alternative text and a tooltip” issue, like the ancient IE alt/hover text fiasco before it. (The webcomics community to this day calls the effect “alt text” despite it being “title” in today’s browsers.)

Complicating the issue is the state of markup inside <title>/<desc>; the spec has changed a few times on the matter, and the validator disallows anything but plain text inside either. I would dearly like to link object descriptions within the SVG together for easier navigation. In the case of the Bosch painting from earlier, imagine the fragment:

<path d="[a trace of God's outline here]" id="god">
  <title>God</title>
  <desc>God presents <a href="#eve">Eve</a> to <a href="#adam">Adam</a>. He is depicted as a man in a pink robe[...]</desc>
</path>

My personal use case was linking character names in my comic images’ descriptions to their Cast page entries; redescribing their appearance every comic was awful UX, but screen-reader users would appreciate being able to refresh their memories if they forgot. (I have a friend with cognitive disabilities in the way of varying over/under focus, and he would often resort to the <title> and <desc> descriptions when having bad days to help him understand. He was the one who suggested the links, but the HTML5 validator complains with any markup inside the descriptive elements.)