воскресенье, 27 ноября 2011 г.

Building Your Site’s Personality

The two examples shared in this post are unlikely to be things you adopt on your site. Yet, well-designed transitions and animations are becoming an expected part of a modern Web experience. Windows 8 Metro style uses fluid and subtle animations extensively to help users better understand their interactions with the system. These literally make Windows 8 Metro style apps feel more responsive to touch.
We hope the examples here, the IE Test Drive demos, and the growing number of articles and examples elsewhere on the Web help you explore this new technology and add personality to your Web site.

Animations

CSS3 Animations are similar to CSS3 Transitions in that they smoothly animate a CSS value over time. The differences are (a) how one specifies the properties to animation, (b) how one triggers the animation and (c) the complexity of the animation possible.
You define animations using a CSS “keyframes” at-rule. A simple keyframes rule that matches the fade out behavior of the transition above would be:
@keyframes fadeOut {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
We apply this to our image with this CSS:
img {
animation-duration: 2s;
animation-delay: 0s;
animation-timing-function: linear;
animation-fill-mode: forwards;
}
img:hover {
animation-name: fadeOut;
}
Many of these properties are familiar from our discussion of transitions. The new ones are:
  • animation-fill-mode – the “forwards” value of this property means to maintain the “to” property values from the end of the animation going forward in time. The default value of this property is “none,” which causes the properties to return to their non-animated values at the end of the animation. (It’s possible to construct the CSS above without using animation-fill-mode. Simply add “opacity: 0;” to the img:hover rule to maintain the ending opacity at 0.)
  • animation-name – setting the animation-name property triggers the animation. When the animation-name property is set, the animation-delay time starts counting down. When animation-delay reaches zero, the animation begins and continues for the animation-duration. The animation-timing-function behaves the same as the transition-timing-function described above.
The power of CSS3 Animations lies in the ability to specify multiple keyframes with properties and intermediate values that don’t have to stay within the bounds of the start and end values. In CSS3 Transitions, intermediate values always progress from the start to the end; they will never go outside that range. Animations do not have that restriction.
This makes it possible to program a “bounce” such as shown in the markup and example below.
#bouncingImage {
width: 400px;
height: 267px;
box-shadow: 2px 2px 5px 0px gray;
animation-duration: 2s;
animation-timing-function: ease-in-out;
animation-fill-mode: forwards;
}
#bouncingImage:hover {
animation-name: zoomInBounce;
}

@keyframes zoomInBounce {
from {
transform: scale(1);
}
30% {
transform: scale(1.4);
}
40% {
transform: scale(1.15);
}
50% {
transform: scale(1.35);
}
60% {
transform: scale(1.2);
}
70% {
transform: scale(1.3);
}
80% {
transform: scale(1.225);
}
90% {
transform: scale(1.275);
}
to {
transform: scale(1.25);
}
}
Image used in the zoom in with bounce example
Move your mouse over the image to zoom it with a bounce effect.
CSS3 Animations are supported by your browser with -moz-animation.
An interactive demo of CSS3 Animations is available on the IE Test Drive site. The demo works in all browsers that support CSS3 Animations, including IE10 in the Windows Developer Preview.

Transitions

The function of CSS3 Transitions is very straightforward: smoothly change the computed value of a CSS property from its old value to its new value. Moreover, changes in value resulting from changes in an element’s CSS class or pseudo-class also trigger transitions.
Consider the following markup:
img {
opacity: 1;
transition-property: opacity;
transition-duration: 2s;
transition-delay: 0s;
transition-timing-function: linear;
}
img:hover {
opacity: 0;
}
The effect of this is that when the user moves his or her mouse over the image, the image will fade out smoothly over 2 seconds starting immediately, as illustrated below (I’ve added a dropped shadow on a wrapping element to illustrate the endpoint).
Fading one image to nothing over 2 seconds
Fading one image to nothing over 2 seconds
The transition properties that cause this to occur are:
  • transition-property – specifies which CSS properties are to be transitioned. The keyword “all” causes all animatable properties to transition when changed. The default value is “all.”
  • transition-duration – the time, in seconds or milliseconds, of the transition, starting after the transition-delay. The default value is zero, meaning that the transition is immediate.
  • transition-delay – the time, in seconds or milliseconds, after the value is changed before the transition starts. The time may be negative, in which case the transition starts part way through its duration. The default value is zero.
  • transition-timing-function – describes how the intermediate values of a transition are calculated. This allows a transition to change speed over its duration. The underlying function is a cubic Bézier curve; keywords match common functions. The default value is the keyword “ease,” a function that starts fast and slows down toward the end.
Fading one image to nothing is a simple example. Let’s say we wanted to fade one image to another, as illustrated below.
Fading from one image to another over 2 seconds
Fading from one image to another over 2 seconds
The following markup accomplishes this (except that vendor prefixes must precede all the transition properties).
HTML Fragment
<div id="imageWrapper">
<img id="backImage" src="imageB.jpg" /><img id="frontImage" src="imageA.jpg" />
div>
CSS Fragment
#imageWrapper {
display: inline-block;
width: 400px;
height: 267px;
box-shadow: 2px 2px 5px 0px gray;
position: relative;
}
#imageWrapper img {
width: 400px;
height: 267px;
position: absolute;
transition-property: opacity;
transition-duration: 2s;
transition-timing-function: linear;
}
#imageWrapper #frontImage, #imageWrapper:hover #backImage {
opacity: 1;
}
#imageWrapper:hover #frontImage, #imageWrapper #backImage {
opacity: 0;
}
Here’s a working version of the markup above:
Ending image of fade one image to another exampleStarting image of fade one image to another example
Move your mouse over the image to fade it to another.
CSS3 Transitions are supported by your browser with -moz-transition.
Simple transitions, such as the one above, are moderately easy to simulate in JavaScript. The benefits of CSS Transitions are their declarative definitions, making them easier than script, and they run—at least in IE10—asynchronously to the main processing thread resulting in smoother transitions and sites that are more responsive.
An interactive demo of CSS3 Transitions is available on the IE Test Drive site. The demo works in all browsers that support CSS3 Transitions, including IE10 in the Windows Developer Preview.

Adding Personality with CSS3 Transitions and Animations

Advancements like high-performance compiled JavaScript and hardware-accelerated rendering of HTML5 and CSS3 in Internet Explorer 9 and 10 allow Web developers to create richer and richer experiences. Two related features, CSS3 Transitions and CSS3 Animations, give Web developers a declarative way to add personality to Web page interactions easily.
This blog post describes these two features as implemented in IE10 in the Windows Developer Preview and Windows 8 Metro style apps written in HTML.

Same Markup—Except for the Vendor Prefix

Like nearly all features new to IE9 and IE10, CSS3 Transitions and Animations are standards-based features implemented with “same markup” interoperability in mind. However, unlike features such as border-radius, box-shadow, and text-shadow, which are part of stable W3C specifications, Transitions and Animations are still at a specification stage where vendors prefix their implementations. Therefore, in this case, “same markup” must be qualified as “same markup except for the vendor prefix.”
Many other writers have written about these features, including Rich Bradshaw’s excellent article Using CSS3 Transitions, Transforms and Animation. Many articles that discuss these features use only the -webkit- prefix in their examples. Users wishing to experiment in other browsers need to copy the example and change -webkit- to -ms-, -moz-, or -o-, as appropriate. Bradshaw’s examples are an exception; they already work in IE10!

