Wrapping, truncating, and auto-rotating axis labels

This tutorial will explain how you can deal with very long axis labels, by wrapping and/or truncating them.

Prerequisites

If you haven't done that already, we suggest you take a look at the "Positioning Axis Elements" article, which explains the principles about configuring Axis elements, including the concept of "axis renderer". Moving forward we will assume you are familiar with the idea, that almost every appearance setting for an axis is added via its renderer property.

Furthermore, this tutorial also uses "list templates". Make sure you take a brief look at the "List templates" article for an introduction to this powerful concept.

Base chart

Let's start off with a basic chart, that has very long labels on its Category axis:

See the Pen amCharts V4: Axis label wrapping and truncation (1) by amCharts (@amcharts) on CodePen.24419

Looks cool? Not really.

Let's see how we can fix that.

Wrapping labels

The first solution that comes into mind is: "let's make labels wrap so they are not overlapping".

To make that happen, we will need to modify axis label template object. For an axis, this template is stored in its Renderer: axis.renderer.labels.template.

An axis label is an object of type Label. Click the link on it to explore it's all options.

For now, to make our labels wrap we will need its two options: wrap and maxWidth.

The first one is obvious - it's a boolean setting indicating whether labels should wrap. The second gives a width threshold for the label, so that it knows how much width it has available.

Let's try it:

let label = categoryAxis.renderer.labels.template;
label.wrap = true;
label.maxWidth = 120;
var label = categoryAxis.renderer.labels.template;
label.wrap = true;
label.maxWidth = 120;
{
  // ...
  "xAxes": [{
    // ...
    "renderer": {
      "labels": {
        "wrap": true,
        "maxWidth": 120
      }
    }
  }]
}

See the Pen amCharts V4: Axis label wrapping and truncation (2) by amCharts (@amcharts) on CodePen.24419

NOTE The maxWidth here simply tells the label to not grow beyond certain number of pixels. The label will automatically wrap on this set threshold.

Truncating labels

Basic usage

Wrapping labels made them readable, but they also made them tall, resulting in chart itself being flattened next to nothing. Not particularly good.

Let's try to make labels auto-truncate.

We'll still need to set the maximum width of the label using maxWidth. However, instead of telling it to wrap, we'll tell it to truncate the text by setting its truncate property.

let label = categoryAxis.renderer.labels.template;
label.truncate = true;
label.maxWidth = 120;
var label = categoryAxis.renderer.labels.template;
label.truncate = true;
label.maxWidth = 120;
{
  // ...
  "xAxes": [{
    // ...
    "renderer": {
      "labels": {
        "truncate": true,
        "maxWidth": 120
      }
    }
  }]
}

See the Pen amCharts V4: Axis label wrapping and truncation (3) by amCharts (@amcharts) on CodePen.24419

Now, as we say here "the wolf is fed, yet the sheep is alive". We don't sacrifice the height of the chart itself, yet we retain part of the labels, giving users an idea of what this category is about.

Modifying ellipsis

By default, labels are truncated with a triple-dot for an ellipsis. You can use label's ellipsis property to set it to any other string.

Displaying tooltips

Now that we have truncated the labels, we are concealing part of the information from our users.

Let's set the labels up to display a tooltip when user rolls over the label with a mouse cursor or taps it on a touch screen.

Any element in amCharts 4 has a property tooltipText. If it's set, a tooltip will appear when hovering the element.

We can set it to some static text, or we can use dynamic placeholders, that can draw data from related data item and even elements own properties and data. Since we know Category axis' labels have data item with a category property, we can use the placeholder "{category}" in label template's tooltipText:

let label = categoryAxis.renderer.labels.template;
label.truncate = true;
label.maxWidth = 120;
label.tooltipText = "{category}";
var label = categoryAxis.renderer.labels.template;
label.truncate = true;
label.maxWidth = 120;
label.tooltipText = "{category}";
{
  // ...
  "xAxes": [{
    // ...
    "renderer": {
      "labels": {
        "truncate": true,
        "maxWidth": 120,
        "tooltipText": "{category}"
      }
    }
  }]
}

That's it. Now hovering over the label will display full text of the truncated label. Go ahead, try it out on a below chart:

See the Pen amCharts V4: Axis label wrapping and truncation (4) by amCharts (@amcharts) on CodePen.24419

Labels are too big even for a tooltip? Let's fix that by constraining tooltip width and making it auto-wrap:

