Wednesday, October 20, 2010

SVG as an image

As of about a month ago, SVG files can now be used as images in Firefox 4.0 nightly builds! This will be included in the next Firefox 4.0 beta iteration (beta 7), when that's released.

This feature is exciting for many reasons:
  • Better-scaling web graphics -- unlike raster images (e.g. JPEG/GIF/PNG), SVG images can be scaled up or down without pixellation. This makes SVG ideal for web developers who want their content to look crisp on giant projector-screens as well as tiny phone screens.
  • SMIL animation in images -- SVG allows for very complex & expressive animations (see Brian Birtles' recent post for a number of great examples).
  • Reduced web-developer frustration -- from an author's perspective, SVG is an image format, and it should Just Work in contexts that expect an image.
  • Broader use of SVG!

For your viewing pleasure, here are some demos of SVG-as-an-image in a variety of situations:
  • In the <img> tag:
  • img tag sourcing an SVG image
  • As a CSS background:
  • This is a div with a tiled SVG image as its background.
  • In the HTML5 canvas element, with a rotation applied via the 2D canvas API:
  • <---- And here, as a CSS list-style-image! (That's the SVG version of the W3C's SVG logo.)

As one last example, I hacked together a Firefox Persona using SMIL-animated SVG images as backgrounds for Firefox's toolbar & addon bar. I wasn't able to publish it to the GetPersonas site, because the uploader page there doesn't accept SVG images yet -- so instead, I've included a small screencast:

Click here to view full-size video

The SVG files used for backgrounds in this Persona are available here. The header SVG file makes use of a locally-saved copy of Marek Raida's excellent hourglass demo.

There are some bugs with this feature that I'm still working out -- for example, you may get pixellation at certain unlucky zoom-levels -- but that will be fixed for the final release. If you run into other issues, please file bugs! :)


Anonymous said...

Is it just me or does the SVG as CSS background not scale/zoom crisply?

(latest nightly)

Daniel said...

Yeah, I noticed that too. I'm pretty sure that's a form of the bug I linked in the last paragraph.

For <img> elements, that bug only gets triggered at unlucky zoomlevels when a rounding error in the image-drawing code makes us think we (barely) need to tile our image. But it may really affect all image-drawing that hits the tiling codepath (tiled CSS backgrounds in particular, and accidentally-tiled-<img>-elements on occasion).

Chris Hubick said...

Thanks SO much! I have basically been waiting for this since NCSA Mosaic added support for the img element. I have always loved the device agnostic semantic markup of HTML, the separation of style/presentation through CSS, and yet thought the implementation marred by being restricted to silly un-scalable bitmap images. When I first got excited about SVG a decade ago, I didn't think it would take this long, but the day I can finally author a single CSS theme (with graphics) for my smartphone and desktop is finally imaginable.

I'm so excited, I jumped the gun and updated one of my little sites already:

Daniel said...

@Chris: Thanks for the encouragement & enthusiasm! :) The header/title SVG file on your site is quite impressive - nice work on that!

Unknown said...

This is a huge improvement. Now Firefox is a SVG first class citizen. Thanks to all of the Mozilla Team that work on SVG. You make an amazing job.

Chris Leary said...

Can you describe what the major obstacles were for we image-technology ignoramuses?

Daniel said...

@Chris: Good question! So the basic challenge here was to shoehorn something that's really a document into a wrapper that looks like an image to callers of Gecko's image APIs.

From the browser's perspective, SVG is a document format (like HTML), with a full DOM, a frame tree, etc. That makes it qualitatively different from raster images (which are just binary blobs representing grids of pixel-values). So, the goal here was to wrap the SVG document in a layer of glue that makes it present itself as an image, so it can respond to API calls like a "real" image would. (This also involved refactoring chunks of our image APIs to make them more amenable to this wrapping, since there are a lot of methods that make sense for raster images but make no sense for SVG images.)

One specific pain-point had to do with handling image-sizes. Clients of our image APIs have traditionally assumed that all images will have pixel-valued heights & widths. But that assumption doesn't always hold with SVG images -- they can have percent-valued heights and/or widths, which in practice tends to means "I'm whatever size you want me to be!", and that's tricky if the client doesn't specify a desired size. :) Anyway -- it took a bit of work to rework the assumptions in these cases and figuring out the Right Thing To Do in each situation.

Tarun Elankath said...

Thank you for this - it was a very succinct summary. Goodbye to Raster images and welcome to type-able Vector!

Daniel F. Boada said...

Hi all,
Did any one here succeed on displaying an image that is a reference to another svg image inside an svg file? I just can't.
Here ( ) it states that a Gecko 2 browser is capable to do so. I am using firefox 4.08b.
Even a very small example like this fails...

I would appreciate much if any one that got the svg image being displayed could give me any tip about it.

Thanks in advance to every one.

Daniel F. Boada said...

Hi again,
I take all the previous post back.
I have just managed to get this working using Daniel's patch at:
You can find it in the currently nightly build of Firefox: (FF4b9pre).
Thank you very much Daniel for your contribution there.

Daniel said...

Hi Daniel,

Thanks for the interest! Sorry for not being clearer about that -- SVG's own element has a few tricky quirks about how it works, so I did that separately -- and that patch landed in December. It'll make it into the upcoming beta (beta9).

Daniel said...

(sorry, I meant to say "SVG's own <image> element" in the previous comment... blogger stripped out the <image> since I'd written it with explicit braces instead of with '& lt;' / '& gt;')