Monday, August 10, 2009

SVG with webpages

At work we are developing a web-based framework that uses an API that support PHP, .NET and Java for developing application within it. As a general rule almost all of application within the framework are written in PHP and uses Zend for an MVC model.

While working on developing my first application I decided to extend our images API to supports SVGs. SVG is a type of image that is built on vector graphics. Vector graphics use mathematical equations to drop simple shapes that on a macro-scale define a larger image. This is very much how 3D-graphics works. Polygons are mixed together to build players, houses, vehicles, and everything else within the 3D world. SVGs usually build 2D images. The advantage to them is that you can scale them to any size you want without losing resolution.

Traditionally if you need an image at different sizes you will make a different image for each size that you need from the source. The primary problem with this is that if you try to scale an image larger than the source you get pixelation. You also might not always have access to the source, and so you are stuck with the largest version you can find.

Take for example this 32X32 image.

You could easily scale this image down to a 16X16 image, but if you wanted to make it larger it would look really ugly.

This is what happens if I try to scale the image up to 150X150:

If you always have access to the source image this shouldn't be a problem, but I see regularly enough images that have been scaled up on web page and they look horrible.

With an SVG you only need the one file and you can then dynamically scale it as you please to as small or large as you want.

Another great advantage of SVGs is that the file is plain text file that holds the formulas that draw the image, so they tend to be relatively small.

The image I am using in this example is 18.2 KB. If I convert it to a 200X200 image it is 18.3KB. If I where to convert it to a larger image then the image would take up more space as a PNG than it does as an SVG. For small files, which are small enough to download almost instantaneously, this doesn't provide any benefit, but it allows developers to provide high-quality large images and use only a very small amount of bandwidth.

IE is the only major browser that does not provide support for SVGs. Firefox, Safari, Opera, Chrome and most other even lesser-known browsers all provide support for SVGs. My plan was to have a folder named SVG in our icon directory, and then have fall back PNGs files for IE.

All of my research on the web indicated that the following code would allow me to provide SVGs with PNG fallback for IE:
<object data="foo.svg" type="image/svg+xml" height="32px" width="32px">
<img src="foo.png" style="height: 32px; width: 32px">
</object>

No matter what I tried this didn't work. Instead of resizing the SVG to 32X32, it clipped the image instead.

Clipped image:

I Googled and searched around and came up dry until I happened upon a response on someone's blog a little over a year ago that said that Firefox was planning on supporting SVGs inside the img tag. I tried <img src="foo.svg" style="height: 32px; width: 32px"> and it worked, dynamically resizing and all, in all non-IE browsers except Firefox.

I then found another trick. SVGs are plain text files that use a standard known as XML. These XML files could be modified to be PHP files that output the XML that defines the SVG iamge, and that too could be placed inside the object tag. This unfortunately gave me the same clipping results.

My final conclusion is that the web is just not ready yet for SVGs until Firefox begins providing some sort of sane support for SVG that allows developers to define the width and height to render the SVG image. We really need Microsoft and Mozilla to get on board so that we can stop using JPGs, GIFs, and PNGs wherever possible.

3 comments:

  1. It's confusing but you need to add the viewBox attribute onto the root SVG tag inside your file, something like:

    <svg viewBox="0 0 32 32">

    This says to always scale the image along those dimensions independent of how it is placed. I believe that should solve the issue for you.

    Technically the clipping is 'correct' I believe since you don't specify the viewBox. The viewBox controls how an image 'maps' onto the space available to it. I think you can also add the preserveAspectRatio attribute to control how things get stretched (Google to see how to use it).

    BTW, I'm working with others on a library that brings SVG to IE; it's still in alpha but it we are looking for early testers if you want to see if what you are doing will work on there: http://code.google.com/p/svgweb

    ReplyDelete
  2. Thanks Brad. I will be very interested in taking a look at the library for cross-browser SVG. Hopefully tomorrow I'll have time to play with viewBox and get my SVGs scaling properly.

    ReplyDelete
  3. I got it working by adding the viewBox attribute to the SVG and changing the width and height attributes to 100% in the SVG. Soon I will post in more detail how I got it to work.

    ReplyDelete