Looking forward to the future of the Web

As the Web transitions from Web sites to Web apps, and as Web developers build new experiences in HTML5, we know that JavaScript will also need to make this transition without compromising its simplicity, flexibility, or performance. An approach that enables broad, incremental adoption by the Web developer community has the highest chance of success. Many of the ideas coming forward in the community support these ideas, and Microsoft will continue to work in the ECMA TC39 standards body to refine proposals for the core JavaScript runtime advancements. Most importantly, progress on the standard should be based on a dialog with Web developers on what is most needed in the Web platform.
We welcome your feedback and look forward to continuing to participate in this dialog.

The ECMAScript Standards Process

For the past couple of years, TC39 has been accepting proposals for new features to add to the ECMAScript standard. As we look at the current work being pursued in the committee, we see two categories of investments:
  • Work on the JavaScript runtime. This work (binary data, private names, globalization, etc.) offers valuable new capabilities to the platform, and can be made available in a feature-detectable way under the existing JavaScript script tags, allowing for smooth and near-term adoption of these features.
  • Work on JavaScript syntax. This work (let, destructuring, iterators, object literals, etc.) adds to the expressiveness of the JavaScript language, but also requires heavier weight versioning for developers, such as opting in to new script tags.
We prioritize the JavaScript runtime because it fundamentally limits the capabilities of the Web. We participate in the standards body to make sure these features can become ubiquitous tools developers can depend upon.

Larger Scale JavaScript

When building applications on a larger scale, developers depend upon high quality authoring and tooling experiences. For applications of this scale, higher-level abstractions such as classes and other common programming patterns can be the basis for better tooling.
The Office Web Applications, which consist of hundreds of thousands of lines of JavaScript, are written primarily in a variant of Script# that is then compiled into JavaScript that can be executed on today’s browsers. Other toolsets like the Google Web Toolkit take similar approaches. More recently, transforming compiler libraries like Traceur and CoffeeScript show how syntax additions to JavaScript and even completely alternative syntaxes can be supported in today’s browsers, without changes to the runtime.
Some examples, like Dart, portend that JavaScript has fundamental flaws and to support these scenarios requires a “clean break” from JavaScript in both syntax and runtime. We disagree with this point of view. We believe that with committee participant focus, the standards runtime can be expanded and the syntactic features necessary to support JavaScript at scale can be built upon the existing JavaScript standard.

Furthering the JavaScript Runtime

Looking ahead, there is a great opportunity for JavaScript to continue to evolve the core runtime. From talking to developers building HTML5 Web sites, we understand that these areas represent the most value:
  • Better integration with the native browser platform. With the introduction of recent APIs in HTML5, such as the File API, Canvas Pixel Array, and XHR2, there is an increasing need for JavaScript to have better interoperability with binary data streams. The need is so acute that there are many proposals across many Web communities and they are starting to converge in the Binary Data proposal. The Binary Data proposal aims to improve usability and expressivity for the use cases above.
  • Improved site load, especially for larger sites. JavaScript today would benefit from a standardized pattern for loading units of code consistently, in a way that won’t cross-contaminate the global scope, with a predictable loading order. A solution would benefit from being integrated into the runtime to ensure efficient page load times in coordination with the other browser subsystems. The modules and module loader proposals look like promising starting points which we aim to make available to scripts in “text/javascript” without needing to introduce breaking changes.
  • Execution performance and responsiveness. Libraries for interacting with intrinsic JavaScript types should continue to be filled out. As the String and Math extensions proposals suggest, JavaScript would benefit from an intrinsic string search like startsWith or contains and additions to the set of math functions to match other client platforms. JavaScript would also benefit from a format capability to replace variables in strings. Like ES5, when integrated into the runtime, these features can provide clear performance improvements for many real-world Web sites with minimal developer effort.

The Role of JavaScript in Improving the Web

These proposals are just part of a larger story of the evolution of JavaScript. In 1998, a complex JavaScript application was a few dozen lines of code. By 2008, leading-edge Web applications like Hotmail, Gmail, and CNN.com included hundreds of thousands of lines of JavaScript. Today, there are Web applications with a million lines of JavaScript. These Web applications look more and more like the applications we run on our desktops, with fewer page transitions and more processing occurring on the client, relying on the server for the occasional burst of data rather than frequent expensive server round-trips.
JavaScript is evolving to meet these needs, and it’s important that it does so in a way that respects everything that developers have invested in their own Web sites and their skill sets by focusing on compatibility and incremental introduction of new functionality.
We strongly believe in the community process driven through TC39 as the keepers of these principles. TC39’s work on ECMAScript 5 is a solid step forward for JavaScript in the Web platform. Some of the principles used to design ES5 provide a good template for future versions of the JavaScript standard:
  • Preserving the fundamental syntax of tomorrow’s “text/javascript” to ensure continuity in the developer skillset and deliver seamless compatibility between today’s JavaScript and tomorrow’s JavaScript.
  • Provide features that are additive and pay-as-you-go, to help developers get more value with minimal new effort or learning.
  • Strive for features to be locally detectable, to help developers build applications that work on the broadest range of browsers.
  • Where possible, allow for a possibly slower library alternative (or ‘polyfill’) for browsers that do not yet support the feature.
We are working with TC39 on applying these same approaches as broadly as possible for the next revision of the ECMAScript standard.

Details on the proposals

Computationally intensive Web applications quickly demonstrate that the built-in JavaScript math library is missing basic functions such as cosh and log10 that have been available in other programming language platforms such as C++, .NET, Java, and Python for years. String and Number can also benefit from some basic functionality common to all modern programming language platforms like testing if a String starts with a specific substring or checking that a Number is an Integer. These are addressed in the proposed additions to the Math, String, and Number APIs.
Web applications have been harder to globalize than native applications because JavaScript has not provided native date and currency formats that the underlying OS has. The drop includes a reference implementation of the proposed Globalization APIs which enable applications to deal correctly with locale specific number and date formats and strings in other languages. With this library, developers can show date and numbers in the specified locale and set collation options for the purposes of sorting and searching strings. Developers can also set date and number formats to use alternate calendars like the Islamic calendar or to show a number as the Chinese Yuan currency. This means that JavaScript applications no longer have to round trip to the server to properly display locale specific dates and numbers, which ultimately translates to faster interactive applications for end-users.

Evolving ECMAScript

For the Web and Web applications to keep making progress, the programming language of the Web must continue to improve. Today’s JavaScript standard lacks a few basic objects and library helpers that are vital for building rich, world-wide Web applications. Last week at the Ecma TC39 meeting at Apple’s campus in Cupertino, Microsoft shared reference implementations of proposals to address gaps in Math, String, and Number functionality as well as Globalization.
To ensure that others in the community are also able to provide feedback, we’re releasing these reference implementations via HTML5 Labs. We encourage you to download the prototypes, and play with the sample Web pages which demonstrate their usage. Try it out, and let us know if you have any feedback or suggestions in the comments.
These proposals provide a great deal of much needed functionality by adding only a few objects and library helpers:
Math String Number
cosh, sinh, tanh
acosh, asinh, atanh
log2, log10, log1p, expm1
sign
trunc
startsWith, endsWith
contains
repeat
toArray
reverse
isFinite
isNaN
isInteger
toInteger
 
