转自:SVG Authoring Guidelines

在这篇文章里,作者列出了出现在很多SVG作品中的坏习惯,这些都可能会造成一些兼容的问题,只是Adobe的SVG Viewer忽略了这些错误(非标准的东西)。现在SVG还在发展初期,希望大家不要像在写HTML的时候被IE养成坏习惯一样给Adobe SVG Viewer养成坏习惯。
目前Adobe对SVG的支持还是未知数,如果大家希望自己的基于SVG的作品能有继续在其他SVG的实现上运行,如Mozilla, Batik,那么请看看我转载的这篇文章。

This is a work in progress. Please send me your feedback and suggestions!

There are a lot of mistakes in the SVG documents currently found on the Web. Because Adobe's SVG Viewer ignores many of these errors, the maintainers of these documents usually don't realise when they're doing something wrong. Unfortunately, the result is that far too often SVG on the Web doesn't work in Mozilla, Batik or one of the other SVG implementations. It is important that these problems are addressed as soon as possible to prevent them from propagating into authoring tools and the SVG documents that people will write in the future.

This document highlights some of the most common mistakes made in SVG content, and explains what SVG maintainers can do to fix them. The hope is that the SVG community will read this document, and that individual members of the community will do what they can to make sure that SVG on the Web is as portable as possible. Please spread the word. If you see others making any of the mistakes described here, please let them know so that they can correct them. Even more important, if you know of SVG authoring tools that make these mistakes please contact the vendor and let me know. Feel free to link to this document, and please send me your feedback. My email address is jwatt@jwatt.org.

Contents

Configure your server for SVG

This isn't really an issue with SVG content itself, but nevertheless, server misconfiguration is a very common reason for SVG failing to load. For security and correctness reasons, some browsers decides how to handle files by looking at the HTTP headers the server sends with them. If your server isn't configured to send the correct headers with the SVG files it serves, then a browser like Mozilla won't treat those files as SVG. Instead it will most likely show the markup of the files as text or encoded garbage, or even ask the viewer to choose an application to open them. For normal SVG files, servers should send the HTTP header:

Content-Type: image/svg+xml

For gzipped SVG files, servers should send the HTTP headers:

Content-Type: image/svg+xml
Content-Encoding: gzip

You can check that your server is sending the correct HTTP headers with your SVG files by using a site such as web-sniffer.net. Submit the URL of one of your SVG files and look at the HTTP response headers. If you find that your server is not sending the headers with the values given above, then you should contact your Web host. If you have problems convincing them to correctly configure their servers for SVG, there may be ways to do it yourself. See the server configuration page on the SVG wiki for a range of simple solutions.

Don't include a DOCTYPE declaration

XML Document Type Definitions, or DTDs for short, are a feature of XML used to validate the contents of a document. A DTD is associated with a document by placing a DOCTYPE declaration in the document. The following line is an example of an SVG DOCTYPE declaration.

<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">

Unfortunately the SVG DTDs are a source of so many issues that the SVG WG has decided not to write one for the upcoming SVG 1.2 standard. In fact SVG WG members are even telling people not to use a DOCTYPE declaration in SVG 1.0 and 1.1 documents. Instead always include the 'version' and 'baseProfile' attributes on the root <svg> tag, and assign them appropriate values as in the following example.

<svg version="1.1"
baseProfile="full"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:ev="http://www.w3.org/2001/xml-events">

If for some reason you want to use the inline features of DOCTYPE declarations (to create entities, etc.), simply omit the public and system identifiers. Your DOCTYPE declaration should then look like this.

<!DOCTYPE svg [
<!-- entities etc. here -->
]>

Bind the required namespaces

SVG is a namespaced XML dialect, and as a consequence all the XML dialects used in your SVG documents must be bound to their namespace as specified in the Namespaces in XML recommendation. It is sensible to bind the SVG and XLink namespaces at a minimum, and possibly also the XML Events namespace. Even if you don't use XLink or XML Events in the current incarnations of some of your SVG documents, including the bindings will prevent annoying errors if you decide to use them later and forget to add the bindings. This simply requires you to include the following three attributes on the root <svg> tag in your SVG documents.

<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:ev="http://www.w3.org/2001/xml-events">

Be careful not to type xmlns:svg instead of just xmlns when you bind the SVG namespace. This is an easy mistake to make, but one that can break everything. Instead of making SVG the default namespace, it binds it to the namespace prefix 'svg', and this is almost certainly not what you want to do in an SVG file. A standards compliant browser will then fail to recognise any tags and attributes that don't have an explicit namespace prefix (probably most if not all of them) and fail to render your document as SVG.

Avoid the 'style' attribute where possible

It is quite common to see the style attribute used to specify properties in SVG. For example, you may see source code that specifies the fill and stroke properties as follows:

<circle style="fill:red; stroke:blue;" ... />

