Honest-To-Gosh Scalable Vector Graphics

10 November 2006

I believe I’ve said it a couple times: I hate Flash. Hate the UI. Hate corruptable binary format. Hate that you can’t make batch changes. I could go on; I won’t. Very slowly, another vector based format has been creeping into tools and browsers—Scalable Vector Graphics (SVG)—and it’s very promising. But there are still some foibles that are driving me mad, and I’m putting out the call for help to see if I can implement SVG now.

The problem with using images (and video) in web content is that they are inherently inflexible; a photo that should fill a 800×600 screen will look tiny on a massive Apple Cinema Display. While other HTML elements can be set to scale along with the content of the site, images will either have to scale up and look blurry or scale down and gobble up bandwidth. With photos, there may never be a good solution to this problem, but graphs, charts and illustrations can (in theory) be done in vectors or order to look crisp at any size—massive to mobile.

Here’s some examples. I’ll use the <object> element (sorry IE 6) for consistency, although the application would be the same in <img>.

PNG SWF SVG
A PNG Image An SWF Image You cannot view this image without an SVG-enabled browser. Try here.

Now, watch what happens when I scale each one up to 3 times the size:

A PNG Image
An SWF Image
An SVG Image

The PNG becomes fuzzy, but the SWF scales nicely. But the SVG—what the heck‽ The latest versions of Gecko and Webkit (but not Opera) render the SVG image at 100×100 within a 300×300 box.

The only work-around I’ve been able to find is to remove the width and height declaration from the root <svg> element, as so:

An SVG Image

Right then—we’re all set right? Wrong. Removing the width and height from the <svg> element removes its intrinsic height—i.e. the browser has no idea how big the image is supposed to be. This makes it impossible to insert the image into a liquid layout where it fills the given horizontal space:

A PNG Image An SVG Image

This leads to all kinds of problems, and essentially makes it impossible to allow SVG to do the one thing it was meant to do: scale. The worst part? I want to deploy these today. And I want them to scale. And I don’t want to use Flash. I’ve filed a test case and votes for this bug in both bugzilla and webkit bugs, but until I receive a better solution, I’m open to suggestions. Help?

5 Responses to “Honest-To-Gosh Scalable Vector Graphics”

  1. stelt insisted,

    Did you set viewBox?

  2. ryan said,

    I did. ViewBox only sets up the coordinate system, is does not say anything about the size of the image.

  3. Jeff Schiller posited,

    Actually, the point of a “scalable” image is that it HAS NO INTRINSIC SIZE. You can display it at any resolution you want. So the solution that will work today is:

    • the SVG should have width=”100%” and height=”100%” (note the percentages here, it means “completely fill up the element that contains the SVG”
    • the HTML:object element should specify the height/width it wants: <object type=”image/svg+xml” width=”300px” height=”300px”….

    Hope this helps you out – deployment is possible today :)

  4. Jeff Schiller insisted,

    Ah, I read the Moz bug now and re-read this statement: “This makes it impossible to insert the image into a liquid layout where it fills the given horizontal space”. I agree with this, and I think it’s actually a browser layout problem, not necessarily a SVG problem.

    If you change the size of the width/height in your SVG to 100%, this should work – the browser should size the SVG to whatever the containing element’s size is. Whether it does or not, is probably an implementation bug. (But a bug, nonetheless).

  5. Ryan said, in that familiar tone,

    @Jeff: Not quite. I checked it in OmniWeb (WebKit), Firefox 2, and Opera. It breaks Opera and doesn’t fix the problem in the other two. Check it out with the scaling SVG in scaling HTML test. Without explicitly setting the width and height inside the SVG, there is no intrinsic height for <html:object> to use in order to determine the aspect ratio.