categoryAxis.tooltip.label.maxWidth = 200;
categoryAxis.tooltip.label.wrap = true;
categoryAxis.tooltip.label.maxWidth = 200;
categoryAxis.tooltip.label.wrap = true;
{
  // ...
  "xAxes": [{
    // ...
    "tooltip": {
      "label": {
        "maxWidth": 200,
        "wrap": true
      }
    }
  }]
}

Auto-fitting labels

All of the above solutions involved hard-coded maxWidth value.

Let's take it one step further and make it fully automatic: so that maxWidth is always set to actual available space.

For that we are going to be utilizing axis' sizechanged event, which kicks in whenever axis size changes.

When that happens we will calculate actual width in pixels, take into account how many categories are there on the screen right now, and div it all up to find out a perfect maxWidth.

categoryAxis.events.on("sizechanged", function(ev) {
let axis = ev.target;
let cellWidth = axis.pixelWidth / (axis.endIndex - axis.startIndex);
axis.renderer.labels.template.maxWidth = cellWidth;
});
categoryAxis.events.on("sizechanged", function(ev) {
var axis = ev.target;
var cellWidth = axis.pixelWidth / (axis.endIndex - axis.startIndex);
axis.renderer.labels.template.maxWidth = cellWidth;
});
{
// ...
"xAxes": [{
// ...
"events": {
"sizechanged": function(ev) {
var axis = ev.target;
var cellWidth = axis.pixelWidth / (axis.endIndex - axis.startIndex);
axis.renderer.labels.template.maxWidth = cellWidth;
}
}
}]
}

Now, whatever data you throw at the chart, it will adapt and crop the labels accordingly:

See the Pen amCharts V4: Axis label wrapping and truncation (4) by amCharts team (@amcharts) on CodePen.0

(Try to open the above chart in a new window and play around with its size)

Auto-rotating labels

Building on the previous example, let's make the sizechanged event work to automatically rotate labels if they do not fit into specific cell width.

categoryAxis.events.on("sizechanged", function(ev) {
let axis = ev.target;
  var cellWidth = axis.pixelWidth / (axis.endIndex - axis.startIndex);
  if (cellWidth < axis.renderer.labels.template.maxWidth) {
    axis.renderer.labels.template.rotation = -45;
    axis.renderer.labels.template.horizontalCenter = "right";
    axis.renderer.labels.template.verticalCenter = "middle";
  }
  else {
    axis.renderer.labels.template.rotation = 0;
    axis.renderer.labels.template.horizontalCenter = "middle";
    axis.renderer.labels.template.verticalCenter = "top";
  }
});
categoryAxis.events.on("sizechanged", function(ev) {
var axis = ev.target;
  var cellWidth = axis.pixelWidth / (axis.endIndex - axis.startIndex);
  if (cellWidth < axis.renderer.labels.template.maxWidth) {
    axis.renderer.labels.template.rotation = -45;
    axis.renderer.labels.template.horizontalCenter = "right";
    axis.renderer.labels.template.verticalCenter = "middle";
  }
  else {
    axis.renderer.labels.template.rotation = 0;
    axis.renderer.labels.template.horizontalCenter = "middle";
    axis.renderer.labels.template.verticalCenter = "top";
  }
});
{
  // ...
  "xAxes": [{
    // ...
    "events": {
      "sizechanged": function(ev) {
        var axis = ev.target;
        var cellWidth = axis.pixelWidth / (axis.endIndex - axis.startIndex);
        if (cellWidth < axis.renderer.labels.template.maxWidth) {
          axis.renderer.labels.template.rotation = -45;
          axis.renderer.labels.template.horizontalCenter = "right";
          axis.renderer.labels.template.verticalCenter = "middle";
        }
        else {
          axis.renderer.labels.template.rotation = 0;
          axis.renderer.labels.template.horizontalCenter = "middle";
          axis.renderer.labels.template.verticalCenter = "top";
        }
      } 
    }
  }]
}

See the Pen amCharts V4: Axis label wrapping and truncation (5) by amCharts team (@amcharts) on CodePen.24419

Zooming axes

So far we have been using sizechanged event to resize labels when actual width of the chart container changed.

However, zooming the axis would also change number and thus available width for the labels, too.

So, to handle both events, we should execute our label sizing code on axis' startendchanged event, as well.

Related tutorials