Number Format Date Format Collator
format ( number ) format ( date ) compare ( x , y )
When running on Windows 7, the prototype implementation supports 363 available Locales, 18 numbering systems, many date patterns, and includes support for the Gregorian, Islamic, Hebrew, Buddhist, Korean, and Japanese calendars.
Note that as with all previous releases of HTML5 labs, this is an unsupported component with an indefinite lifetime. This should be used for evaluation purposes only and should not be used for production level applications.

понедельник, 14 ноября 2011 г.

Spellchecking and Multiple Languages

We know a lot of our customers speak and write in more than one language. It’s important that the spellchecking engine use the right language when you are entering text, and that it is easy to switch between languages when necessary.
In IE10, the selection of the spellchecking language is determined by evaluating the following sources (in priority order):
  • The HTML lang attribute. The Web developer knows the design and intent of the site and can control which parts of the page are associated with which language (in multi-language scenarios).
  • The keyboard input language. Windows 8 makes it easy for users to specify the languages they are interested in and to switch between them on the fly. To switch the language used by the spellchecking engine while entering text, you simply change the input language. With two or more languages configured (or two or more keyboard layouts) simply press the Windows key + spacebar. On the touch keyboard, there is a key to toggle the input language as well.
  • Window’s current display language (the language you are using to run Windows).
Switch between keyboard input languages via Win+Space or by the language key on the touch keyboard
Switch between keyboard input languages via Win+Space or by the language key on the touch keyboard
Spellchecking is an IE10 feature; while it is seamlessly integrated into Windows 8, we want to ensure that all users of IE10 benefit from this feature, including our users of IE10 on Windows 7. I’ll share more about the IE10 on Windows 7 experience in a future post.
Spellchecking in the browser will improve the accuracy and speed at which you input text on the Web. I’ve really enjoyed having it available and I know that the people with whom I correspond online also appreciate it!

Web Developer Options

As alluded to earlier, textarea and contenteditable elements are spellchecked by default; single-line input boxes (input type=text) are not checked by default since many sites use them for username fields or other purposes not suitable for spellchecking. We tried to pick good defaults, but if your Web site needs to change any of these defaults, it can. The ‘spellcheck’ attribute defined by HTML5 allows you as a developer to override the default spellchecking behavior for an element and all of its children.
By adding the spellcheck=false attribute value on any element, you disable spellchecking for all textarea, contenteditable, and input type=text elements that are children of the given element (including the element itself). Setting spellcheck=true enables spellchecking in the same scenario, and can also be used to override the spellchecking setting from a parent in the element tree. For example, if you want spellchecking disabled for all textarea elements on a page, with one exception, you can add the spellcheck=false attribute value to the HTML element, and then add a spellcheck=true attribute to the textarea element that is the exception.
Try out this capability using the spellchecking IE10 test drive demo.
The spellcheck attribute gives Web developers the flexibility to tailor the experience to the needs of their users.

Spellchecking in Your Language

Each of these spellchecking facilities (auto-correction, and word identification with corrective action menus), use the spellchecking dictionaries installed on your local PC. In the Windows Developer Preview, all of the dictionaries for all the supported languages are pre-installed. Many of the languages also include different language reform variants that you can toggle between in the re-designed Language control panel. All spellchecking options can be managed in the language control panel in Windows 8. On Windows 7, the spellchecking management experience for IE10 will be provided by the browser instead; I'll describe this in more detail in a future post.
The Windows 8 language options dialog for Portuguese (Brazil), including language reform variants
The Windows 8 language options dialog for Portuguese (Brazil), including language reform variants
Internet Explorer 10 supports spellchecking in many common languages. View a list of supported spellchecking dictionaries and language/locales, including language reform variants.
There are sometimes needs for highly specialized spellchecking dictionaries, for example, in specific industries with their own vernacular or for languages not commonly spoken such as Latin. To support these scenarios, the Windows 8 spellchecking facility supports 3rd party spellchecking engines. When installed, IE10 and all other Windows components will use the installed 3rd party spellchecking engine.

Word Identification and Corrective Actions Menu

No spellchecking experience would be complete without the red squiggles you’re familiar with from your favorite Office programs.
By default, as you enter text into any HTML textarea element (a multi-line input box) or any region of editable HTML content, the spellchecking engine will be used to check the last entered word. The word is checked against a dictionary associated with the current keyboard input language. If that word is misspelled or repeated it will be identified as a potential error using the familiar red squiggly underline. The identification of potential misspelled or repeated words is done in the background so that it does not slow your text entry.
The corrective actions menu has suggested alternate words and options to add the misspelled word to your custom dictionary or ignore the word. This works across all supported languages, including Portuguese (shown here).
The corrective actions menu has suggested alternate words and options to add the misspelled word to your custom dictionary or ignore the word. This works across all supported languages, including Portuguese (shown here).
The corrective actions menu will offer the most likely replacements for the identified word. You can replace the identified word with the suggested word in one step by selecting it from this menu. In addition you may choose to:
  • Add to dictionary. Your Windows user account has a built-in custom dictionary (which is initially empty). You may add frequently used words to this dictionary (in my case, I always need to add my last name). In Windows 8 this custom dictionary will be roamed to any other Windows 8 machine that you use via the cloud.
  • Ignore. The word will no longer be identified as a potentially misspelled word on this page. After you navigate away from the current page, the list of ignored words is cleared, and will again be flagged as a potential error.

Auto-correction

IE10 has the first browser-based implementation of auto-correct.
In some cases, a misspelled word is so common that it is better to just correct the word immediately, rather than wait for you to review the error later In the rare case that auto-correct changes something that you didn’t want changed, you can undo the change via CTRL+Z (Undo) using the keyboard, or bring up the auto-correction context menu using the mouse. In addition to using the mouse, the auto-correction menu can be activated via the keyboard by moving the insertion point inside of the word and pressing SHIFT+F10 (that key combo works to trigger any context menu). From the auto-correction menu you can also prevent the word from being auto-corrected in the future.
For auto-corrected words, press CTRL+Z to undo the change, or bring up a context menu for additional actions
For auto-corrected words, press CTRL+Z to undo the change, or bring up a context menu for additional actions
You can try out auto-correct in my test drive demo; it includes a short list of some of the common misspelled words that will be auto-corrected.

Typing with Speed and Accuracy in IE10

Typing quickly and accurately is a critical part of the user experience for any piece of software. When using a device without a physical keyboard, providing a great text input experience is even more important. Windows 8 provides several capabilities to make text input great on any device, and spellchecking is one of them.
Spellchecking in Windows 8 allows customers to identify misspelled words while they are entering text, have commonly misspelled words fixed automatically, and take corrective action on others. In Windows 8, spellchecking support is available to applications across the entire operating system, including IE10. Of course, spellchecking will also be available as an IE10 browser feature on all supported versions of Windows (including Windows 7).

