Chartd: responsive, retina-compatible charts with just an img tag

responsive, retina-compatible charts with just an img tag

At StatHat, we
make a lot of charts…

Our web app creates dynamic, autoupdating charts using JavaScript, but we also send charts via email and to external services like Campfire and Slack. Plus, we let users embed charts on their own web pages. For these situations, JavaScript charts either won’t work, are overkill, or could get messy.

So we made chartd. It allows you to create a chart with just an img tag. These charts:

  • are responsive (resize this page to see the charts respond)
  • are retina-friendly
  • can contain up to 5 datasets
  • can be line or step charts
  • have customizable colors and strokes

No JavaScript is required. You can generate SVG or PNG charts. We prefer SVG, but some services (like gmail) won’t render SVGs in emails.

Here’s a basic chart. All charts must have these parameters: width (w), height (h), and a dataset (d0).

When you give chartd the ymin and ymax values, it will draw the y axes.

Just show the left axis with ol=1 (or just the right with or=1).

You can add a title with the t parameter.

You can put up to 5 datasets (d0..d4) on each chart.

Change any chart to a step chart by adding step=1.

Highlight the last point with hl=1. This is the style StatHat uses for automatic anomaly detection emails.

Provide xmin and xmax as UNIX timestamps and chartd will render the times on the X axis.

UTC is the default time zone. Change this with the tz parameter.

You can change the stroke colors and fills.

You can make the lines dashed or dotted.

If you need a PNG chart instead of SVG, use a.png instead of a.svg.

Responsive SVG

The SVG chart images are vectors and can be scaled down for smaller screens. If you’re on a desktop browser, go ahead and resize this window to see the charts scale.

To make this happen, wrap the image in an svg-container class and give the image tag an svg-content class.

Here’s the CSS for svg-container and svg-content:

.svg-container {
        display: inline-block;
        position: relative;
        vertical-align: middle;
        overflow: hidden;
        width: 100%;
        padding-bottom: 32%;

.svg-content {
        display: inline-block;
        position: absolute;
        top: 0;
        left: 0;

The only tricky thing is that you need the padding-bottom percentage to be at least as great as the ratio of the chart height to its width. The charts on this page are 580px wide by 180px high. So the ratio of height to width is just over 31%, so we rounded up to 32%. You can make it larger to add more padding below the charts.

Responsive PNG

While they don’t scale as nicely as SVGs, you can make the PNG charts responsive as well. Add the img-responsive class to the PNG img tag and make sure the width you provide as a parameter matches the width of the container.

Here’s the CSS for img-responsive (borrowed from Bootstrap 3):

.img-responsive {
  display: block;
  width: 100% 9;
  max-width: 100%;
  height: auto;

Don’t care about responsive?

Then just provide the width and height to the img tag for SVG or PNG.
It won’t resize when displayed on a smaller screen (but will still look great on retina displays).

Speaking of retina…

All chartd charts look great on retina displays. The SVG charts are vectors and render perfectly. chartd generates all the PNGs @2x the resolution so they scale appropriately.

All parameters, explained.

There are only two URLs: /a.svg and /a.png. Use /a.svg for SVG charts and /a.png for PNG charts.

Here are all the possible chartd parameters:

Data encoding

The data is encoded into a base-62 string. Each character in the string is a data point. Each character represents a value of 0 to 61. The characters are A..Za..z0..9. ‘A’ is 0, ‘9’ is 61. To encode, you map the Y values in your data onto the base-62 characters. Here’s what it looks like in Go:

const b62 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"

func encode(data []float64, min, max float64) string {
        r := math.Dim(max, min)
        bs := make([]byte, len(data))
        if r == 0 {
                for i := 0; i = 0 && index 


Stroke string

You can customize the color and the stroke of each dataset with the s0 - s4 parameters and the fill color with the f0 - f4 parameters. Each stroke string is 6-9 characters long. The first 6 characters are your typical CSS hexadecimal RGB values. The next two characters are an optional hexadecimal alpha value. The final character is on optional stroke parameter that determines if the line is solid, dashed, or dotted. The stroke parameter is ignored for fill parameters.

Here's how it looks:

The RR, GG, BB, and AA fields can go from 00 to FF.

The S field is either – for dashed or . for dotted (anything else, including nothing, will be a solid line).

Some examples:

4991AE blue solid line, no alpha

EFF3F680 red with 50% alpha.

4991AE- blue dashed line, no alpha

FF8300. orange dotted line, no alpha

FF830080. orange dotted line, 50% alpha

SSL, etc.

All chartd charts are also available over SSL. Just use

Original URL:

Original article

Comments are closed.

Proudly powered by WordPress | Theme: Baskerville 2 by Anders Noren.

Up ↑

%d bloggers like this: