Gerbil guides

You can check the documentation of the gerbil/axis and gerbil/chart modules to see everything you can do with gerbil.

Here’s a list of common questions, problems, and code snippets you can check and use in your project. If you’re looking for something that isn’t here, please open an issue and let me know!

Render a chart to svg? How do I...

A gerbil chart.Chart can be turned into a Lustre Element with chart.to_svg. Then you’re free to use it however you want: embed it in an interactive Lustre application, or render it to HTML to produce static pages.

In this example we’re rendering a chart as an plain HTML string:

+ import lustre/element

  chart.new(x: axis.int(), y: axis.int())
  |> chart.add(chart.points([], [
    chart.point(1, 2, []),
    chart.point(2, 2, []),
  ]))
+ |> chart.to_svg
+ |> element.to_string

Draw a scatterplot? How do I..., Plots

You can draw a scatterplot by adding a chart.points plot to an existing chart:

pub fn scatterplot() {
  chart.new(x: axis.float(), y: axis.float())
  |> chart.add(chart.points([], [
    chart.point(1.1, 10.0, []),
    chart.point(2.0, 11.1, []),
    chart.point(4.3, 15.4, []),
    chart.point(5.0, 12.2, []),
  ]))
}

Draw a line chart? How do I..., Plots

You can draw a line chart by adding a chart.line plot to an existing chart:

pub fn line_chart() {
  chart.new(x: axis.float(), y: axis.float())
  |> chart.add(chart.line([], [
    chart.point(1.1, 10.0, []),
    chart.point(2.0, 11.1, []),
    chart.point(4.3, 15.4, []),
    chart.point(5.0, 12.2, []),
  ]))
}

Show points in a line chart? How do I..., Plots

You can add any number of plots to a chart and really get creative with it. If you want to show a line chart, and have the points it connects stand out, you can use both a chart.line plot and a chart.points plot into a single chart:

pub fn line_and_points() {
  let points = [
    chart.point(1.1, 10.0, []),
    chart.point(2.0, 11.1, []),
    chart.point(4.3, 15.4, []),
    chart.point(5.0, 12.2, []),
  ]

  chart.new(x: axis.float(), y: axis.float())
  |> chart.add(chart.line([], points))
  |> chart.add(chart.points([], points))
}

Remember that plots added last will appear on top of plots added first, so to have the points appear over the line we need to add that plot last.

Change the number of ticks? How do I..., Ticks

By default all axes have roughly 5 ticks, you can change that using axis.infer_ticks:

axis.int()
|> axis.infer_ticks(preferred_count: 15)

It will automatically pick a “round” step to produce roughly the given number of ticks.

If you want more control over the exact step to use to generate ticks you can check axis.ticks.

Set an exact step for ticks? How do I..., Ticks

You can use axis.ticks: it takes a function which defines what the next tick should be, given the previous one. For example if I wanted a tick every 5 units in an int axis I’d write:

axis.int()
|> axis.ticks(fn(previous) { previous + 5 })

When using ticks, you will most likely want to also set an exact minimum value with axis.min to make sure ticks start where you would expect:

  axis.int()
+ |> axis.min(0)
  |> axis.ticks(fn(previous) { previous + 5 })

In this example we have defined an axis that will have a tick for 0, 5, 10, … until the maximum is reached.

Make sure ticks start at a certain value? How do I..., Ticks

If an axis doesn’t have a fixed minimum or maximum values, gerbil will pick values that result in nice “round” inferred ticks. If you want to be sure ticks start or end at some specific value you can use axis.min and axis.max:

axis.int()
|> axis.min(0)
|> axis.max(100)

In this example ticks will never go below 0, or above 100.

Change the default text of labels? How do I..., Labels

Why are there no labels on my axis? Troubleshooting

You can choose how tick values are turned into labels with the axis.show_labels function. It accepts a function that, given a tick’s value, outputs the label to be used for it:

axis.int()
|> axis.show_labels(fn(value) {
  // Show numbers in base 2 in the labels.
  int.to_base2(value)
})

Most importantly you’ll need to use axis.show_labels to show the labels of categorical and timestamp axes: gerbil can’t decide for you how those should be displayed and won’t display anything unless explicitly told to.

axis.timestamp()
|> axis.show_labels(fn(value) {
  // Show the times in the rfc3339 format with
  // Italy's timezone offset.
  timestamp.to_rfc3339(value, duration.hours(2))
})

Change the colour of a plot? How do I..., Styling

The colour of each plot is defined by a --plot-colour CSS variable, if you want to change the colour of all plots in a chart you can do it like so:

.gerbil {
  --plot-colour: #faaff3;
}

You can also change the colour of individual plots by writing more precise CSS selectors:

/* Only change the colour of line plots */
.gerbil .line {
  --plot-colour: #faaff3;
}

You can check the documentation of the gerbil/chart module to see what CSS classes are added to each plot.

Style a specific element? How do I..., Styling

Plots are styled using CSS. If you want to style one specific plot (as opposed to styling all line plots as a whole, as shown in the previous section) you can do so by adding an id to the plot:

import lustre/attribute

chart.new(x:, y:)
|> chart.add(plot.line([attribute.id("special-plot")], points))
|> chart.add(plot.line([], other_points))

Now you can select and style the plot more precisely:

#special-plot {
  --plot-colour: #faaff3;
}

Hide some of the labels? How do I..., Styling

Labels are given the .label CSS class, labels of the x axis also have a .x class, labels of the y axis also have a .y class.

Say the labels of the x axis are getting crowded and you only want to show one every two labels. You can do so with some CSS:

.label.x:nth-of-type(2n) {
  display: none;
}

Hide the horizontal/vertical ticks? How do I..., Styling

Ticks are given a .tick CSS class, the vertical ticks of the x axis also have a .x class, the horizontal ticks of the y axis also have a .y class.

If you want to hide all the vertical ticks you can do so with some CSS:

.tick.x {
  display: none;
}

If you want to hide all the horizonatl ticks you can do so with some CSS:

.tick.y {
  display: none;
}

Change the space left for labels? How do I..., Sizing

Why is the gap for labels so large? Troubleshooting

Why are labels overflowing? Troubleshooting

Gerbil tries to estimate a label gutter that is large enough to fit labels. This is not a perfect process, sometimes the gutter might be too big or too small.

In this case you will want to change the size of the gutter left for an axis’ labels using axis.labels_gutter:

axis.int()
// pick whatever size can comfortably fit your labels
|> axis.labels_gutter(80)

The gutter is space that is taken out of the total width of the chart. If a chart is 500 svg units wide, and the gutter of the y axis is 100 units wide, the plots themselves will have a region 400 units wide left.

Change the size of a chart? How do I..., Sizing

By default charts are 500 svg units wide and 250 svg units tall, if you want them to have a different size you can use chart.size:

chart.new(x: axis.categorical(), y: axis.int())
|> chart.size(width: 250, height: 250)


This is all written by a human, me! If you have some spare change and appreciate what I do, please consider sponsoring me.

✨ Search Document