Making Progress with SVG

Shelley Sun, 06/06/2010 - 11:57

Web Directions has created a No Bit, Sherlock developer challenge, with nice prizes such as a laptop and XBox for the person or persons who comes up with the most creative variation of SVG progress element. A nice play on the name ("no bit"), but even nicer prizes.

I'm not participating in the contest, but couldn't resist playing with the idea of creating progress elements with SVG.

One type of progress element is the indeterminate progress, also called a throbber. If you use Twitter, it's equivalent to the circling animated graphic, and indicates that an event is happening, but the web site can't determine the exact progress of the event.

When I think of an unending event, I always imagine ouroboros, the serpent swallowing its own tail, and creating an infinite seeming circle. It can represent many things in many different cultures but, to me, represents a continuous cycle with no beginning, middle, or end. It just is, until it is no more.

With that in mind, I thought I would try my hand at creating an ouroboros indeterminate progress element. Luckily for me, I didn't have to stretch my rather limited graphic skills in order to create the ouroboros: Wikipedia provides an elegant graphic, already formatted as SVG (PNG format), and with a license that allows me to use the graphic for my own work.

My first indeterminate progress element plays on the cyclical nature of ouroboros, by rotating the graphic around its origin, as you can see in the following example if your browser supports SVG. Clicking the start button begins the animation; clicking the end button, stops it. The application makes use of the built-in transformational capability of SVG.

It's an interesting effect, but a little CPU intensive. In addition, there's nothing uniquely SVG about the effect. I could have just as easily grabbed the PNG formatted graphic and used the new CSS3 transform attributes to rotate the image. I wanted something that plays on the uniqueness of SVG—that non-bit nature of SVG that forms part of the title of the Web Directions contest.

SVG is a vector graphics language, which means that a graphic consists of various elements, all combined into a whole. The ouroborus I used is actually made up of several path elements, forming the head, the eye, and the different scales along the body.

What if, instead of cycling the entire serpent graphic, I just cycle an effect around the serpent? A popular Ajax-based throbber is the one that Twitter uses, and consists of a animated dashed circle, where the dashes around the circle are hidden and displayed using a circular motion.

I applied the Ajax style throbber effect to my ouroborus graphic to create my next effort, as shown below. In this case, the serpent remains static, and only the scales change color, in a circular motion, to indicate some action is taking place.

I prefer the second approach, and it's less CPU intensive than using a rotating graphic. You can also play with the colors: just make sure there's enough contrast between "inactive" scale and active one so that the circular effect is easily seen.

Of course, both of these designs are for an indeterminate progress graphic. What about a deterministic one, where there is a beginning, middle, and end?

Even though I was inspired to use ouroboros because of the cyclical nature of the graphic, I'm also using SVG, which I've always felt to be synonymous with limitless possibilities. Ouroboros also means complementary opposites and what is more complementary, and opposite, than an event that's not started, and an event that's completely finished?

I made a third progress animation, but this time, there is a beginning, middle, and end. As whatever task progresses, my serpent's scales turn from gray to black. In order to ensure that my application user knows what's happening, I also provide a text description of the progress.

One last change for all of the graphics: ensuring they're accessible.

All three graphics are given a role of progressbar. All three would also normally be associated with the task using other ARIA attributes. In addition, since the third application is a deterministic progress graphic, I also set the aria-valuemin, aria-valuemax, and aria-valuenow attributes on the SVG element. (I could have also set these values on the g element that groups the graphic within the SVG.)

If you load the graphic within Firefox using the NVDA open source screenreader, you'll not only "see" the progress, you'll also be able to hear the progress. And though these variations are a fixed size for demonstration purposes, they can be easily scaled as small or as large as you want, because I'm using SVG.

A fun little challenge. I'm looking forward to seeing the Web Directions "No Bit, Sherlock" contest entries.

Progress Element: What I've Found

Shelley Sun, 05/16/2010 - 08:59

To recap my weekend effort with the WebKit nightly implementation of the HTML5 progress element:

  • I created a application that uses the progress element and provides a text-based fallback for the element. You need to use setAttribute and getAttribute to get the progress element's value attribute, as accessing the attribute directly on the object only works when progress is implemented in the browser. Apple's VoiceOver seems to only audibly announce the state of the progress bar when it first receives focus. I can't test with Firefox and NVDA on Windows, as Firefox has not yet implemented the element.
  • I created another application that provides a graphical progress bar fallback using two div elements. I also use ARIA to provide audible signals of progress bar state. During this experimentation, I found that you can't change the background-color of the progress element, as this will wipe out the progress effect.
  • I created a third application, this time embedding the graphical progress bar fallback directly in the progress element. This approach works, but is invalid, since the progress element does not allow flow content. The assumption we take from the allowable content is that we're supposed to accept a text-only progress bar fallback. This assumption of text-only fallback completely disregards the state of the art when it comes to progress bars that exists today.
  • I created a indeterminate progress bar application today. I discovered that you can't change height or width of the progress element after all. If you do change the progress bar's style setting, it adversely impacts on the indeterminate progress bar display. You have to accept the exact presentation of the progress bar, as determined by the browser. Frankly, I've never been overfond of the "blue gel" progress bar for Apple, and I think the progress bars, as implemented in WebKit, are ugly. Again, the indeterminate progress bar completely ignores the state of the art of "throbbers" that exists today. Can you see using this progress bar in Twitter?