Usually this is simply gratuitous use of the style attribute, and something that should be avoided. Contrary to popular belief the style attribute (note, that's attribute, not element) doesn't separate content from presentation, and unless you need to override properties set by a CSS selector, it is best to use the SVG formatting attributes instead. In other words it would be better to rewrite the previous code snippet as:

<circle fill="red" stroke="blue" ... />

Using the formatting attributes avoids the pitfalls that can be encountered when using CSS in SVG (see the following section, for example) and is generally considered to be better style. Unlike CSS and the style attribute, the formatting attributes are also supported in SVG Tiny, if that matters to you. Unfortunately many SVG authoring tools and human authors still make unnecessary use of the style attribute.

Specify units when assigning lengths to properties

SVG uses styling properties to describe many of its document parameters such as fill and stroke-width. These properties can be set by CSS declarations or by presentation attributes (XML attributes that share the same name as the property and map to their corresponding CSS properties if the implementation supports CSS). For example, the display property is set on a circle by both:

<circle style="display:none;" ...>

and:

<circle display="none" ...>

For most properties there should be few interoperability problems, but frustratingly when properties are assigned a length the visual result can be completely different in the various SVG implementations. The problem arises because the SVG specification allows units to be omitted from lengths (in which case the lengths' units are the units of the current coordinate system (user units)), while on the other hand the CSS specification absolutely requires units to be explicity specified for all length values. The question is, are units required for lengths assigned to properties in SVG or not? Which specification takes precedence?

Unfortunately, this issue is a lot more compex than it first seems, and the answers to these questions are still disputed. The result is that implementations don't agree. Some require units, while others don't. The only way to avoid problems is to always specify a unit when assigning lengths to properties. Happily, in SVG, px units are defined to be equivalent to the units established by the current coordinate system (user units). In other words, wherever you would otherwise have omitted the unit from a length assigned to a property, use the px unit instead. For example, instead of writing:

<text stroke-width="2" style="font-size:20;" ...>

write:

<text stroke-width="2px" style="font-size:20px;" ...>

Note that units are only required for properties. Plain attributes such as the width or height attributes on the <rect> tag do not require a unit since they do not map to a CSS property. They can simply be assigned a number and it implicitly has the units of the current coordinate system.

According to the SVG 1.1 Property Index, there are only eight properties applicable to SVG 1.1 that accept a length value: stroke-width, stroke-dashoffset, font, font-size, baseline-shift, kerning, letter-spacing and word-spacing. It is these properties that you should be careful to always specify a length for.

Use namespace aware DOM methods

The DOM Level 1 recommendation was created before the original Namespaces in XML recommendation was released, therefore DOM1 isn't namespace aware. This causes problems for namespaced XML such as SVG. To resove these problems, DOM Level 2 Core added namespace aware equivalents of all the applicable DOM Level 1 methods. When scripting SVG it is important to use the namespace aware methods. The table below lists the DOM1 methods that shouldn't be used in SVG along with their equivalent DOM2 counterparts that should be used instead.

DOM1 (don't use) DOM2 (use these instead!)
createAttribute createAttributeNS
createElement createElementNS
getAttributeNode getAttributeNodeNS
getAttribute getAttributeNS
getElementsByTagName getElementsByTagNameNS (also added to Element)
getNamedItem getNamedItemNS
hasAttribute hasAttributeNS
removeAttribute removeAttributeNS
removeNamedItem removeNamedItemNS
setAttribute setAttributeNS
setAttributeNode setAttributeNodeNS
setNamedItem setNamedItemNS

The first argument for all the DOM2 namespace aware methods must be the "namespace name" of the element or attribute in question. For SVG elements this is 'http://www.w3.org/2000/svg'. However, note carefully: the Namespaces in XML 1.1 recommendation states that the namespace name for attributes without a prefix does not have a value. In other words you must use null as the namespace name for SVG attributes. As a result, to create an SVG 'rect' element using createElementNS you must write:

createElementNS('http://www.w3.org/2000/svg', 'rect');

However, to retrieve the value of the 'x' attribute on an SVG 'rect' element you must write:

getAttributeNS(null, 'x');

Note that this is not the case for attributes from other (non-SVG) namespaces such as the xlink:href attribute which use a namespace prefix. Since it has a namespace prefix in the markup ("xlink") it's namespace name is the value that was assigned to that prefix, 'http://www.w3.org/1999/xlink'. Hence to get the value of the xlink:href attribute of an 'a' element in SVG you would write:

getAttributeNS('http://www.w3.org/1999/xlink', 'href');

In summary the rule is simple. For elements with or without a namespace prefix, and for attributes with a namespace prefix, the namespace name is the namespace URI of the element/attribute in question. For attributes without a namespace prefix the namespace name is null.

Don't use Adobe's getter and setter extensions

Long, long ago when Adobe first released their SVG viewer plug-in, Netscape 4 still had enough users that it was important to be compatible with it. To do this it seems it was necessary to extend the ECMAScript interfaces and provide corresponding getters and setters for all the properties defined by the specification. As a result in ASV it is possible to write code like this:

evt.getTarget().getOwnerDocument().getDocumentElement();

when the DOM and SVG specifications actually define properties, not methods, so the correct way to write this code is:

evt.target.ownerDocument.documentElement;

The problem is that no one else supports ASV's getter and setter extensions. Scripts that uses them will not work in other SVG implementations. Happily Netscape 4 is now irrelevant for most of us, and since ASV supports the properties too, new SVG scripts can conform to the standards and work in all SVG implementations by using the properties. (In fact old code could, and should, be updated too.)

It is difficult to give a list of what is and isn't an ASV extension since there are so many properties. If you aren't familiar enough with the specifications to know which getters and setters are defined by the W3C and which are ASV extensions, be sure to test your scripts using another SVG implementation such as Mozilla Firefox or Batik. If you get errors relating to getters or setters try using properties instead and see if that fixes things. You can also search for getter and setter names in the SVG, DOM2 Core, DOM2 Events and DOM2 Style IDL. If you can't find them in any of those documents they probably aren't part of any W3C standard.


Jonathan Watt