Highcharts, SVG, VML, and Auto-Sizing for Legends

By Zach Dennis on 11 09 2011

Recently we hit a limitation with Highcharts: it has no way of dynamically resizing itself or its parent container to ensure that you see the legend and the full chart at the same time. Here's the issue at hand: http://jsfiddle.net/KYfHM/2/

This isn’t a problem if you know in advance how many data series you’ll be showing, because you can specify the proper width and height when you create the chart. We’re populating the charts on a lot of dynamic factors, so we don’t know how many series will always be displayed upfront and we don’t know how long the labels will be. For us, this meant that our legend could easily grow beyond the bounds the chart.

No one wants to see a cut-off legend.

Determined to resolve the problem, we created a chart-resizing.js file which would unobtrusively define the ability for charts to automatically resize. Modern browsers support SVG, but IE7 and IE8 do not, and even IE9 has its own quirks.

We decided to start with an SVGChartResizing object which would be used to define the strategy for how the charts should be resized. This worked great in Chrome, Safari, and Firefox.

IE9

Initially our SVGChartResizing object relied on the following code to determine y position of our legend:

For SVG supporting browsers we were set. Now onto non-SVG supporting browsers.

IE8

IE7 and IE8 don’t support SVG, they support VML, which they are both equally finicky about.

Breaking jQuery

When VML is present on the page IE breaks jQuery when using pure pseudo-selectors:

The feedback you get from IE not very helpful. Fortunately, a similar issue was discovered way back in April 2010 when integrating Cufon, jQuery, and IE. There were only a few places where a pure pseudo selector was used so we updated them to be slightly more specific:

Adding the input makes it more specific so jQuery won’t try to select certain VML elements.

Getting computed heights on VML objects

A Highcharts legend is a container which groups all of the individual legend items themselves. With the SVG-capable browsers you could ask the legend for its height and it would return its computed height. This was reliable enough to get the actual height needed to display the legend.

It seems that IEs DOM interface to VML objects doesn’t quite work the same way. It seems practically impossible to determine the computed height of a VML container. So rather than asking for the legend’sheight we had to find alternative paths.

In IE8 we were able to use scrollHeight. IE7's scrollHeight didn't work the same way so we had to resort finding the largest child node and then rely on that to determine the legend's height:

The End

For all of the complexities that Highcharts supports it was surprising that it didn't surprise gracefully resizing the chart and re-positioning the legend. From many Google searches it appears we aren't alone in this feature request, although most users seem to have found their own type of work around. Until it gets resolved there will be an open issue for this.

At the end end of the day the code is cleaner than we thought would have thought given the oddities we initially hit and the time it took to sort through the problems related to IE7 and IE8.

I remember walking away from work thinking I can’t wait until I get coffee-script on this project.

You can find the full code of what it took in this gist.