---
title: "Axis Labels"
framework: javascript
version: "14.1.0"
---

# Axis Labels

Axis labels provide clear identification and context for the data represented on each axis in a chart.

## Collision Avoidance

AG Charts has a number of methods to avoid axis label collisions, which occur when two labels overlap or when a label exceeds the axis's `maxThicknessRatio`.

#### Axis Label Collision

```ts
import {
  AgBarSeriesOptions,
  AgCartesianChartOptions,
  AgCategoryAxisOptions,
  AgCharts,
  AgNumberAxisOptions,
  BarSeriesModule,
  CategoryAxisModule,
  LegendModule,
  ModuleRegistry,
  NumberAxisModule,
  TextWrap,
} from "ag-charts-community";
import { getData } from "./data";

ModuleRegistry.registerModules([
  BarSeriesModule,
  CategoryAxisModule,
  LegendModule,
  NumberAxisModule,
]);

const options: AgCartesianChartOptions = {
  data: getData(),
  series: [
    {
      type: "bar",
      xKey: "year",
      yKey: "value",
    },
  ],
  axes: {
    x: {
      type: "category",
      label: {},
    },
    y: {
      type: "number",
      label: {},
    },
  },
};

options.container = document.getElementById("myChart");

const chart = AgCharts.create(options);

function reset() {
  const categoryAxis = options.axes!.x! as AgCategoryAxisOptions;
  const numberAxis = options.axes!.y! as AgNumberAxisOptions;
  delete categoryAxis.label!.rotation;
  delete categoryAxis.label!.autoRotate;
  delete categoryAxis.label!.avoidCollisions;
  delete categoryAxis.label!.truncate;
  delete numberAxis.label!.rotation;
  delete numberAxis.label!.autoRotate;
  delete numberAxis.label!.avoidCollisions;
  delete numberAxis.label!.truncate;
  (options.series![0] as AgBarSeriesOptions).xKey = "year";

  chart.update(options);
}

function rotationChange(e: Event) {
  const categoryAxis = options.axes!.x! as AgCategoryAxisOptions;
  const numberAxis = options.axes!.y! as AgNumberAxisOptions;
  delete categoryAxis.label!.rotation;
  delete numberAxis.label!.rotation;
  const value = (e.target as HTMLInputElement).value;
  switch (value) {
    case "auto":
      categoryAxis.label!.autoRotate = true;
      numberAxis.label!.autoRotate = true;
      break;
    case "fixed":
      categoryAxis.label!.rotation = 45;
      numberAxis.label!.rotation = 45;
      categoryAxis.label!.autoRotate = false;
      numberAxis.label!.autoRotate = false;
      break;
    case "disabled":
      categoryAxis.label!.autoRotate = false;
      numberAxis.label!.autoRotate = false;
      break;
  }

  chart.update(options);
}

function labelChange(e: Event) {
  const value = (e.target as HTMLInputElement).value;
  (options.series![0] as AgBarSeriesOptions).xKey = value;

  chart.update(options);
}

function truncationChange(e: Event) {
  const categoryAxis = options.axes!.x! as AgCategoryAxisOptions;
  const numberAxis = options.axes!.y! as AgNumberAxisOptions;
  delete categoryAxis.label!.rotation;
  delete numberAxis.label!.rotation;
  const value = (e.target as HTMLInputElement).value;
  const enabled = value === "enabled";
  categoryAxis.label!.truncate = enabled;
  numberAxis.label!.truncate = enabled;

  chart.update(options);
}

function avoidanceChange(e: Event) {
  const categoryAxis = options.axes!.x! as AgCategoryAxisOptions;
  const numberAxis = options.axes!.y! as AgNumberAxisOptions;
  delete categoryAxis.label!.rotation;
  delete numberAxis.label!.rotation;
  const value = (e.target as HTMLInputElement).value;
  const enabled = value === "enabled";
  categoryAxis.label!.avoidCollisions = enabled;
  numberAxis.label!.avoidCollisions = enabled;

  chart.update(options);
}

function wrapChange(e: Event) {
  const categoryAxis = options.axes!.x! as AgCategoryAxisOptions;
  const numberAxis = options.axes!.y! as AgNumberAxisOptions;
  const value = (e.target as HTMLInputElement).value as TextWrap;
  categoryAxis.label!.wrapping = value;
  numberAxis.label!.wrapping = value;

  chart.update(options);
}

if (typeof window !== "undefined") {
  // Attach external event handlers to window so they can be called from index.html
  (<any>window).reset = reset;
  (<any>window).rotationChange = rotationChange;
  (<any>window).labelChange = labelChange;
  (<any>window).truncationChange = truncationChange;
  (<any>window).avoidanceChange = avoidanceChange;
  (<any>window).wrapChange = wrapChange;
}
```