воскресенье, 6 ноября 2011 г.

Call to Action

You’ve seen SVG in use. With its benefits outlined and some practical tips to avoid early roadblocks, there’s every reason to start experimenting with SVG to see how you can take advantage of it on your HTML5 Web site. Post some of your creations or links to other libraries – we’d love to see them!

Tools & Libraries

Though SVG is readable and can be crafted by hand, it is still largely visual and often unintuitive to translate a visual graphic into a mathematical description of its shape. Using vector design tools already in existence today, static SVG images can easily be created. Inkscape is an option available for free download. Adobe Illustrator, often used by professional Web developers to create vector images, can save files in the SVG format. Microsoft Visio, also capable of exporting in an SVG format, is tailored towards developing business diagrams and flowcharts. If optimization is important to you, note that these applications do not output SVG in the simplest format; their output contains proprietary namespace elements and attributes that allow for round-trip editing but are not useful for final production graphics. Additional markup cleanup may be desired for a reduction in file size or for easy styling.
In addition to Inkscape, another free SVG editor is SVG-edit. It is a JavaScript SVG editor and uses your browser to render the SVG creation! The latest alpha version has some great features. Try it in IE9!
IE9 supports WOFF fonts instead of SVG Fonts. WOFF fonts bridge the gap between HTML and SVG, reducing the learning curve for SVG and integrating SVG as a part of HTML. This makes it easy to apply the same custom fonts to both your HTML and SVG content. For those already acquainted with SVG fonts, Font Squirrel can convert your SVG Fonts to the WOFF format.
Another common problem is providing fallback support for older versions of IE that do not support SVG. SVG libraries on the Web often provide fallback support and abstract the process away from you. RaphaelJS is one of the most widely known that displays VML in older versions of IE. Charting libraries that provide graceful fallback, such as Highcharts are springing up all over the web.
These are just a few basic resources to help you get started. The tools and libraries in existence today fall into two camps: (1) creation of static, standalone SVG content and (2) programming dynamic, script-driven, and script-created SVG. Both have their place in your toolbox. For those of you pioneering SVG on the Web, you’ll find there is a lot to play around with.

Getting Started: Best Practices

Despite SVG’s similarities to HTML, some frequently made errors can easily be avoided. Listed below are some common mistakes to avoid so that you don’t waste time figuring out what’s going on.

HTML5 Doctype

If you are including SVG inline in HTML5, make sure you use the HTML5 doctype . This is a requirement of HTML5. Without specifying the appropriate doctype, your page will not render in the expected document mode in IE9 or IE10. As a result, your SVG content will not appear. Don’t forget to specify the HTML5 doctype!

Default Overflow

Like other HTML elements such as
, the default overflow for a top-level inline element is visible. (This is different from the default behavior of an element in XHTML, which is "overflow: hidden.") This default means that SVG content outside the element’s bounding box will be visible. In some cases, this can lead to unexpected behavior. You can remedy this by explicitly setting either the SVG attribute overflow="hidden" on your element or by adding svg { overflow: hidden; } to your document’s CSS block.
SVG element with default overflow SVG element with overflow=hidden

default overflow is visible

SVG content is clipped

Default Text Baseline Position

If you are creating SVG by hand, you may not realize that the y attribute of and elements refers to the baseline of your text. If you do not specify the y attribute, text is positioned at y=0 relative to its containing transform. This could mean the text baseline is positioned at the top of the SVG container and end up being invisible if you’ve set overflow="hidden" as described above. So, if you don’t see your text, check to see if the y attribute is specified with a positive value.
SVG text element default y attribute SVG text positioning with the y attribute specified
(default y=0)

Accessibility

