In Part 1 and Part 2 of this series on image optimization, we discussed ways to optimize raster graphics to get image sizes as small as possible. In this part, we’ll discuss the ways HTML can render its own vector graphics and composite images client-side, making websites load and run faster. There are two ways of going about this: SVG and HTML5’s Canvas element. For most common uses SVG is the faster of the two, but just as with raster image formats these two approaches have their strengths and weaknesses when it comes to performance.
Why use vector images?
“Raster” images are images that store data as a grid of pixels. JPEG, PNG, and GIF are all raster formats. By contrast, “vector” images are stored as a mathematical formula that will generate the desired image. Raster image files tend to be large and bulky where vector images are often quite lean since they are only storing a few lines of code rather than a huge array of color values. Depending on the complexity of the image, this can make images much smaller in file size. The drawback here is that the image is generated on the client-side, so if the image is complex or vector graphics are overused it can create a drain on the client’s CPU while it generates.
SVG
SVG (Scalable Vector Graphics) is a vector image format that has been around since 1999, and it has been a W3C Recommendation since 2001. So unlike Canvas, it is compatible with many older browsers. (The exception being Internet Explorer, but old versions of IE can’t really be expected to support anything cool.) Based off of XML, SVG objects are built right into the DOM, so they can be manipulated with CSS and JavaScript on a per-shape basis.
SVG is best used for most static images, as SVG markup tends to be much smaller, much simpler, and run much faster than Canvas scripts that generate the same image. It produces much higher performance at larger screen sizes than Canvas. SVG images can also be rapidly scaled on the client-side, so detailed graphics are most quickly rendered with SVG.
Canvas
HTML5 Canvas creates an easily manipulated bitmap inside of a browser. Canvas can draw vector graphics, but they are rendered using a raster format. (Think drawing a square in Photoshop using the Rectangle tool versus using the paintbrush.) Unlike SVG, Canvas can only be manipulated with JavaScript, but it only adds one line to the DOM. Being an HTML5 object, Canvas is only supported by the latest browsers. Where SVG is shape-based, Canvas is more pixel-based in its graphics, essentially drawing a bitmap with JavaScript and then pushing it to the screen. Thus it’s not technically “vector” graphics, but it’s still an image that is stored as a script.
Canvas is fastest at small dimensions since it has fewer pixels to render, and can handle large numbers of individual objects and shapes faster and more efficiently than SVG. This is because SVG must retain an instance of each shape it draws where Canvas just manipulates pixels and forgets about it. Canvas can also cache images it draws and prerender images to use instances with no performance cost. Dynamically generated images like histograms and graphs are best done with Canvas.
Canvas and raster images
SVG deals exclusively with vector images, but Canvas can load and manipulate raster graphics as well. This creates the potential to allow for client-side image compositing. As a simple example, rotating a thin image into place with Canvas rather than loading the pre-rotated image can save a bit of file space, potentially making sites load a bit faster.
All files were in PNG format. Red boxes represent transparent pixels within the file.
You can also use client-side compositing to layer multiple images onto one another and/or perform operations on them that would increase file size if done beforehand, such as adding noise to an image. (A great example can be found here: http://coding.smashingmagazine.com/2011/08/30/optimize-images-with-html5-canvas/)
Pixel manipulation techniques like these usually require some moderate to advanced JavaScript knowledge though, so only attempt client-side compositing if you think it’s worth your time. Again, the downside of this technique is that it pushes more workload onto the client’s CPU, so very processor-intensive actions could slow down their computer. Unless the image is cached afterwards, these scripts must also run each time the page is loaded, so keep that in mind when using Canvas in this way.
Summary
SVG and Canvas are designed to accomplish very different goals, so both SVG and Canvas are best used with different things. Both can be used for interactivity at different levels, but for the purposes of this article, we’re only discussing how they can both be used to display images and graphics. To that end, here are my recommendations to get the most performance from both:
Use SVG with
- Static vector graphics with a small number of individual shapes
- Graphics that need to dynamically scale
- Larger screen sizes
Use Canvas with
- Static vector graphics with a large number of individual shapes
- Dynamically generated graphics and client side compositing
- Smaller screen sizes
There are some excellent performance graphs that support these best practices here: http://smus.com/canvas-vs-svg-performance/
Finally, if you’d like to know more, MSDN has a more in-depth look at SVG vs Canvas: http://msdn.microsoft.com/en-us/library/ie/gg193983(v=vs.85).aspx