[Live example: Axis Label Collision](https://www.ag-grid.com/charts/typescript/axes-labels/examples/axis-label-collision)

In this example:

- Use the grab handle in the bottom right of the example to resize the chart. Observe how the labels behave with the different options applied.
- The first dropdown allows enabling and disabling collision avoidance altogether.
- The second dropdown buttons allows changing the length of the labels. This more easily shows the [wrapping](#wrapping) and [skipping](#skipping) behaviour.
- The [Rotation](#rotation), [Wrapping](#wrapping) and [Truncation](#truncation) controls enable exploration of their behaviour with all the available options.
- If enabled, labels try [wrapping](#wrapping), then [truncation](#truncation), [rotation](#rotation), and finally [skipping](#skipping) if needed.

Collision avoidance is enabled by default, to disable set `label.avoidCollisions` to false.

```js
{
    label: {
        avoidCollisions: false,
    },
}
```

### Wrapping

Text wrapping allows labels to fit within constrained space by breaking across multiple lines.

Wrapping behaviour is set with the `label.wrapping` property:

- `'on-space'` - Wraps only on whitespace. If no suitable space is found, the next avoidance strategy is used.
- `'always'` - Forces wrapping to fit within the available space, including breaking words if needed.
- `'hyphenate'` - Similar to `'always'`, but inserts a hyphen (`-`) when wrapping in the middle of a word.
- `'never'` - Disables wrapping. Labels will remain on a single line, with the next avoidance strategy being used.

```js
{
    label: {
        wrapping: 'hyphenate',
    },
}
```

This defaults to `on-space` for Category Axes, and to `never` on all other axes types.

### Truncation

Set `truncate: true` on a label to truncate the label’s text when there isn't enough space to display it fully. This ensures as much as possible of each label remains readable without reducing the number of ticks.

When truncation occurs, hovering over the truncated text will display a tooltip with the full label text.

> **Note**
>
> Truncation takes precedence over auto-rotation. When truncation is enabled, auto-rotation will not apply.

### Rotation

Rotating axis labels allows fitting more labels into a smaller area, at the expense of readability.

Three rotation options are available:

- No rotation.
- Fixed rotation - labels are always rotated by the amount specified in the `rotation` property.
- Automatic rotation - labels are rotated if any label will be wider than the gap between ticks.

Automatic rotation can be enabled or disabled using the `autoRotate` property. It is also possible to specify a rotation angle for the automatic rotation via the `autoRotateAngle` property.

Category axes have `autoRotate` enabled by default with a default `autoRotateAngle` of `335`.

### Skipping

Label skipping is performed automatically when there is a high likelihood of collisions between labels. Labels that would collide are not displayed.

A collision is defined as labels coming within 10 pixels of each other. This minimum gap allowed between the axis labels before skipping can be configured using the `label.minSpacing` property.

```js
{
    label: {
        minSpacing: 20,
    },
}
```

If `autoRotate` is enabled, rotation will be attempted before label skipping applies.

## Label Text Formatting

The label text is taken directly from the data.

To format how this is displayed, either use a [Global Formatter](https://www.ag-grid.com/charts/javascript/formatters/), or specify an axis label level [Formatter](#formatter) or [Format](#format) as explained below.

> **Note**
>
> This section discusses formatting the label text. See the [Axis Intervals](https://www.ag-grid.com/charts/javascript/axes-intervals/) section to learn how to configure which labels are shown.

### Formatter

The `label.formatter` callback allows maximum flexibility for controlling what appears in the labels.

#### Axis Label Formatter

```ts
import {
  AgChartOptions,
  AgCharts,
  BarSeriesModule,
  CategoryAxisModule,
  LegendModule,
  ModuleRegistry,
  NumberAxisModule,
} from "ag-charts-community";
import { DataType, getData } from "./data";

ModuleRegistry.registerModules([
  BarSeriesModule,
  CategoryAxisModule,
  LegendModule,
  NumberAxisModule,
]);

const options: AgChartOptions<DataType> = {
  data: getData(),
  title: {
    text: "Desktop Operating Systems",
  },
  series: [
    {
      type: "bar",
      xKey: "os",
      yKey: "share",
    },
  ],
  axes: {
    x: {
      type: "category",
      label: {
        formatter: ({ value }) =>
          value === "Windows" ? "== Windows ==" : value,
      },
    },
    y: {
      type: "number",
      label: {
        formatter: ({ value }) => `${value * 100}%`,
      },
    },
  },
};

options.container = document.getElementById("myChart");

const chart = AgCharts.create(options);
```

[Live example: Axis Label Formatter](https://www.ag-grid.com/charts/typescript/axes-labels/examples/axis-label-formatter)

```js
{
    label: {
        formatter: function (params) {
            return params.value * 100 + '%';
        },
    },
}
```

In the above example:

- The number axis uses a formatter to multiply by 100 and append `'%'` to all values.
- The category axis uses a formatter to add `'=='` around the 'Windows' label only.

The formatter function receives a single `params` object which contains:

- The raw `value` of the label (without any default formatting applied).
- The `index` of the label in the data array.
- The number of `fractionDigits`, if the value is a number.

It is called for each label and should return a string.

### Format

The `label.format` property takes a static string representing a time or number format. This has less flexibility than the formatter, but can be serialised. For all time axes, an object format mapping a unit of time to a format string can also be used.

#### Label Format

```ts
import {
  AgChartOptions,
  AgCharts,
  LegendModule,
  LineSeriesModule,
  ModuleRegistry,
  NumberAxisModule,
  UnitTimeAxisModule,
} from "ag-charts-community";

ModuleRegistry.registerModules([
  LegendModule,
  LineSeriesModule,
  NumberAxisModule,
  UnitTimeAxisModule,
]);

const options: AgChartOptions = {
  series: [
    {
      type: "line",
      xKey: "date",
      yKey: "temp",
    },
  ],
  axes: {
    x: {
      type: "unit-time",
      interval: { step: "month" },
      label: {
        format: "%b %Y",
      },
    },
    y: {
      type: "number",
      label: {
        format: "$#{0>6.2f}",
      },
    },
  },
  data: [
    { date: new Date("2019-01-01"), temp: 82.0 },
    { date: new Date("2019-02-01"), temp: 75.0 },
    { date: new Date("2019-03-01"), temp: 62.0 },
    { date: new Date("2019-04-01"), temp: 99.0 },
    { date: new Date("2019-05-01"), temp: 82.0 },
  ],
};

options.container = document.getElementById("myChart");

const chart = AgCharts.create(options);
```

[Live example: Label Format](https://www.ag-grid.com/charts/typescript/axes-labels/examples/axis-label-format)

```js
{
    label: {
        format: '%b %Y',
    },
}
```

```js
{
    label: {
        format: '$#{0>6.2f}',
    },
}
```

In the above example:

- The time axis uses a format to display the short month name and full year for all values.
- The number axis uses a format to prepend a `'$'` and use 2 decimal places for all values. Shorter numbers are padding with `'0'`.

The syntax used in the format strings depends on the axis type.

See the [Formatters](https://www.ag-grid.com/charts/javascript/formatters/#format-strings) page for a full list of the available formats.

## Customisation

See [Fills & Borders](https://www.ag-grid.com/charts/javascript/fills-borders/) for details on customising axis labels.