Achieving a graphic fully accessible is challenging but because SVG supports adding descriptive text and titles to individual SVG graphic elements and groups of elements, it is possible to create an SVG graphic with much greater accessibility than an HTML element’s alt text.
Without any additional markup, text content is naturally readable by screen readers. For graphic elements, adding and <desc> tags as child elements of the shape or group allows screen readers access to that descriptive text. Like the <i>title</i> attribute of an HTML <img> element, SVG title elements display as a tooltip with the mouse is hovered over the containing shape.</p> <p>The following example illustrates the <i><title></i> element on a simple drawing.</p> <div style="font-family: Consolas, Monospace; font-size: 13px; color: Black; text-indent: -4em; padding: 0 0.25in;"> <div style="background-color: #f0f0f0; padding: 0 4px 2px 4px;"> <p style="margin: 0 0 0 4em;"><span style="color: Blue;"><?</span><span style="color: rgb(163,21,21);">xml</span> <span style="color: Red;">version</span><span style="color: Blue;">=</span>"<span style="color: Blue;">1.0</span>" <span style="color: Red;">encoding</span><span style="color: Blue;">=</span>"<span style="color: Blue;">UTF-8</span>"<span style="color: Blue;">?></span></p> <p style="margin: 0 0 0 4em;"><span style="color: Blue;"><</span><span style="color: rgb(163,21,21);">svg</span> <span style="color: Red;">xmlns</span><span style="color: Blue;">=</span>"<span style="color: Blue;">http://www.w3.org/2000/svg</span>" <span style="color: Red;"> xmlns:xlink</span><span style="color: Blue;">=</span>"<span style="color: Blue;">http://www.w3.org/1999/xlink</span>" <span style="color: Red;">width</span><span style="color: Blue;">=</span>"<span style="color: Blue;">500</span>" <span style="color: Red;">height</span><span style="color: Blue;">=</span>"<span style="color: Blue;">300</span>" <span style="color: Red;">viewBox</span><span style="color: Blue;">=</span>"<span style="color: Blue;">0 0 500 300</span>"<span style="color: Blue;">></span></p> <p style="margin: 0 0 0 5em;"><span style="color: Blue;"><</span><span style="color: rgb(163,21,21);">title</span><span style="color: Blue;">></span>Abstract Art<span style="color: Blue;"></</span><span style="color: rgb(163,21,21);">title</span><span style="color: Blue;">></span></p> <p style="margin: 0 0 0 5em;"><span style="color: Blue;"><</span><span style="color: rgb(163,21,21);">style</span> <span style="color: Red;">type</span><span style="color: Blue;">=</span>"<span style="color: Blue;">text/css</span>"<span style="color: Blue;">></span></p> <p style="margin: 0 0 0 6em;">/*<span style="color: Blue;"><![CDATA[</span><span style="color: Gray;">*/</span></p> <p style="margin: 0 0 0 6em;"><span style="color: Gray;">.c0, .c1, .c2 { fill-opacity: 1; fill-rule: evenodd; stroke-dasharray: none; stroke-linecap: round; stroke-linejoin: round; stroke-miterlimit: 4; stroke-opacity: 1; stroke-width: 10px; }</span></p> <p style="margin: 0 0 0 6em;"><span style="color: Gray;">.c0 { fill: #e3caad; stroke: #4e320e; }</span></p> <p style="margin: 0 0 0 6em;"><span style="color: Gray;">.c1 { fill: #bc9dc9; stroke: #4b1268; }</span></p> <p style="margin: 0 0 0 6em;"><span style="color: Gray;">.c2 { fill: #2cec7d; stroke: #2c9549; stroke-linecap: butt; stroke-linejoin: miter; }</span></p> <p style="margin: 0 0 0 6em;"><span style="color: Gray;">/*</span><span style="color: Blue;">]]></span>*/</p> <p style="margin: 0 0 0 5em;"><span style="color: Blue;"></</span><span style="color: rgb(163,21,21);">style</span><span style="color: Blue;">></span></p> <p style="margin: 0 0 0 5em;"><span style="color: Blue;"><</span><span style="color: rgb(163,21,21);">rect</span> <span style="color: Red;">class</span><span style="color: Blue;">=</span>"<span style="color: Blue;">c0</span>" <span style="color: Red;">width</span><span style="color: Blue;">=</span>"<span style="color: Blue;">131.429</span>" <span style="color: Red;">height</span><span style="color: Blue;">=</span>"<span style="color: Blue;">168.571</span>" <span style="color: Red;">x</span><span style="color: Blue;">=</span>"<span style="color: Blue;">37.143</span>" <span style="color: Red;">y</span><span style="color: Blue;">=</span>"<span style="color: Blue;">40.934</span>"<span style="color: Blue;">></span></p> <p style="margin: 0 0 0 6em;"><span style="color: Blue;"><</span><span style="color: rgb(163,21,21);">title</span><span style="color: Blue;">></span>Toast<span style="color: Blue;"></</span><span style="color: rgb(163,21,21);">title</span><span style="color: Blue;">></span></p> <p style="margin: 0 0 0 5em;"><span style="color: Blue;"></</span><span style="color: rgb(163,21,21);">rect</span><span style="color: Blue;">></span></p> <p style="margin: 0 0 0 5em;"><span style="color: Blue;"><</span><span style="color: rgb(163,21,21);">g</span><span style="color: Blue;">></span></p> <p style="margin: 0 0 0 6em;"><span style="color: Blue;"><</span><span style="color: rgb(163,21,21);">title</span><span style="color: Blue;">></span>Bunch of grapes<span style="color: Blue;"></</span><span style="color: rgb(163,21,21);">title</span><span style="color: Blue;">></span></p> <p style="margin: 0 0 0 6em;"><span style="color: Blue;"><</span><span style="color: rgb(163,21,21);">path</span> <span style="color: Red;">class</span><span style="color: Blue;">=</span>"<span style="color: Blue;">c2</span>" <span style="color: Red;">d</span><span style="color: Blue;">=</span>"<span style="color: Blue;">M314.286,78.076 340,15.219 428.571,26.648z</span>"<span style="color: Blue;">></span></p> <p style="margin: 0 0 0 7em;"><span style="color: Blue;"><</span><span style="color: rgb(163,21,21);">title</span><span style="color: Blue;">></span>Grape Leaf<span style="color: Blue;"></</span><span style="color: rgb(163,21,21);">title</span><span style="color: Blue;">></span></p> <p style="margin: 0 0 0 6em;"><span style="color: Blue;"></</span><span style="color: rgb(163,21,21);">path</span><span style="color: Blue;">></span></p> <p style="margin: 0 0 0 6em;"><span style="color: Blue;"><</span><span style="color: rgb(163,21,21);">circle</span> <span style="color: Red;">cx</span><span style="color: Blue;">=</span>"<span style="color: Blue;">270</span>" <span style="color: Red;">cy</span><span style="color: Blue;">=</span>"<span style="color: Blue;">100</span>" <span style="color: Red;">r</span><span style="color: Blue;">=</span>"<span style="color: Blue;">20</span>" <span style="color: Red;">class</span><span style="color: Blue;">=</span>"<span style="color: Blue;">c1</span>" <span style="color: Red;">id</span><span style="color: Blue;">=</span>"<span style="color: Blue;">grape</span>"<span style="color: Blue;">/></span></p> <p style="margin: 0 0 0 6em;"><span style="color: Blue;"><</span><span style="color: rgb(163,21,21);">use</span> <span style="color: Red;">xlink:href</span><span style="color: Blue;">=</span>"<span style="color: Blue;">#grape</span>" <span style="color: Red;">x</span><span style="color: Blue;">=</span>"<span style="color: Blue;">40</span>"<span style="color: Blue;">/></span></p> <p style="margin: 0 0 0 6em;"><span style="color: Blue;"><</span><span style="color: rgb(163,21,21);">use</span> <span style="color: Red;">xlink:href</span><span style="color: Blue;">=</span>"<span style="color: Blue;">#grape</span>" <span style="color: Red;">x</span><span style="color: Blue;">=</span>"<span style="color: Blue;">80</span>"<span style="color: Blue;">/></span></p> <p style="margin: 0 0 0 6em;"><span style="color: Blue;"><</span><span style="color: rgb(163,21,21);">use</span> <span style="color: Red;">xlink:href</span><span style="color: Blue;">=</span>"<span style="color: Blue;">#grape</span>" <span style="color: Red;">x</span><span style="color: Blue;">=</span>"<span style="color: Blue;">20</span>" <span style="color: Red;">y</span><span style="color: Blue;">=</span>"<span style="color: Blue;">35</span>"<span style="color: Blue;">/></span></p> <p style="margin: 0 0 0 6em;"><span style="color: Blue;"><</span><span style="color: rgb(163,21,21);">use</span> <span style="color: Red;">xlink:href</span><span style="color: Blue;">=</span>"<span style="color: Blue;">#grape</span>" <span style="color: Red;">x</span><span style="color: Blue;">=</span>"<span style="color: Blue;">60</span>" <span style="color: Red;">y</span><span style="color: Blue;">=</span>"<span style="color: Blue;">42</span>"<span style="color: Blue;">/></span></p> <p style="margin: 0 0 0 6em;"><span style="color: Blue;"><</span><span style="color: rgb(163,21,21);">use</span> <span style="color: Red;">xlink:href</span><span style="color: Blue;">=</span>"<span style="color: Blue;">#grape</span>" <span style="color: Red;">x</span><span style="color: Blue;">=</span>"<span style="color: Blue;">38</span>" <span style="color: Red;">y</span><span style="color: Blue;">=</span>"<span style="color: Blue;">80</span>"<span style="color: Blue;">/></span></p> <p style="margin: 0 0 0 5em;"><span style="color: Blue;"></</span><span style="color: rgb(163,21,21);">g</span><span style="color: Blue;">></span></p> <p style="margin: 0 0 0 4em;"><span style="color: Blue;"></</span><span style="color: rgb(163,21,21);">svg</span><span style="color: Blue;">></span></p> </div> </div> <p style="text-align: center; font-size: 8.25pt; font-style: italic;"> </p> <p>In addition, the <a href="http://www.w3.org/TR/SVGTiny12/interact.html#focusable-attr"><i>focusable</i> attribute</a> can be used to enable keyboard access to these descriptions. If <i>focusable="true"</i>, a tab stop will be created for that element, making it easy for a keyboard-centric user to focus on the shape and obtain its information from an accessibility tool. Additionally, tabbing to and from these elements will trigger the <i>focusin</i> and <i>focusout</i> events.</p> <h3>MIME type</h3> <p>If you are serving up standalone SVG files, ensure that the server is configured to be serving up the files with the proper MIME type. The correct SVG MIME type is <i>image/svg+xml</i>. This is not to be confused with image/svg-xml. Some already existing content may use the incorrect MIME type due to the Adobe SVG Viewer’s acceptance of it. Make sure you are using the correct MIME type.</p> <h3>SVGZ files</h3> <p>Similar to the above, if you are using compressed SVG, you should make the line <i> Content-Encoding: gzip</i> is in your header response of the SVG file, much like how other gzip-encoded files should have this header response line.</p> <h3>Scaling: viewBox and preserveAspectRatio</h3> <p>To ensure your graphics will scale the way that you’d like it to, specify the <a href="http://www.w3.org/TR/SVG/coords.html#ViewBoxAttribute">viewBox</a> attribute on your top-level <svg> element. With a viewBox specified, changing the height and width of the graphic will scale it rather than clip the SVG image.</p> <p>The <a href="http://www.w3.org/TR/SVG/coords.html#PreserveAspectRatioAttribute">preserveAspectRatio</a> attribute can also be used to control the scaling of images within SVG. The syntax of this attribute is preserveAspectRatio="<i>align</i> <i>meetOrSlice</i>". These two parameters describe the how an image is to fit into its containing <image> element and where the image is positioned within the container. By setting preserveAspectRatio="none", the SVG <image> element behaves like the HTML’s <img> element as illustrated below.</p> <p style="text-align: center; font-size: 8.25pt; font-style: italic;"> <img alt="Photo of two giraffes" style="vertical-align: top; border: solid 1px black !important;" src="http://ieblog.members.winisp.net/images/20111027-giraffes.jpg" width="200"><img alt="Photo of two giraffes scaled to fit odd container" style="margin-left: 0.25in; vertical-align: top; border: solid 1px black !important;" src="http://ieblog.members.winisp.net/images/20111027-giraffes.jpg" height="81" width="200"><br> <span style="display: inline-block; max-width: 424px;">Left: image at its original aspect ratio; Right: same image stretched into a 200 x 81 container with preserveAspectRatio="none"</span> </p> <p style="margin-bottom: 0">Things get interesting when preserveAspectRatio is not "none". In such cases you control how the image aligns within a container of a different aspect ratio than the image itself. The <i>meetOrSlice</i> parameter determines whether the image is scaled down to fit within the container (<i>meet</i>) or scaled up to fill the container (<i>slice</i>). The <i>align</i> parameter specifies how to align the image within its container. Three options—min, mid, and max—are provided for each direction—x and y. This yields nine combinations of alignments specified as:</p> <ul style="margin-top: 0;"><li>xMinYMin – align image in left-top corner of container</li><li>xMidYMin – align image at center-top of container</li><li>xMaxYMin – align image in right-top corner of container</li><li>xMinYMid – align image at left-middle of container</li><li>xMidYMid – align image at center-middle of container</li><li>xMaxYMid – align image at right-middle of container</li><li>xMinYMax – align image in left-bottom corner of container</li><li>xMidYMax – align image at center-bottom of container</li><li>xMaxYMax – align image in right-bottom corner of container</li></ul> <p>The following examples show how an image is aligned for its controlling alignment. Note that <i>align</i> only matters in one dimension at a time; the image exactly fills the container in the other dimension so it doesn’t matter whether that dimension is min, mid, or max.</p> <div style="margin: 1em 0; text-align: center;"> <div style="max-width: 95%; margin: 0 auto;"> <table style="margin-right: 0.25in; vertical-align: middle; display: inline-block; font-family: Consolas; font-size: 13px; text-align: right;" border="0" cellpadding="0" cellspacing="8"> <tbody><tr> <td>xMin</td> <td width="200"> <img alt="Example of preserveAspectRatio="xMinY* meet"" src="http://ieblog.members.winisp.net/images/20111027-giraffes_meet_xMin.png" width="200"></td> </tr> <tr> <td>xMid</td> <td> <img alt="Example of preserveAspectRatio="xMidY* meet"" src="http://ieblog.members.winisp.net/images/20111027-giraffes_meet_xMid.png" width="200"></td> </tr> <tr> <td>xMax</td> <td> <img alt="Example of preserveAspectRatio="xMaxY* meet"" src="http://ieblog.members.winisp.net/images/20111027-giraffes_meet_xMax.png" width="200"></td> </tr> </tbody></table> <table style="vertical-align: middle; display: inline-block; font-family: Consolas; font-size: 13px; text-align: center;" border="0" cellpadding="0" cellspacing="8"> <tbody><tr> <td>YMin</td> <td>YMid</td> <td>YMax</td> </tr> <tr> <td width="81"> <img alt="Example of preserveAspectRatio="x*YMin meet"" src="http://ieblog.members.winisp.net/images/20111027-giraffes_meet_yMin.png" height="200"></td> <td width="81"> <img alt="Example of preserveAspectRatio="x*YMid meet"" src="http://ieblog.members.winisp.net/images/20111027-giraffes_meet_yMid.png" height="200"></td> <td width="81"> <img alt="Example of preserveAspectRatio="x*YMax meet"" src="http://ieblog.members.winisp.net/images/20111027-giraffes_meet_yMax.png" height="200"></td> </tr> </tbody></table> </div> <span style="font-size: 8.25pt; font-style: italic;">meetOrSlice parameter = "meet": image is scaled down to fully fit within the container leaving empty space if the container aspect ratio differs from that of the image</span> </div> <div style="margin: 1em 0; text-align: center;"> <div style="max-width: 95%; margin: 0 auto;"> <table style="margin-right: 0.25in; vertical-align: middle; display: inline-block; font-family: Consolas; font-size: 13px; text-align: center;" border="0" cellpadding="0" cellspacing="8"> <tbody><tr> <td>xMin</td> <td>xMid</td> <td>xMax</td> </tr> <tr> <td width="81"> <img alt="Example of preserveAspectRatio="xMinY* slice"" src="http://ieblog.members.winisp.net/images/20111027-giraffes_slice_xMin.png" height="200"></td> <td width="81"> <img alt="Example of preserveAspectRatio="xMidY* slice"" src="http://ieblog.members.winisp.net/images/20111027-giraffes_slice_xMid.png" height="200"></td> <td width="81"> <img alt="Example of preserveAspectRatio="xMaxY* slice"" src="http://ieblog.members.winisp.net/images/20111027-giraffes_slice_xMax.png" height="200"></td> </tr> </tbody></table> <table style="vertical-align: middle; display: inline-block; font-family: Consolas; font-size: 13px; text-align: right;" border="0" cellpadding="0" cellspacing="8"> <tbody><tr> <td>YMin</td> <td width="200"> <img alt="Example of preserveAspectRatio="x*YMin slice"" src="http://ieblog.members.winisp.net/images/20111027-giraffes_slice_yMin.png" width="200"></td> </tr> <tr> <td>YMid</td> <td> <img alt="Example of preserveAspectRatio="x*YMid slice"" src="http://ieblog.members.winisp.net/images/20111027-giraffes_slice_yMid.png" width="200"></td> </tr> <tr> <td>YMax</td> <td> <img alt="Example of preserveAspectRatio="x*YMax slice"" src="http://ieblog.members.winisp.net/images/20111027-giraffes_slice_yMax.png" width="200"></td> </tr> </tbody></table> </div> <span style="font-size: 8.25pt; font-style: italic;">meetOrSlice parameter = "slice": image is scaled up to fully fill the container cuttin off some of the image if the container aspect ratio differs from that of the image</span> </div> <p>SVG’s preserveAspectRatio property gives you the control to define both the scaling and positioning of an image within its container. preserveAspectRatio="none" yields behavior common with HTML.</p> <h3>Scripting: SVG DOM vs. Core DOM</h3> <p>The getAttribute() and setAttribute() methods come from the DOM Core specification and apply to HTML and XML alike, including SVG. These methods are familiar, easy, and consistent ways to make changes to element attributes. Regardless of the attribute to be changed, setAttribute(<i>attribute</i>, <i>value</i>) can always be used. However, performance gains can often be attained by taking advantage of the SVG DOM. SVG supports its own DOM that exposes a multitude of attribute values and methods. Due to the nature of the SVG DOM, modifying attribute values requires a steeper learning curve than simply using setAttribute(). But the SVG DOM provides direct access to attribute values, which both improves performance and can make value manipulation simpler.</p> <p>For instance, the following function doubles the radius of a circle element using setAttribute():</p> <div style="font-family: Consolas, Monospace; font-size: 13px; color: Black; text-indent: -4em; padding: 0 0.25in;"> <div style="background-color: #f0f0f0; padding: 0 4px 2px 4px;"> <p style="margin: 0 0 0 4em;"><span style="color: Blue;">function</span> doubleCircleRadius(circle) {</p> <p style="margin: 0 0 0 6em;">circle.setAttribute(<span style="color: Maroon;">"r"</span>, 2 * parseFloat(circle.getAttribute(<span style="color: Maroon;">"r"</span>)));</p> <p style="margin: 0 0 0 4em;">}</p> </div> </div> <p>By contrast, using the SVG DOM, achieving the same effect looks like this:</p> <div style="font-family: Consolas, Monospace; font-size: 13px; color: Black; text-indent: -4em; padding: 0 0.25in;"> <div style="background-color: #f0f0f0; padding: 0 4px 2px 4px;"> <p style="margin: 0 0 0 4em;"><span style="color: Blue;">function</span> doubleCircleRadius(circle) {</p> <p style="margin: 0 0 0 6em;">circle.r.baseVal.value *= 2;</p> <p style="margin: 0 0 0 4em;">}</p> </div> </div> <p>With the setAttribute() and getAttribute() methods of the Core DOM, parsing will often be required to manipulate values. Modifying values based on the existing ones is easier done with the SVG DOM.</p> <p>Because the SVG DOM accesses attributes directly instead of dealing in strings, value type awareness is necessary and makes scripting with it more complex.</p> <p>Below is a table describing a generalization of how to access a few common attributes:</p> <table style="border-collapse: collapse; margin-left: auto; margin-right: auto;" cellpadding="0" cellspacing="0"> <tbody><tr> <th style="padding: 4px; border: 1px solid gray !important;">Value “type” </th> <th style="padding: 4px; border: 1px solid gray !important;">Attribute examples </th> <th style="padding: 4px; border: 1px solid gray !important;">DOM access </th> </tr> <tr> <td style="padding: 4px; border: 1px solid gray !important;">Presentation attribute </td> <td style="padding: 4px; border: 1px solid gray !important;">fill, stroke </td> <td style="padding: 4px; border: 1px solid gray !important;">elem.style.<i>fill</i> </td> </tr> <tr> <td style="padding: 4px; border: 1px solid gray !important;">Length </td> <td style="padding: 4px; border: 1px solid gray !important;">r, width, height, cx, cy, x, y </td> <td style="padding: 4px; border: 1px solid gray !important;">elem.<i>r</i>.baseVal.value </td> </tr> <tr> <td style="padding: 4px; border: 1px solid gray !important;">Object </td> <td style="padding: 4px; border: 1px solid gray !important;">viewBox </td> <td style="padding: 4px; border: 1px solid gray !important;">elem.<i>viewBox</i>.baseVal.<i>x</i><br> elem.<i>viewBox</i>.baseVal.<i>y</i><br> elem.<i>viewBox</i>.baseVal.<i>width</i><br> elem.<i>viewBox</i>.baseVal.<i>height</i> </td> </tr> <tr> <td style="padding: 4px; border: 1px solid gray !important;">List </td> <td style="padding: 4px; border: 1px solid gray !important;">transform, d </td> <td style="padding: 4px; border: 1px solid gray !important;">elem.<i>transform</i>.baseVal.getItem(0); </td> </tr> </tbody></table> <p>The SVG DOM interfaces are documented at the end of each chapter in the <a href="http://www.w3.org/TR/SVG/">SVG specification</a>.</p></DIV>

When to use SVG in HTML5

As the declarative graphics format in HTML5, SVG is designed for graphics that need to scale, contain selectable text, are dynamic and interactive, or benefit from being styled using CSS. (For a comparison of SVG and HTML5’s procedural 2D graphics element, , see Thoughts on when to use Canvas and SVG.)

Scalable Graphics

Graphics are used in different contexts and on different mediums. SVG is an excellent choice because fidelity is maintained at all resolutions—important for dealing with different device form factors and high-quality printing. For instance, SVG is a great format for logos as illustrated by the W3C HTML5 logo below.

The W3C HTML5 logo at different sizes

Selectable Text

Images containing text are better served as SVG than a raster alternative. Charts and diagrams fall under this category. In addition to the added benefit of scalability, the text in charts and diagrams retains the properties of text. It can be copied and pasted, searched, and easily updated. Image headers containing decorative text may be candidates for using SVG. WOFF fonts combined with a text stroke and gradient or pattern fill enables customized text to remain selectable and indexed by search engines.
Flow charts, for instance, tend to be composed mostly of text, which incidentally serves as good search terms for the image. As can be seen in the screenshot below, the text within an SVG chart can be selected; just like other text, it can be copied, crawled by a search engine, or even used in conjunction with Accelerators in IE.
SVG flowchart showing selected text
A flowchart showing selected text

Dynamic and Interactive Graphics

Dynamic and interactive graphics can include games, maps, graphs, seating charts, and more. One use of SVG that Internet users frequently encounter can be found on Bing and Google maps. When requesting directions, they draw a blue SVG path that your car should follow, overlaid on a raster map image. SVG can be generated through client-side scripting, which is great for making minor additions to existing images as with mapping directions. SVG’s rich DOM support also makes it fantastic for dynamically changing images. Charts can be updated in the browser as data changes. Shapes can move and change size or color by altering their DOMs. Additionally, SVG’s hit testing abilities mean that precise interactions with shapes can occur. Much like with HTML elements, event handlers can be attached to an SVG element. However, unlike HTML elements, mouse events will only be affected by mouse interactions on the shape and not its entire rectangular bounding box.
Map showing SVG driving directions overlay
Map showing driving directions: base map is a bitmap image, driving path is overlaid SVG

Formatting with CSS

The benefits of styling content with CSS are another core reason for using SVG. Every shape in SVG is reflected in the DOM and contains all information about the graphic, including the appearance of each shape. This makes it easy to update the styling information about each shape. UI elements can benefit from using SVG as it allows for non-rectangular shapes and its appearance is customizable. The fills, strokes, and opacity of shapes can be modified via a new stylesheet, via script, or even via a pseudo selector such as :hover.
These benefits of SVG are not mutually exclusive. For example, below is a map graphic that displays data over time. It scales well and utilizes multiple stylesheets to show data changes over time. On this map, only the colors of the states are changing. Each state is represented by a element with an id corresponding to its postal code. Using CSS selectors on these ids, the fill color of the shapes is specified in stylesheets that are each applied as appropriate when cycling through years. Election maps often show data trends in this color-coded manner. You could easily envision live election result updates requiring only minor modification of the graphic. These updates are simple, isolated, and small.

A choropleth map of the United States illustrating some data over time

Best Practices for Getting Started with SVG

Web graphics in SVG (Scalable Vector Graphics) format offer better quality display over a broader range of device sizes compared to bitmap-based graphics. SVG also has inherent accessibility making it the best choice for interactive graphics and those involving text.
SVG usage on the Web continues to grow. Last week at SVG Open 2011, we had the opportunity to meet with and hear from Web developers putting SVG to use in a wide variety of real-world applications. These applications include data-driving charts, technical drawings, games, interactive instructional diagrams, and geographic visualization of data.
Though the SVG specification itself is nearing a decade old, SVG wasn’t available as an inline element in HTML until the HTML5 specification. As browsers support SVG as part of HTML5, the next generation Web can use these technologies to enable Web experiences previously available only with the use of plug-in technologies. SVG’s easy integration with HTML markup, CSS, the HTML DOM, and JavaScript makes it a natural choice for building integrated, interactive experiences that are stylable and adaptable to different form factors. SVG is also the declarative vector graphics technology for building Windows 8 Metro style apps using HTML.
In this post, I offer ideas for when to use SVG in your HTML5 Web sites and outline some best practices to help you get started with SVG.

Testing Sites that Use Vendor-Prefixed Properties

A common question is what property names to use if some browsers don’t yet support the property or if no browser supports the standards-based property without a prefix. There are a couple approaches, each with merit:
  1. Always include all expected names, even if they don’t yet work in shipping browsers. The benefit of this path is that as browsers add support with their vendor prefix or add support for the non-prefixed property, your site will “just work” without changes. The risk is that the site will automatically pick up behavior you’ve never tested. A vendor prefix indicates the behavior isn’t finalized and all prefixed properties and the non-prefixed property may not behave the same, so as browsers add support your site might “just not work.”
  2. Only include property names you can test. The benefit is that your site will behave the same as when you first wrote it even as browsers add support for new properties. The risk is that you have unnecessarily degraded functionality. For sample or demo sites, people can interpret this as a browser not having a feature at all.
You need to determine the right path for your site. In most of our demos we want to show off new Web platform functionality in any browser that supports it. And since small errors in these demos don’t create big problems for users, we usually choose option #1. On the other hand, if you have a production site where a change in behavior will cause a problem for your business, you may opt for the more risk-averse path.
Regardless of which path you choose, the one constant is testing. When using vendor-prefixed properties you’re leveraging early, often unstable functionality that can change even after a browser first introduces support for a property, so it’s critical to test with each browser update to make sure your site functions as expected.

Consolidating Vendor-Prefixed Properties to a Single Name

A better pattern is to define a method that loops through a list of property names and returns the first supported property or null if the browser doesn’t support any of them.
function FirstSupportedPropertyName(prefixedPropertyNames) {
var tempDiv = document.createElement("div");
for (var i = 0; i < prefixedPropertyNames.length; ++i) {
if (typeof tempDiv.style[prefixedPropertyNames[i]] != 'undefined')
return prefixedPropertyNames[i];
}
return null;
}
We then initialize a variable for each vendor-prefixed property we use, passing it an array of possible properties in the order we prefer to use them.
var transformName = FirstSupportedPropertyName(["transform", "msTransform", "MozTransform", "WebkitTransform", "OTransform"]);
var backfaceVisibilityName = FirstSupportedPropertyName(["backfaceVisibility", "msBackfaceVisibility", "MozBackfaceVisibility", "WebkitBackfaceVisibility", "OBackfaceVisibility"]);
var transitionName = FirstSupportedPropertyName(["transition", "msTransition", "MozTransition", "WebkitTransition", "OTransition"]);
var animationName = FirstSupportedPropertyName(["animation", "msAnimation", "MozAnimation", "WebkitAnimation", "OAnimation"]);
var gridName = FirstSupportedPropertyName(["gridRow", "msGridRow", "MozGridRow", "WebkitGridRow", "OGridRow"]);
var regionsName = FirstSupportedPropertyName(["flowFrom", "msFlowFrom", "MozFlowFrom", "WebkitFlowFrom", "OFlowFrom"]);
var hyphensName = FirstSupportedPropertyName(["hyphens", "msHyphens", "MozHyphens", "WebkitHyphens", "OHyphens"]);
var columnName = FirstSupportedPropertyName(["columnCount", "msColumnCount", "MozColumnCount", "WebkitColumnCount", "OColumnCount"]);
Then code throughout your site that uses these properties becomes something like this:
var elm = document.getElementById("myElement");
if (transitionName) {
elm.style[transitionName + "Property"] = "all";
elm.style[transitionName + "Duration"] = "3s";
elm.style[transitionName + "Delay"] = "0s";
}
else {
// fallback for browsers without CSS3 transitions
}
Note the simple feature detection enabled by returning null in FirstSupportedPropertyName.
That pattern also works when CSS properties have vendor prefixes. You can use a slightly different pattern for cases where a CSS value (for example, linear-gradient) has vendor prefixes:
function FirstSupportedFunctionName(property, prefixedFunctionNames, argString) {
var tempDiv = document.createElement("div");
for (var i = 0; i < prefixedFunctionNames.length; ++i) {
tempDiv.style[property] = prefixedFunctionNames[i] + argString;
if (tempDiv.style[property] != "")
return prefixedFunctionNames[i];
}
return null;
}
 
var linearGradientName = FirstSupportedFunctionName("backgroundImage", ["-ms-linear-gradient", "-moz-linear-gradient", "-webkit-linear-gradient", "-o-linear-gradient"], "(top, black, white)");
var radialGradientName = FirstSupportedFunctionName("backgroundImage", ["-ms-radial-gradient", "-moz-radial-gradient", "-webkit-radial-gradient", "-o-radial-gradient"], "(50% 50%, circle cover, black, white)");