I would move on to testing other new HTML5 elements, except for one small problem: the majority of new HTML5 elements have no real world implementation. Even many of the input elements, which have been around for six years have no implementation, or only partial implementation in one user agent, Opera.

As I wrote in an email to the HTML WG:

There are many new and modified elements in the HTML5 specification that do not have any implementation, and several that only have partial implementation by one User Agent. There are no implementations of any of the new or modified elements by any User Agent other than browsers (such as in authoring tools, or WYSIWYG plug-ins). Lack of implementation, or plans for implementation, especially when an element has been part of the WD for years, seems to meet the criteria for "features at risk". Features at risk are those most likely to be challenged during Last Call, which could impede progress of the document through the Last Call process.

We get so caught up in the gee whiz newness of HTML5, and all its perceived glamor and sexy techiness that we forget that, for all intents and purposes, three-quarters of the specification is untried.

updated: Cross-browser implementation of progress element

Shelley Fri, 05/14/2010 - 12:28

A useful coincidence: just after I wrote my concerns about the progress element, the WebKit nightly contains the first implementation of this element.

I created an application to test the element. It works as I expected, and is somewhat accessible, though Mac's VoiceOver would only voice the progress when the element first receives focus. Note, support for the element is only in Webkit nightly on the Mac.

I created a cross-browser version of the application that should work in most modern browsers—modern meaning IE8, not IE5.5, IE6, or even IE7. I had a heck of a time with the application.

The first challenge was the fact that IE8 doesn't allow dynamic styling of the progress element, even if you use an HTML5 shim. What was more surprising was that Webkit on the PC and Chrome had problems with the progress element, period. Both kept giving me errors about a progress element within a div element, and neither would allow any form of dynamic access.

If you try to emulate the progress element's effect, using the actual progress element in browsers that don't currently support the element, setting the background-color for the element wipes out the progress effect with the Webkit nightly. Other than setting width and height, you can't style the element. Or at least, I'm not sure how to style the element using general CSS properties.

I had to create a separate div element for those browsers that don't implement progress. To make it work, I tested for progress element support, and if the browser does not support the element, turn off its display and turn on the display of the div element workaround. I had to test on the element's form property to see if progress was supported. If you access the element, and it isn't null, and the form property is defined, then the progress element is supported. You can't test using nodeName, because all browsers return PROGRESS. Unfortunately, there is no elegant way to test for type of DOM object, such as HTMLProgressElement. There's a hack I found at Sam Ruby's weblog but that doesn't work for IE, and again, Chrome and Webkit on the PC had problems with any programmatic access of the element.

You can't provide a text description of the percentage by using the element's innerHTML property. I didn't try creating a new text node and attaching it to the progress element, but I don't expect this approach to work, either.

You also can't set a minimum value. The test case the WebKit developers attached for the new element uses the dir attribute to "reverse" the display.

update

I checked the HTML5 spec definition for progress again and found:

Content model:
    Phrasing content, but there must be no progress element descendants.

The HTML editing and WYSIWYG tools and validators are just going to love this. Anyway, supposedly this does mean that the element can take text. This must mean, then, that the Webkit implementation is incorrect.

second update

I created a variation of the application that embeds the fallback approach within the progress element itself. This seems to work fine. It cuts down a couple of lines of code, and at least looks a little more graceful (though it's not valid). Note that I had to turn off the display of the elements by default, as Webkit nightly sets the background on the progress element to be transparent by default.

Last Update

The WebKit installation is most likely correct in its handling of the text for the progress element. According to the specification:

Authors are encouraged to also include the current value and the maximum value inline as text inside the element, so that the progress is made available to users of legacy user agents.

Though not a directive to the user agents, we have to assume from this statement that UAs are not supposed to display the text if the progress element is supported. However, the direction is unclear, one has to make an assumption that this is what's happening in the browser.

This also means that if a person wants to include a text description of the progress, as I do in my original approach—something that happens frequently— you can't. Instead, you'll have to overlay the progress element with a div element and add the text to it.

You also have to use getAttribute and setAttribute to get and set the element's value attribute. Accessing the attribute directly only works when the element is supported.

Frankly, I will never use the progress or meter elements. They are inferior, less accessible, more cumbersome options compared to what we have today. That the elements were poorly thought out is obvious when one tries to actually implement them.