In the YUI 3 Gallery: Extensions for SVG, Created for SVG Wow!

By YUI TeamOctober 18, 2010


SVG (Scalable Vector Graphics) provides a declarative syntax for interactive, animated 2D graphics: shapes, images and text. SVG support is part of the HTML 5 specification and SVG is implemented by all major browsers, including Microsoft's Internet Explorer in version 9.

The web site showcases what can be done with SVG today. The demos on this web site were created for the SVG Open conference, where the SVG Wow! sessions have been a tradition for several years. The SVG Wow! sessions were started by Dean Jackson, then in collaboration with myself and then continued by Erik Dahlstrom. Erik and I have collorated on the session for the 2009 and 2010 editions of the conference.

For the past two years, the demos have increasingly used AJAX frameworks, applying their features to SVG instead of (or in addition to) HTML. YUI is the most widely used framework on the web site, which uses both YUI 2 and YUI 3.

I'll start with a quick SVG overview and then discuss the type of demos that YUI supported and the extensions I've added to the YUI 3 Gallery to make it work with SVG. (These extensions are now free to use under the terms of YUI's BSD license.)

SVG overview

Like HTML, SVG is a W3C specification. It provides a syntax for describing basic shapes (rectangles, circles, lines, polygons, ellipses, polylines), arbitrary shapes (described in terms of path segments which can be lines, quadratic or cubic Bezier curves), text and images.

The following image is a screen capture of the alternate stylesheet example on and shows some SVG features at play: rich rendering (shadow effects, gradients, patterns) and simple and complex shapes.

Because SVG images are defined in terms of geometry and rendering attributes, it is possible to render them at any resolution. As a result, SVG images can be scaled to any size while retaining a high rendering quality, for example when printing (no more jagged edges).

The following zoomed-in view shows the same SVG image shown earlier but rendered at a higher resolution while preserving the high quality.

Just like HTML, SVG supports interactivity: it is possible to add event listeners on graphic objects for mouse or keyboard interactions. Of course, SVG supports the Document Object Model, which makes it easy to manipulate the different properties of graphical objects, such as their geometry or rendering style.

There is a lot to the SVG specification: advanced rendering styles (stroking, filling, patterns, gradients), filter effects (blurs, shadows, color matrices), CSS styling, advanced text features (such as text on a path) and declarative animation. You can check out the references at the end of this post to learn more about the SVG format features.


With HTML5, SVG can be inlined in HTML documents without further ado. Browsers are starting to support that feature (e.g., Firefox 4). For the time being, all major browsers support SVG inlined in XHTML, which provides the same functionality. SVG in XHTML just requires that namespaces are properly declared.

<html xmlns="">
        <h1>Inline SVG</h1>

        <svg xmlns="" version="1.1"
         width="100%" height="100%" id="backgroundSVG">
            <!-- svg content here -->

All the code samples on this page use this way of inlining SVG in XHTML.


SVG supports declarative animation. For example, you can animate the radius of a <circle> element like this:

<circle cx="50" cy="100" r="40">
    <animate attributeName="r" values="40,60,20,40" dur="1.5s" />

The <animate> tag is borrowed from the SMIL specification and, along with the other animation elements, it provides a very powerful animation engine to SVG.

Unfortunately, until recently, browser support for SVG animation was sparse. It has improved over the past two years, but Microsoft has made it clear it will not support declarative SVG animation in IE 9.

As a result, most of the demos on the web site use scripted animation instead of declarative animations. On one hand, this is unfortunate because declarative animations are more efficient than scripted animations. On the upside, scripted animations can be very flexible, and they work across implementations very well.

The need for a good scripted animation solution is what drove the usage of YUI on the svg-wow demos. However, the demos also use other YUI features, in particular the Loader and Node modules.

Animating SVG with YUI

The demos on svg-wow use YUI to create elastic drum beats, morphing shapes or rotating text and shapes for example. Using YUI with SVG required a few YUI extensions; I'll describe these in just a moment.

rotating text and shapes morphing shapes
elastic drum beats

The following illustrates how YUI comes in handy to simply animate and manipulate SVG graphics.

Animating the SVG transform attribute

All SVG graphical elements have a transform attribute. That attribute specifies a 2D affine transformation on elements, which can be used to scale, skew, rotate or translate.

The YUI extensions for SVG allow animating the transform attribute like this:

var anim = new Y.Animate({
    node: '#circleA',
    from: {
        transform: {tx: 0, ty: 0, sx: 2, sy: 2}
    to: {
        transform: {tx: 20, ty: 20, sx: 1, sy: 1}
    transformTemplate: "translate(#tx, #ty) scale(#sx, #sy)",
    duration: 1

See the transform animations tests.

You'll note that the transform values are defined in terms of "components" (such as tx or ty) which are combined to form a value using the transformTemplate found on the animation configuration object.

The template is a flexible mechanism for building transform values while separate components make it easy to compute the animated values. This is an example where the YUI animation model allowed more flexibility (and more expressive power) than SVG's SMIL animation element (animateTransform). In order to create the animation described above, the equivalent SMIL declaration would have been:

<circle ...>
    <animateTransform attributeName="transform" type="translate"
                      from="0,0" to="20,20" dur="1s" begin="scaleAnim.begin"/>
    <animateTransform id="scaleAnim" attributeName="transform" type="scale"
                      from="2,2" to="1,1"  dur="1s" begin="indefinite"/>

Note how the above snippet requires multiple animateTransform elements which have to be synchronized: the begin attribute of the first animation is set to scaleAnim.begin to synchronize the start of the two animations. A nice feature of the YUI animation engine is that the timing of an animation (i.e., start, end and duration) can be shared to apply to multiple element properties.

The YUI extension for animating SVG transforms is used extensively, such as in the camera and animated lyrics examples. The former uses an extension of YUI 3 while the latter uses an extension of YUI 2.

Animating geometry
Basic Geometry

Animating SVG geometry with YUI is quite simple. The following example animates a <rect> element's width, height and corner radii:

var anim = new Y.Animate({
    node: '#rectA',
    from: {
        width: 200,
        height: 100,
        rx: 5,
        ry: 5
    to: {
        width: 300,
        height: 100,
        rx: 10,
        ry: 10;
    duration: 2,
    easing: Y.Easing.elasticOut

See the shape animations tests.

As discussed later on, some changes under the YUI hood made this work. But from a developer's perspective, this animation works the exact same way as the animation of any other HTML attribute or CSS property.

The <path>'s d attribute

One geometry attribute is a little special: the d attribute on the <path> element. The <path> element is used for arbitrarily complex geometry. A <path> can describe any shape. Its d attribute describes its geometry in terms of path segments which can be lines, arcs, quadratic or cubic Bezier curves (there are a few more commands, but they all map to Bezier curves).

Animating the d attribute also required a bit of extension to YUI's animation engine, but with that extension, the d attribute can be animated like any other, as shown below.

var anim = new Y.Animate({
    node: "#pathA",
    from: {d: "M 0 0 C 50 0 100 50 100 100 C 50 100 0 50 0 0 Z"},
    to: {d: "M 0 0 C 100 0 100 0 100 100 C 0 100 0 100 0 0 Z"},
    duration 1s,
    easing: Y.Easing.bounceBack

See the paths animations tests, which shows, among other things, a check mark morphing into a cross over time, as represented in the following images.

The Gandhi quotes demo uses this technique of animating the d attribute to morph shapes into Gandhi's figure.

Animating other SVG attributes

Of course, the YUI animations are not limited to geometry attributes. Any SVG attribute can be animated. For example, the following animation animates the blur radius on a horizontal blur filter.

// SVG snippet
<filter ..
    <feGaussianBlur id="blurFilter" stdDeviation="10 10" ... />

// JavaScript animation
var anim = new Y.Animate({
    node: '#blurFilter',
    from: {stdDeviation: [0, 20]},
    to: {stdDeviation: [0, 0]}

See the filter animations tests. The following image shows how animating a Gaussian blur can be used to transition between button states.

This type of effect is used in the fast blur effect demo, even though that demo does not use YUI animation but declarative SMIL animation elements (at the expense of only running in browsers supporting that feature, as explained earlier).

Animating CSS properties

Like HTML, SVG elements have attributes and also CSS properties. SVG has some specific CSS properties. These properties can be animated, sometimes to create surprising effects. For example, the stroke-dashoffset property can be used to simulate drawing a shape.

// SVG snippet
<rect id="rectA" width="100" height="50" stroke-dasharray="300 300" stroke-dashoffset="300" />

// JavaScript
var anim = new Y.Animate({
    node: "#rectA",
    to: {'stroke-dashoffset': 0},
    duration: 0.25

See the stroke animations tests.

The graffitis demo uses this technique (even though without YUI animation) and so does the camera demo (this time with YUI animation).

YUI and SVG: Under the hood

The web site uses both YUI 2 and YUI 3 and has SVG-specific extensions for both. The following section of this article focuses on the YUI 3 extensions.

Extensions were needed to:

  • make YUI work with SVG's DOM specificities
  • account for implementation differences
  • add support for new attribute types such as SVG transforms
  • add additional animation timing and synchronization features

Accounting for SVG DOM Specificities

As described earlier, SVG attributes can be animated with declarative elements such as <animate>. To support SVG's animation model, SVG attribute values hold both an animated and a base value. For example, the r attribute on a <circle> element is an SVGAnimatedLength defined as follows:

interface SVGAnimatedLength {
  readonly attribute SVGLength baseVal;
  readonly attribute SVGLength animVal;

As a result, even in implementations that do not support declarative animation, we need to reach down to the baseVal to read an attribute's value:

var circle = document.getElementById('#myCircle');
var rValue = circle.getAttribute('r').baseVal.value;

Extensions were needed to allow the animation engine to account for the SVG attributes' unusual value model. Thankfully, YUI 3 has a concept of animation behaviors. Behaviors are essentially attribute-specific hooks, and it was fairly easy to add support to handle SVG attribute values. For example, SVGAnimatedLength attributes are handled like so:

var lengthBehavior = {
    set: function (anim, att, from, to, elapsed, duration, fun) {
        // SVG specific handling

    get: function (anim, attr) {
        // SVG specific handling

// Handle <circle>'s r attribute
Y.Animate.behaviors.r = lengthBehavior;

There are more extensions for other SVG attributes values such as the transform attribute, color attribute values (like fill, stroke or stop-color) and attributes such as stdDeviation mentioned earlier.

A few similar tweaks were required, for example in the Y.Node.prototype.toString method, again to account for SVG's baseVal (this time on the className node property). Another example is the default node setter in the Node module.

Accounting for browser differences

While the previous extensions are required because of specification differences between HTML and SVG, the following are required because of implementation variations between browsers.

SVG has a special category of attributes called presentation attributes. In implementations also supporting CSS styling (which all browsers support), these presentation attributes are really just another way to specify a CSS property with a low specificity. From the SVG specification:

The presentation attributes thus will participate in the CSS2 cascade as if they were replaced by corresponding CSS style rules placed at the start of the author style sheet with a specificity of zero. In general, this means that the presentation attributes have lower priority than other CSS style rules specified in author style sheets or 'style' attributes.

Unfortunately, some browsers do not implement the specification correctly and window.getComputedStyle does not always account for all possible sources for setting the SVG CSS properties: CSS selectors, style attribute and presentation attributes.

YUI came to the rescue thanks to the Node module which could be extended to hide these browser differences. The Y.DOM.CUSTOM_STYLES and the Y.Node.prototype.getComputedStyle could be extended to offer a uniform way to read SVG style properties.

Extending Y.DOM

YUI wraps all DOM access through the Node interface. As a result, some SVG specific DOM methods, such as getBBox (used to compute the bounds of an SVG element), are not accessible on the wrapped object.

To make things easier to program for SVG, extensions to the default Y.DOM module (which Node uses) were added to either expose SVG DOM features or add convenience methods, commonly needed when manipulating content:

  • firstElement/lastElement/prevElement/nextElement/removeAllChildren (not SVG specific)
  • getMatrix/setMatrix. Provides an easy way to manipulate transforms on SVG elements, something notoriously difficult with the standard SVG DOM
  • getBBox/getViewportBBox provide simple ways to access bounding box in the element's coordinate system or in viewport space.
  • loadContent. A utility to insert a DOM fragment described using a JavaScript object literal. For example:
        tag: 'g',
        fill: 'red',
        stroke: 'none',
        children: [{
            tag: "rect",
            x: 10,
            y: 10,
            width: 200,
            height: 300
        }, {
            tag: 'circle',
            r: 10,
            cx: 105,
            cy: 155
        }, {
            tag: 'image',
            'xlink:href': 'images/photo.png',
            width: 200,
            height: '300px'
        }, prevSibling);

    is a shorthand for making various DOM calls (such as createElementNS, setAttributeNS and appendChild) to create a g element and its children and inserting it before prevSibling under myNode. The utility deals with namespaces for attributes and elements.

Additions to the Animation engine for timing and synchronization

Many, if not most effects involving animation require multiple choreographed animation instances. Typically, several animations are required to create a desired effect, and the start or end of animations depend on each other, sometimes with a time offset: animations need to be synchronized.

For example, if you have a set of shapes which need to fade in one after the other, you will need to create a fade animation for each element and then chain their start time with a slight offset.

var chained = Y.all('#chained circle'),
    firstAnim, previousAnim;

chained.each(function (circle) {
    var anim = new Y.Animate({
        node: circle,
        from: {'fill': 'white'},
        to: {'fill': 'gray'},
        duration: 0.25
    if (previousAnim !== undefined) {
        // Synchrnoize the start of anim to be 0.15 seconds after the begining
        // of the previous circle's animation (previousAnim).
        previousAnim.onBegin(anim, 0.15);
    } else {
        firstAnim = anim;
    previousAnim = anim;

// Start the first animation 1s after a click on any of the circles.
// Note that this is an extension to the default YUI run method which does not
// take a time offset.
chained.on('click', function () {;

See the time offsets tests.

The method onBegin makes it easy to synchronize the start of two animations, with an optional time offset. Actually, onBegin can also invoke a function with a time offset. Likewise, the onEnd extension makes it easy to synchronize with the end of an animation.

By default, YUI animations have events which provide a way to synchronize. The onBegin and onEnd methods express the synchronization more concisely (a similar example of conciseness is shown below).

In addition, it is sometime necessary to synchronize an animation with an event, again with a time offset. The beginOn and endOn extensions allow us to express that. For example:

anim.beginOn('#button'), 'click', 0.5);

will start the animation 0.5s after the element with id 'button' was clicked. This is a short-hand for:'#button').on('click', function () {
    setTimeout(500 /* ms */, function () {;});

A final extension made to the animation class was the ability to make an animation object apply its first frame's state before it was actually started. This is often needed when creating animation effects involving multiple animations which start at different time offsets.

var anim = new Y.Animate({
    from: {r: 30, 'fill-opacity': 0, color: 'crimson'},
    to: {r: 80, 'fill-opacity': 1, color: 'gold'},
    duration: 0.25

// the following will set the desired state on the target object prior to
// actually starting the animation.

The picture shuffle demo uses animation offsets for the effect that spreads the stack of pictures or puts the pictures back in a stack.


Working with SVG and YUI, and in particular YUI 3, has been a very enjoyable experience: a lot of the YUI functionality applies to SVG right out of the box and YUI's extensible architecture made it possible to work around occasional issues and to add desired functionality.

Of course, increased standard support for SVG in YUI would be helpful, in particular making YUI work with stand alone SVG documents and making the Node class wrap SVG elements without workarounds.

There are also a few enhancements that would be helpful. For example, it would help if animations could target multiple elements. Likewise, supporting multiple values (as in the <animate> SVG element for example) would be helpful to create more sophisticated effects.

The demos on were written for YUI 3.1 and ported to 3.2 for the purpose of this blog. In 3.2, transitions were introduced which make use of native CSS transitions if available in the browser. It might be possible for the YUI animation engine to similarly leverage SMIL animation where available (Opera, Firefox and WebKit at the time of this writing) which should also yield performance improvements.

The SVG extensions on the web site are available as a YUI 3 Gallery module for those who want to enjoy the fun of working with YUI and SVG.