---
title: "Series Labels"
framework: vue
version: "14.1.0"
---

# Series Labels

Series data labels display the value of a data point directly on the chart. These are configured on the `label` property of each series.

Please see the [API Reference](#api-reference) for the full list of available options, which vary slightly between series types.

## Styling

Enable labels with `label.enabled`, then style them with the following options.

#### Label Styling

```ts
import { createApp, defineComponent, ref } from "vue";
import { AgCharts } from "ag-charts-vue3";
import type { AgChartOptions } from "ag-charts-types";
import {
  BarSeriesModule,
  CategoryAxisModule,
  LegendModule,
  ModuleRegistry,
  NumberAxisModule,
} from "ag-charts-community";
import { data } from "./data";

function seriesLabel() {
  return {
    enabled: true,
    fontWeight: "bold",
    placement: [
      "outside-end",
      "inside-center",
      "beside-after-center",
      "beside-before-center",
    ],
    orientation: "horizontal",
    border: { enabled: true, strokeWidth: 1 },
    insideStyle: {
      color: "white",
      fill: "black",
      fillOpacity: 0.6,
      border: { stroke: "white" },
    },
    outsideStyle: {
      color: "black",
      fill: "white",
      fillOpacity: 0.8,
      border: { stroke: "black" },
    },
  };
}

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

const ChartExample = defineComponent({
  template: `
    <ag-charts
      :options="options"
    />
  `,
  components: {
    "ag-charts": AgCharts,
  },
  setup(props) {
    const options = ref<AgCartesianChartOptions<DataType>>({
      title: { text: "Quarterly Revenue by Product Line ($m)" },
      data,
      series: [
        {
          type: "bar",
          xKey: "quarter",
          yKey: "hardware",
          yName: "Hardware",
          stacked: true,
          label: seriesLabel(),
        },
        {
          type: "bar",
          xKey: "quarter",
          yKey: "services",
          yName: "Services",
          stacked: true,
          label: seriesLabel(),
        },
        {
          type: "bar",
          xKey: "quarter",
          yKey: "software",
          yName: "Software",
          stacked: true,
          label: seriesLabel(),
        },
      ],
      axes: {
        x: { type: "category" },
        y: { type: "number", max: 90, title: { text: "Revenue ($m)" } },
      },
    });

    return {
      options,
    };
  },
});

createApp(ChartExample).mount("#app");
```

[Live example: Label Styling](https://www.ag-grid.com/charts/vue3/series-labels/examples/label-showcase)

```js
{
    series: [
        {
            // ...
            label: {
                enabled: true,
            },
        },
    ],
}
```

In this example:

- The label text is styled with properties such as `color` and `fontWeight`. Other available options include `fontSize`, `fontStyle` and `fontFamily`.
- The label itself has a fill and border, configured with properties such as `fill` and `border`. Other available options include `fillOpacity`, `cornerRadius` and `padding`. See [Fills & Borders](https://www.ag-grid.com/charts/vue/fills-borders/) for more details.
- The `insideStyle` and `outsideStyle` properties override these text and box styles for when the resolved label placement sits inside or outside the series node — used here to swap between a dark-on-light and light-on-dark treatment.
- Bar-family labels can additionally be rotated with `orientation`. See [Orientation](#orientation) for more details.
- Providing `placement` as an ordered array lets a label fall back to an alternative position. See [Placement](#placement) for more details.

## Placement

The available label positions are series-specific. These include `'inside-start'` or `'outside-end'` for a bar series, and `'top'` or `'left'` for a bubble series.

See the [API Reference](https://www.ag-grid.com/charts/options/) for the full list of placement values per series type.

#### Label Placement

```ts
import { createApp, defineComponent, ref } from "vue";
import { AgCharts } from "ag-charts-vue3";
import type { AgChartOptions } from "ag-charts-types";
import {
  BarSeriesModule,
  BubbleSeriesModule,
  CategoryAxisModule,
  LegendModule,
  ModuleRegistry,
  NumberAxisModule,
} from "ag-charts-community";
import { barData, bubbleData } from "./data";
import type {
  AgBarSeriesLabelPlacement,
  AgChartLabelCollisionPlacement,
} from "ag-charts-types";
import clone from "clone";

type SeriesType = "bubble" | "bar" | "bar-horizontal";

let spacing = 6;

function formatCurrency(value) {
  const sign = value < 0 ? "-" : "";
  return `${sign}$${Math.abs(value)}m`;
}

function parsePlacement(value) {
  const placements = value.split(/,\s*/g);
  return placements.length > 1 ? placements : placements[0];
}

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

const ChartExample = defineComponent({
  template: `
    <div class="example-controls">
      <div class="controls-row">
        <span>Series:</span>
        <button v-on:click="setSeriesType('bubble')"><code>Bubble</code></button>
        <button v-on:click="setSeriesType('bar')"><code>Bar</code></button>
        <button v-on:click="setSeriesType('bar-horizontal')"><code>Horizontal Bar</code></button>
      </div>
      <div class="controls-row">
        <span>Placement:</span>
        <span id="bubblePlacementRow">
          <select id="bubblePlacementSelect" class="gap-right" v-on:change="setPlacement($event.target.value)">
            <option value="top" selected="">Top</option>
            <option value="top-right">Top Right</option>
            <option value="right">Right</option>
            <option value="bottom-right">Bottom Right</option>
            <option value="bottom">Bottom</option>
            <option value="bottom-left">Bottom Left</option>
            <option value="left">Left</option>
            <option value="top-left">Top Left</option>
            <option value="inside">Centre (Inside)</option>
            <hr />
            <option value="top, bottom, left, right">Top + Bottom + Left + Right fallback</option>
            <option value="left, right">Left + Right fallback</option>
          </select>
        </span>
        <span id="barPlacementRow" style="display: none">
          <select id="barPlacementSelect" class="gap-right" v-on:change="setPlacement($event.target.value)">
            <option value="outside-end" selected="">Outside End</option>
            <option value="outside-start">Outside Start</option>
            <option value="inside-end">Inside End</option>
            <option value="inside-start">Inside Start</option>
            <option value="inside-center">Centre (Inside)</option>
            <option value="beside-before-start">Beside Before Start</option>
            <option value="beside-before-center">Beside Before Centre</option>
            <option value="beside-before-end">Beside Before End</option>
            <option value="beside-after-start">Beside After Start</option>
            <option value="beside-after-center">Beside After Centre</option>
            <option value="beside-after-end">Beside After End</option>
            <hr />
            <option value="outside-end, inside-end">Outside End + Inside End fallback</option>
            <option value="inside-center, beside-after-center">Inside Centre + Beside After Centre fallback</option>
          </select>
        </span>
        <label for="spacingSlider">Spacing:</label>
        <input type="range" id="spacingSlider" min="0" max="20" value="6" v-on:input="setSpacing($event)" v-on:change="setSpacing($event)">
          <span id="spacingValue" style="display: inline-block; min-width: 3ch; text-align: right">6</span>
        </div>
      </div>
      <div class="resizable-container">
        <ag-charts
          :options="options"
          class="resizable"
        />
      </div>
  `,
  components: {
    "ag-charts": AgCharts,
  },
  setup(props) {
    const options = ref<AgCartesianChartOptions<BubbleDataType | BarDataType>>({
      title: { text: "Weather Station Readings" },
      data: bubbleData,
      series: [
        {
          type: "bubble",
          xKey: "temperature",
          yKey: "humidity",
          sizeKey: "windSpeed",
          labelKey: "station",
          maxSize: 60,
          label: {
            enabled: true,
            placement: "top",
            spacing,
          },
        },
      ],
      axes: {
        x: { type: "number", title: { text: "Temperature (°C)" } },
        y: { type: "number", title: { text: "Humidity (%)" } },
      },
    });

    const updateSpacingSlider = () => {
      const optionsCopy = clone(options.value);

      const series = optionsCopy.series[0];
      const placement = series.label.placement;
      const isCentred = placement === "inside" || placement === "inside-center";
      document.getElementById("spacingSlider").disabled = isCentred;

      options.value = optionsCopy;
    };
    const setSeriesType = (seriesType) => {
      const optionsCopy = clone(options.value);

      document.getElementById("bubblePlacementRow").style.display =
        seriesType === "bubble" ? "" : "none";
      document.getElementById("barPlacementRow").style.display =
        seriesType === "bubble" ? "none" : "";
      if (seriesType === "bubble") {
        optionsCopy.title = { text: "Weather Station Readings" };
        optionsCopy.data = bubbleData;
        optionsCopy.axes = {
          x: { type: "number", title: { text: "Temperature (°C)" } },
          y: { type: "number", title: { text: "Humidity (%)" } },
        };
        const bubblePlacementSelect = document.getElementById(
          "bubblePlacementSelect",
        );
        optionsCopy.series = [
          {
            type: "bubble",
            xKey: "temperature",
            yKey: "humidity",
            sizeKey: "windSpeed",
            labelKey: "station",
            maxSize: 60,
            label: {
              enabled: true,
              placement: parsePlacement(bubblePlacementSelect.value),
              spacing,
            },
          },
        ];
      } else {
        optionsCopy.title = { text: "Quarterly Profit Change ($m)" };
        optionsCopy.data = barData;
        // direction: 'horizontal' swaps which axis carries the category vs the value
        optionsCopy.axes =
          seriesType === "bar-horizontal"
            ? {
                y: { type: "category" },
                x: { type: "number", title: { text: "Profit Change ($m)" } },
              }
            : {
                x: { type: "category" },
                y: { type: "number", title: { text: "Profit Change ($m)" } },
              };
        const barPlacementSelect =
          document.getElementById("barPlacementSelect");
        optionsCopy.series = [
          {
            type: "bar",
            direction:
              seriesType === "bar-horizontal" ? "horizontal" : "vertical",
            xKey: "quarter",
            yKey: "profitChange",
            label: {
              enabled: true,
              placement: parsePlacement(barPlacementSelect.value),
              spacing,
              truncate: false,
              formatter: ({ value }) => formatCurrency(value),
            },
            tooltip: {
              renderer: ({ datum }) => ({
                data: [
                  {
                    label: "Profit Change",
                    value: formatCurrency(datum.profitChange),
                  },
                ],
              }),
            },
          },
        ];
      }

      updateSpacingSlider();

      options.value = optionsCopy;
    };
    const setPlacement = (placement) => {
      const optionsCopy = clone(options.value);

      const series = optionsCopy.series[0];
      series.label.placement = parsePlacement(placement);

      updateSpacingSlider();

      options.value = optionsCopy;
    };
    const setSpacing = (event) => {
      const optionsCopy = clone(options.value);

      spacing = Number(event.target.value);
      document.getElementById("spacingValue").textContent = String(spacing);
      const series = optionsCopy.series[0];
      series.label.spacing = spacing;

      options.value = optionsCopy;
    };

    return {
      options,
      setSeriesType,
      setPlacement,
      setSpacing,
    };
  },
});

createApp(ChartExample).mount("#app");
```

[Live example: Label Placement](https://www.ag-grid.com/charts/vue3/series-labels/examples/label-position)

```js
{
    series: [
        {
            // ...
            label: {
                enabled: true,
                placement: ['top', 'bottom', 'left', 'right'],
                spacing: 6,
            },
        },
    ],
}
```

In this example:

- Providing `placement` as an ordered array allows the label to fallback to an alternative position if the first doesn't fit or collides with another item.
  - This is affected by [Orientation](#orientation) and other [Collision Avoidance](#collision-avoidance) options.
  - Resize the example to see the fallback placements in action.
- `spacing` sets the pixel distance between a label and its anchor and is ignored when the resolved placement is centred.

## Orientation

Bar-family series can rotate their labels using the `label.orientation` option. This accepts `'horizontal'`, `'vertical'` or `'vertical-reversed'`, or an ordered array of fallback orientations.

#### Label Orientation

```ts
import { createApp, defineComponent, ref } from "vue";
import { AgCharts } from "ag-charts-vue3";
import type { AgChartOptions } from "ag-charts-types";
import {
  BarSeriesModule,
  CategoryAxisModule,
  LegendModule,
  ModuleRegistry,
  NumberAxisModule,
} from "ag-charts-community";
import { data } from "./data";
import type { AgChartLabelOrientation } from "ag-charts-types";
import clone from "clone";

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

const ChartExample = defineComponent({
  template: `
    <div class="example-controls">
      <div class="controls-row">
        <span>Orientation:</span>
        <select class="gap-right" v-on:change="setOrientation($event.target.value)">
          <option value="horizontal" selected="">Horizontal</option>
          <option value="vertical">Vertical</option>
          <option value="vertical-reversed">Vertical Reversed</option>
          <hr />
          <option value="horizontal, vertical">Horizontal, Vertical fallback</option>
          <option value="vertical, horizontal">Vertical, Horizontal fallback</option>
        </select>
      </div>
    </div>
    <div class="resizable-container">
      <ag-charts
        :options="options"
        class="resizable"
      />
    </div>
  `,
  components: {
    "ag-charts": AgCharts,
  },
  setup(props) {
    const options = ref<AgCartesianChartOptions<DataType>>({
      title: { text: "Quarterly Profit Change ($m)" },
      data,
      series: [
        {
          type: "bar",
          xKey: "quarter",
          yKey: "profitChange",
          label: {
            enabled: true,
            placement: "inside-end",
            orientation: "horizontal",
            wrapping: "never",
            formatter: (params) =>
              `$${params.value}m profit${params.datum.note ? ` (${params.datum.note})` : ""}`,
          },
          tooltip: {
            renderer: ({ datum }) => ({
              data: [
                { label: "Profit Change", value: `$${datum.profitChange}m` },
              ],
            }),
          },
        },
      ],
      axes: {
        x: { type: "category" },
        y: { type: "number", title: { text: "Profit Change ($m)" } },
      },
    });

    const setOrientation = (orientation) => {
      const optionsCopy = clone(options.value);

      const series = optionsCopy.series[0];
      const orientations = orientation.split(/,\s*/g);
      series.label.orientation =
        orientations.length > 1 ? orientations : orientations[0];

      options.value = optionsCopy;
    };

    return {
      options,
      setOrientation,
    };
  },
});

createApp(ChartExample).mount("#app");
```

[Live example: Label Orientation](https://www.ag-grid.com/charts/vue3/series-labels/examples/label-orientation)

```js
{
    series: [
        {
            type: 'bar',
            // ...
            label: {
                enabled: true,
                orientation: ['horizontal', 'vertical'],
                wrapping: 'never',
            },
        },
    ],
}
```

In this example:

- Providing `orientation` as an ordered array allows the label to fallback to an alternative orientation if the first doesn't fit or collides with another item.
  - This is affected by [Placement](#placement) and other [Collision Avoidance](#collision-avoidance) options.
  - Resize the example to see the fallback placements in action.

## Collision Avoidance

As well as using [fallback placement](#placement) and [fallback orientation](#orientation) options, labels can also wrap, truncate or be hidden when they collide with other elements or don't fit within provided `maxWidth`/`maxHeight` values.

#### Label Fitting

```ts
import { createApp, defineComponent, ref } from "vue";
import { AgCharts } from "ag-charts-vue3";
import type { AgChartOptions } from "ag-charts-types";
import {
  BarSeriesModule,
  CategoryAxisModule,
  LegendModule,
  ModuleRegistry,
  NumberAxisModule,
} from "ag-charts-community";
import { data } from "./data";
import type { TextWrap } from "ag-charts-types";
import clone from "clone";

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

const ChartExample = defineComponent({
  template: `
    <div class="example-controls">
      <div class="controls-row">
        <div class="gap-right">
          <label for="maxWidthSlider">Max Width:</label>
          <input type="range" id="maxWidthSlider" min="20" max="150" value="70" v-on:input="setMaxWidth($event)" v-on:change="setMaxWidth($event)">
            <span id="maxWidthValue" style="display: inline-block; min-width: 4ch; text-align: right">70</span>
          </div>
          <div>
            <label for="maxHeightSlider">Max Height:</label>
            <input type="range" id="maxHeightSlider" min="10" max="80" value="54" v-on:input="setMaxHeight($event)" v-on:change="setMaxHeight($event)">
              <span id="maxHeightValue" style="display: inline-block; min-width: 4ch; text-align: right">54</span>
            </div>
          </div>
          <div class="controls-row">
            <div class="gap-right">
              <label for="wrap-select">Wrapping:</label>
              <select id="wrap-select" v-on:change="setWrapping($event.target.value)">
                <option value="on-space">on-space (default)</option>
                <option value="always">always</option>
                <option value="hyphenate">hyphenate</option>
                <option value="never">never</option>
              </select>
            </div>
            <div>
              <label for="truncate-select">Truncate:</label>
              <select id="truncate-select" v-on:change="setTruncate($event.target.value)">
                <option value="enabled">Enabled</option>
                <option value="disabled">Disabled</option>
              </select>
            </div>
          </div>
        </div>
        <div class="resizable-container">
          <ag-charts
            :options="options"
            class="resizable"
          />
        </div>
  `,
  components: {
    "ag-charts": AgCharts,
  },
  setup(props) {
    const options = ref<AgCartesianChartOptions<DataType>>({
      title: { text: "Quarterly Revenue by Leading Division" },
      data,
      series: [
        {
          type: "bar",
          xKey: "quarter",
          yKey: "revenue",
          label: {
            enabled: true,
            placement: "inside-end",
            formatter: (params) => `$${params.value}m ${params.datum.division}`,
            maxWidth: 70,
            maxHeight: 54,
            wrapping: "on-space",
            truncate: true,
          },
          tooltip: {
            renderer: ({ datum }) => ({
              data: [{ label: "Revenue", value: `$${datum.revenue}m` }],
            }),
          },
        },
      ],
      axes: {
        x: { type: "category" },
        y: { type: "number", title: { text: "Revenue ($m)" } },
      },
    });

    const setMaxWidth = (event) => {
      const optionsCopy = clone(options.value);

      const value = Number(event.target.value);
      document.getElementById("maxWidthValue").textContent = String(value);
      optionsCopy.series[0].label.maxWidth = value;

      options.value = optionsCopy;
    };
    const setMaxHeight = (event) => {
      const optionsCopy = clone(options.value);

      const value = Number(event.target.value);
      document.getElementById("maxHeightValue").textContent = String(value);
      optionsCopy.series[0].label.maxHeight = value;

      options.value = optionsCopy;
    };
    const setWrapping = (wrapping) => {
      const optionsCopy = clone(options.value);

      optionsCopy.series[0].label.wrapping = wrapping;

      options.value = optionsCopy;
    };
    const setTruncate = (value) => {
      const optionsCopy = clone(options.value);

      optionsCopy.series[0].label.truncate = value === "enabled";

      options.value = optionsCopy;
    };

    return {
      options,
      setMaxWidth,
      setMaxHeight,
      setWrapping,
      setTruncate,
    };
  },
});

createApp(ChartExample).mount("#app");
```

[Live example: Label Fitting](https://www.ag-grid.com/charts/vue3/series-labels/examples/label-fitting)

```js
{
    series: [
        {
            // ...
            label: {
                enabled: true,
                placement: 'inside-end',
                maxWidth: 70,
                maxHeight: 54,
                wrapping: 'on-space',
                truncate: true,
            },
        },
    ],
}
```

In this example:

- `maxWidth` and `maxHeight` specify the maximum label size.
- `wrapping` (`'on-space'`, `'always'`, `'hyphenate'`, `'never'`) controls how overflowing text wraps within the provided size or bar boundary.
- `truncate` truncates whatever still doesn't fit, appending an ellipsis.

Series label collision avoidance is separate from [axis label collision avoidance](https://www.ag-grid.com/charts/vue/axes-labels/#collision-avoidance), which is configured independently on each axis.

### Hiding Labels

When any of these strategies are used but fail to find a satisfactory resolution, the label is hidden by default.

Use `collision.alwaysShow: true` to force the label to remain visible, or `collision.alwaysShow: false` to allow labels to be hidden even when no other strategies are enabled.

#### Label Collision Threshold

```ts
import { createApp, defineComponent, ref } from "vue";
import { AgCharts } from "ag-charts-vue3";
import type { AgChartOptions } from "ag-charts-types";
import {
  BubbleSeriesModule,
  LegendModule,
  ModuleRegistry,
  NumberAxisModule,
} from "ag-charts-community";
import { data } from "./data";
import clone from "clone";

ModuleRegistry.registerModules([
  BubbleSeriesModule,
  LegendModule,
  NumberAxisModule,
]);

const ChartExample = defineComponent({
  template: `
    <div class="example-controls">
      <div class="controls-row">
        <label for="thresholdSlider">Collision Threshold:</label>
        <input type="range" id="thresholdSlider" min="-10" max="5" value="4" v-on:input="setThreshold($event)" v-on:change="setThreshold($event)">
          <span id="thresholdValue" style="display: inline-block; min-width: 4ch; text-align: right">4</span>
        </div>
        <div class="controls-row">
          <span>Colliding labels:</span>
          <select v-on:change="setAlwaysShow($event.target.value)">
            <option value="hide" selected="">Hide</option>
            <option value="show">Keep visible</option>
          </select>
        </div>
      </div>
      <div class="resizable-container">
        <ag-charts
          :options="options"
          class="resizable"
        />
      </div>
  `,
  components: {
    "ag-charts": AgCharts,
  },
  setup(props) {
    const options = ref<AgCartesianChartOptions<DataType>>({
      title: { text: "Weather Station Readings" },
      data,
      series: [
        {
          type: "bubble",
          xKey: "temperature",
          yKey: "humidity",
          sizeKey: "windSpeed",
          labelKey: "station",
          label: {
            enabled: true,
            border: {
              enabled: true,
              stroke: {
                ref: "foregroundColor",
                mix: 0.5,
                onto: "backgroundColor",
              },
              strokeWidth: 2,
            },
            collision: {
              threshold: 4,
              alwaysShow: false,
            },
          },
        },
      ],
      axes: {
        x: { type: "number", title: { text: "Temperature (°C)" } },
        y: { type: "number", title: { text: "Humidity (%)" } },
      },
    });

    const updateThresholdSlider = () => {
      const optionsCopy = clone(options.value);

      const series = optionsCopy.series[0];
      document.getElementById("thresholdSlider").disabled = Boolean(
        series.label.collision.alwaysShow,
      );

      options.value = optionsCopy;
    };
    const setThreshold = (event) => {
      const optionsCopy = clone(options.value);

      const value = Number(event.target.value);
      document.getElementById("thresholdValue").textContent = String(value);
      optionsCopy.series[0].label.collision.threshold = value;

      options.value = optionsCopy;
    };
    const setAlwaysShow = (value) => {
      const optionsCopy = clone(options.value);

      optionsCopy.series[0].label.collision.alwaysShow = value === "show";

      updateThresholdSlider();

      options.value = optionsCopy;
    };

    return {
      options,
      setThreshold,
      setAlwaysShow,
    };
  },
});

createApp(ChartExample).mount("#app");
```

[Live example: Label Collision Threshold](https://www.ag-grid.com/charts/vue3/series-labels/examples/label-threshold)

```js
{
    series: [
        {
            // ...
            label: {
                enabled: true,
                collision: {
                    alwaysShow: true,
                },
            },
        },
    ],
}
```

### Threshold

Collisions are defined as the edge of one label hitting the edge of another element.

Use a `collision.threshold` value to ensure labels are a minimum pixel distance from obstacles, or a negative value to allow labels to overlap somewhat.

```js
{
    series: [
        {
            // ...
            label: {
                enabled: true,
                collision: {
                    threshold: 4,
                },
            },
        },
    ],
}
```

## API Reference

#### Label Options

| Property | Type | Default | Description |
| --- | --- | --- | --- |
| formatter | RichFormatter |  | A custom formatting function used to convert data values into text for display by labels. |
| format | string |  | Format string used when rendering labels. |
| itemStyler | Styler |  | Function used to style individual datum labels. |
| enabled | boolean |  | Whether the associated elements and properties should be used in the chart. |
| color | CssColor \| AgColorRef \| AgColorRefMixOnto \| AgColorRefMixOntoColor |  | The colour for text elements. A colour string, or a theme-colour reference object. |
| fontSize | FontSize |  | The size of the font in pixels for text elements. |
| fontFamily | FontFamily |  | The font family for text elements. |
| fontStyle | FontStyle |  | The style to use for text elements. |
| fontWeight | FontWeight |  | The font weight to use for text elements. |
| border | BorderOptions |  | Stroke options for the box border. |
| border.enabled | boolean |  | Whether the associated elements and properties should be used in the chart. |
| border.stroke | CssColor \| AgColorRef \| AgColorRefMixOnto \| AgColorRefMixOntoColor |  | The colour for the stroke. |
| border.strokeWidth | PixelSize |  | The width of the stroke in pixels. |
| border.strokeOpacity | Opacity |  | The opacity of the stroke colour. |
| cornerRadius | PixelSize |  | Apply rounded corners to the label box. |
| padding | PixelSize \| PaddingOptions |  | Distance between the label text and the border. A number applies uniform padding; an object sets each side. |
| fill | CssColor \| AgColorRef \| AgColorRefMixOnto \| AgColorRefMixOntoColor \| AgGradientColor \| AgPatternColor \| AgImageFill |  | The colour for filling shapes. A colour string, or an object for a gradient, pattern, or image fill. |
| fillOpacity | Opacity |  | The opacity of the fill colour. |

#### Collision Avoidance

| Property | Type | Default | Description |
| --- | --- | --- | --- |
| collision | AgChartLabelCollisionOptions |  | Configuration controlling the spacing kept from obstacles and whether a label that cannot be placed clear of every obstacle is kept at its least-overflowing placement or hidden. |
| collision.threshold | PixelSize |  | Collision threshold in pixels. A positive value triggers avoidance strategies when labels are further away, a negative value allows labels to overlap without triggering avoidance. |
| collision.alwaysShow | boolean |  | Whether to keep a colliding label visible when a collision remains after every avoidance strategy has been applied. When `true` the label stays at the best available position; when `false` it is hidden instead. |
| maxWidth | PixelSize |  | Maximum width, in pixels, the label may occupy before it is wrapped or truncated to fit. |
| maxHeight | PixelSize |  | Maximum height, in pixels, the label may occupy before it is wrapped or truncated to fit. |
| wrapping | 'never' \| 'always' \| 'hyphenate' \| 'on-space' |  | Text wrapping strategy applied when the label is constrained by `maxWidth` or `maxHeight`. - `'always'` will always wrap text to fit within the bounds. - `'hyphenate'` is similar to `'always'`, but inserts a hyphen (`-`) if forced to wrap in the middle of a word. - `'on-space'` will only wrap on white space. If there is no possibility to wrap a line on space and satisfy the bounds, the text will be truncated. - `'never'` disables text wrapping. |
| truncate | boolean |  | Whether to truncate the label with an ellipsis when it does not fit within its bounds. |
