SVG Illustrations 201

HTML and CSS have come a long way recently, but even today they often lack a certain something. We, as content authors, sometimes want a little more flair on the web.

For this, my weapon of choice is the SVG, primarily for its scalability and open format. We have open-source vector authoring software, and the SVG specification can be commented on via the SVG mailing list. In the future, because the bodies that maintain the HTML, CSS, and SVG standards work closely together, we'll see more and more integration between these technologies. Their synergy will make SVG the de-facto standard for illustrations on the web. Today, however, there are a lot of issues.

First, there are a plethora of ways to use SVGs in your documents, but we'll focus on just a few [modern and general] ways to use them:

  • object element
  • img element
  • css background-image property
  • inline svg

img would be the obvious choice here, for which we simply set the src attribute to the URL of our image, but the object  tag is also appropriate for this context. The W3C describes the element this way:

The object element can represent an external resource, which, depending on the type of the resource, will either be treated as an image, as a nested browsing context, or as an external resource to be processed by a plugin.
Embedded Content – HTML 5.1 Nightly

The real benefit of this element is that it provides an opening and closing tag between which you can provide fallbacks for browsers that dont support the data you're embedding. But this is where the fun in the object tag ends for me. Much of the benefit of SVG is that it has a DOM interface, just like HTML, but when using img and object tags, we don't have access to the SVG nodes using external CSS stylesheets (a convenient practice for keeping styles organized). Using object , we can still access an SVG through the DOM by calling window.frames[].document; . It's rather messy, though, as we're really asking for a document in an array of frames.

Inline is the answer

For these reasons, I opt for inline SVGs, as their child elements can be targetted by both javascript and external CSS. There's still an argument to be made over whether inline SVG is really semantic. It seems a bit odd to dedicate a large portion of our DOM tree to an image, when the rest of the tree is rich in text and data. My basic answer is that it depends on whether your SVGs are content or style—that is, whether or not they add anything to the message. Also, I'll go out on a limb and say that if your SVG has any sort of node-level interactivity (as opposed to, say, applying a transform to the entire SVG), it's semantically ok to use inline so long as you define your image using  alt  or the global title  attributes.

To demonstrate the flexibility, take a path element and apply the following CSS to a path element with ID #grass :

#grass {
fill: lawnGreen;
}

This might not seem like much, but what I've found this particularly useful for is theming my illustrations and giving them different colour schemes. For instance, on my Totoro web page I've used a small javascript function that fetches the user's time. If it's [roughly] daytime, a class of day will be appended to the html element. From here, it's very easy to style the SVG nodes using a CSS child selector like .day #grass { ... } .

There are a lot of possibilities here, especially if we were to apply class attributes to various elements inside the SVG, but there's a limitation with Illustrator: if we add classes to our SVG elements and then re-edit the file in illustrator, our SVG will be stripped of those classes.

We can also use other fancy css properties; everything from transforms to css filters (SVG has its own filter syntax defined in its markup, but ideally we'd be able to set these using CSS for concision's sake and to give certain conditional properties to the images). This flexibility is particularly useful for things like drop shadows on images that actually follow a transparency mask (unlike box-shadow which renders a... boxy shadow around the image's bounds).

Notes on CSS and SVG

Though this is open for debate, I find it's beneficial to leave in fill attributes even if you plan to style the SVG via CSS. The reason being that you leave a default color scheme should the css fail to load or should it be unable to load—in the case that someone should load your SVG as an external resource—while the CSS will actually override the attribute styling.

While CSS properties will take precedence over presentation attributes in SVG, not all CSS properties affect the appearance of an SVG. Here's some examples of properties with logical equivalents in SVG that do and do not affect SVGs.

CSS propertySVG AttributeCSS Applicable to SVG?
fillfillyes
strokestrokeyes
opacityopacityyes
displaydisplayyes
visibilityvisibilityyes
width / heightwidth / heightno
top / bottom / left / rightx / yno
transformtransform 1yes
border-radiusrx / ry 2no
font-sizefont-size 3yes
  • 1 slightly different syntaxes
  • 2 only applicable to rect and ellipse
  • 3 only applicable to text elements

SSI + SVG

One thing I found to help cut down on HTTP requests and keep the flexibility of inline SVGs is using server side includes to dynamically include SVG files through the server. Called Server Side Includes, it sounds like cheating, and oh - it is. Using PHP as an example, we can use the following code to include a file, fields.svg:

<?php include "img/fields.svg" ?>

Save this file out with a .php extension and by using the server to include your SVGs, you're able to keep the images separate for editing in applications like Illustrator, should you need to, and when you save the file after editing, PHP will include the updated file into the document when you refresh.

Can't get jiggy with WSYWIGS

There's a caveat here, of course: when saving to SVG with Illustrator, it's saved with an opening <?xml ?> tag and a <!DOCTYPE> . It looks a little like this messy bit:

<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="720px" height="720px" viewBox="0 0 720 720" enable-background="new 0 0 720 720" xml:space="preserve">

The issue with this is that the xml tag is not valid inside HTML documents, but the svg tag is, so we'll need to open the SVG file in a text editor and remove those xml and doctype tags. ( !doctype isn't necessary because we've most likely already declared our document as HTML at the very top).

In addition, when coming out of a visual editor like Adobe Illustrator, we have a lot of markup that may not be very well optimized. For instance, Illustrator often spits out code like  transform="matrix(1 0 0 1 6672.8564 1386.332)"  with no x and y attributes to signify the position of a text element. It's easily fixable, though. Given the following syntax for SVG transform matrices,

matrix([scaleX] [skewY] [skewX] [scaleY] [transformX] [transformY])

we can take out the transformX and transformY values and place them into their respective x and y attributes.

<text x="6672.8564" y="1386.332" font-size="1em">Bonjour TLM</text>

Edit (03/04/2013): Inline CSS with media queries

Not a day after posting, Jason Grigsby tweeted a video posted by Andreas Bovens almost four years ago, detailing how we can use inline styles and media queries in SVGs to change the appearance of our SVG based on the size of the image. There are some strong use cases here, and it made me reconsider what I've said above.

As Andreas mentions, using media queries in the SVG means that the media queries take effect based on changes (height, width, etc.) made to the image—not directly based on the viewport. This gives us a little more fine-tuned control on each image, and is particularly useful if we have multiple instances of the same SVG. Say we have a header which carries a brand logo, and a footer in which we want to have a much smaller version of the logo. They can reference the same SVG file, but because the media queries affect the styling per-instance of the image, they'll be applied differently. We can modify stroke-widths to make the image more legible, change the size of an element, or modify colors... There are really a lot of possibilities, and the most important part is that, because the styles are embedded in the SVG, they go wherever the image goes. You can include the SVG using any of the above methods and it will maintain the media queries.

I still feel that external CSS is good for organization and less localized styles, but this is definitely a case I hadn't considered.

Level 300 Courses

This article is largely just an account of my experience with SVGs, so I don't have all the answers. These folks might have more than me:

Conveniently, Chris Coyier just posted his piece on SVGs as I was working on mine. They cover some of the same issues, so if you found this useful, the CSS-Tricks article is worth a look.

Kyle Foster recently updated a video on SVG optimization and demonstrated his workflow. The new title is SVG Optimization - End-All, Be-All Edition.

- Truncation with CSS (Sassy) »