---
product: "AG Charts"
title: "Axis Position"
description: "Control where each axis is rendered in an AG Charts cartesian chart and how axes cross with crossAt."
framework: react
version: "14.2.0"
related:
    - title: "Axis Configuration"
      url: "https://www.ag-grid.com/charts/archive/14.2.0/react/axes-configuration/"
    - title: "Axis Types"
      url: "https://www.ag-grid.com/charts/archive/14.2.0/react/axes-types/"
    - title: "Axis Intervals"
      url: "https://www.ag-grid.com/charts/archive/14.2.0/react/axes-intervals/"
    - title: "Axis Domain"
      url: "https://www.ag-grid.com/charts/archive/14.2.0/react/axes-domain/"
    - title: "Axis Labels"
      url: "https://www.ag-grid.com/charts/archive/14.2.0/react/axes-labels/"
    - title: "Time Axes"
      url: "https://www.ag-grid.com/charts/archive/14.2.0/react/axes-time/"
    - title: "Grid Lines & Band Shading"
      url: "https://www.ag-grid.com/charts/archive/14.2.0/react/axes-grid-lines/"
    - title: "Secondary Axes"
      url: "https://www.ag-grid.com/charts/archive/14.2.0/react/axes-secondary/"
llms: "https://www.ag-grid.com/charts/archive/14.2.0/llms.txt"
---

# Axis Position

Cartesian axes can be positioned on the `top`, `bottom`, `left`, or `right` edge of the chart.

## Axis Placement

The axis `position` property controls where the axis is rendered. By default, horizontal axes appear at the bottom of the chart and vertical axes appear on the left.

#### Axis Positions

```tsx
import React, { useState } from "react";
import { createRoot } from "react-dom/client";
import { AgCharts } from "ag-charts-react";
import {
  AgCartesianChartOptions,
  BarSeriesModule,
  CategoryAxisModule,
  LegendModule,
  LineSeriesModule,
  ModuleRegistry,
  NumberAxisModule,
} from "ag-charts-community";

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

const ChartExample = () => {
  const [options, setOptions] = useState<AgCartesianChartOptions>({
    title: {
      text: "Company Financials (2023)",
    },
    data: [
      { quarter: "Q1", revenue: 8.5, profitMargin: 22 },
      { quarter: "Q2", revenue: 11.2, profitMargin: 27 },
      { quarter: "Q3", revenue: 9.8, profitMargin: 25 },
      { quarter: "Q4", revenue: 13.4, profitMargin: 31 },
    ],
    axes: {
      x: {
        title: { text: "Quarter" },
      },
      y: {
        position: "left",
        title: { text: "Revenue ($M)" },
        line: {
          stroke: "red",
          width: 3,
        },
      },
      ySecondary: {
        type: "number",
        position: "right",
        title: { text: "Profit Margin (%)" },
        label: {
          formatter: ({ value }) => `${value}%`,
        },
        line: {
          stroke: "red",
          width: 3,
        },
      },
    },
    series: [
      {
        type: "bar",
        xKey: "quarter",
        yKey: "revenue",
      },
      {
        type: "line",
        xKey: "quarter",
        yKey: "profitMargin",
        yKeyAxis: "ySecondary",
      },
    ],
  });

  return <AgCharts options={options} />;
};

const root = createRoot(document.getElementById("root")!);
root.render(<ChartExample />);
```

[Live example: Axis Positions](https://www.ag-grid.com/charts/archive/14.2.0/reactFunctionalTs/axes-position/examples/axis-position-basic/)

```js
{
    axes: {
        x: {
            type: 'category',
            position: 'bottom',
            title: { text: 'Quarter' },
        },
        y: {
            type: 'number',
            position: 'left',
            title: { text: 'Revenue ($M)' },
        },
        ySecondary: {
            type: 'number',
            position: 'right',
            title: { text: 'Profit Margin (%)' },
        },
    },
}
```

[Secondary Axes](https://www.ag-grid.com/charts/archive/14.2.0/react/axes-secondary/) default to the opposite edge from the primary axis, but it is possible to have multiple axes on the same edge. These are displayed alongside each other.

## Axis Crossing Point

The `crossAt` option allows an axis to intersect a perpendicular axis at a specific axis value instead of the chart edge. This is useful for centring the chart origin or aligning axes to highlight particular thresholds.

The axis title, [labels](https://www.ag-grid.com/charts/archive/14.2.0/react/axes-labels/) and [crosshair label](https://www.ag-grid.com/charts/archive/14.2.0/react/axes-crosshairs/) can be positioned alongside the axis or at the edge of the chart.

#### CrossAt

```tsx
import React, { useState, Fragment } from "react";
import { createRoot } from "react-dom/client";
import { AgCharts } from "ag-charts-react";
import {
  AgCartesianAxisCrossAtPlacement,
  AgCartesianChartOptions,
  CrosshairModule,
  LegendModule,
  LineSeriesModule,
  ModuleRegistry,
  NumberAxisModule,
} from "ag-charts-enterprise";
import { getData } from "./data";
import clone from "clone";

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

const ChartExample = () => {
  const [options, setOptions] = useState<AgCartesianChartOptions>({
    theme: {
      overrides: {
        common: {
          axes: {
            number: {
              line: {
                enabled: true,
                stroke: "red",
              },
              label: {
                color: "red",
              },
            },
          },
        },
      },
    },
    title: { text: "Axes crossing at 0", fontWeight: "bold" },
    data: getData(),
    axes: {
      x: {
        type: "number",
        title: { text: "X Axis" },
        crossAt: {
          value: 0,
        },
      },
      y: {
        type: "number",
        title: { text: "Y Axis" },
        crossAt: {
          value: 0,
        },
      },
    },
    series: [
      {
        type: "line",
        xKey: "x",
        yKey: "y",
        yName: "Function plot",
        strokeWidth: 3,
        marker: { size: 0 },
      },
    ],
  });

  const setTitlePlacement = (placement: AgCartesianAxisCrossAtPlacement) => {
    const nextOptions = clone(options);

    nextOptions.axes!.x!.crossAt!.titlePlacement = placement;
    nextOptions.axes!.y!.crossAt!.titlePlacement = placement;

    setOptions(nextOptions);
  };

  const setLabelPlacement = (placement: AgCartesianAxisCrossAtPlacement) => {
    const nextOptions = clone(options);

    nextOptions.axes!.x!.crossAt!.labelPlacement = placement;
    nextOptions.axes!.y!.crossAt!.labelPlacement = placement;

    setOptions(nextOptions);
  };

  const setCrosshairLabelPlacement = (
    placement: AgCartesianAxisCrossAtPlacement,
  ) => {
    const nextOptions = clone(options);

    nextOptions.axes!.x!.crossAt!.crosshairLabelPlacement = placement;
    nextOptions.axes!.y!.crossAt!.crosshairLabelPlacement = placement;

    setOptions(nextOptions);
  };

  return (
    <Fragment>
      <div className="example-controls">
        <div className="controls-row">
          <label htmlFor="title-placement-select">Title Placement:</label>
          <select
            className="gap-right"
            id="title-placement-select"
            onChange={(event) => setTitlePlacement(event.target.value)}
          >
            <option value="crossing">crossing</option>
            <option value="edge">edge</option>
          </select>
          <label htmlFor="label-placement-select">Label Placement:</label>
          <select
            className="gap-right"
            id="label-placement-select"
            onChange={(event) => setLabelPlacement(event.target.value)}
          >
            <option value="crossing">crossing</option>
            <option value="edge">edge</option>
          </select>
          <label htmlFor="crosshair-label-placement-select">
            Crosshair Label Placement:
          </label>
          <select
            id="crosshair-label-placement-select"
            onChange={(event) => setCrosshairLabelPlacement(event.target.value)}
          >
            <option value="edge">edge</option>
            <option value="crossing">crossing</option>
          </select>
        </div>
      </div>
      <AgCharts options={options} />
    </Fragment>
  );
};

const root = createRoot(document.getElementById("root")!);
root.render(<ChartExample />);
```

[Live example: CrossAt](https://www.ag-grid.com/charts/archive/14.2.0/reactFunctionalTs/axes-position/examples/axis-cross-at/)

```js
{
    axes: {
        x: {
            type: 'number',
            // place the bottom axis at '0' on the left axis scale
            crossAt: {
                value: 0,
                titlePlacement: 'crossing',
                labelPlacement: 'crossing',
                crosshairLabelPlacement: 'edge',
            },
        },
        y: {
            type: 'number',
            // place the left axis at '0' on the bottom axis scale
            crossAt: {
                value: 0,
                titlePlacement: 'crossing',
                labelPlacement: 'crossing',
                crosshairLabelPlacement: 'edge',
            },
        },
    },
}
```

In this example:

- Both axes have a `crossAt.value` set. It is also possible to set it on a single axis only.
- The `crossAt.titlePlacement`, `crossAt.labelPlacement` and `crossAt.crosshairLabelPlacement` properties control where these elements are placed.
- The `crossAt.value` must be of the same type as the perpendicular axis domain, such as `Number` or `Date`.
- The `crossAt` target value should be within the domain of the perpendicular axis.

When the target value leaves the visible range, such as by [Zooming](https://www.ag-grid.com/charts/archive/14.2.0/react/zoom/), the axis will stick to the edge of the chart and remain in view. Set `sticky: false` to allow the axis to be moved out of view in this scenario.

## Band Alignment

The `bandAlignment` option controls the band layout when using [fixed width bars](https://www.ag-grid.com/charts/archive/14.2.0/react/bars/#fixed-width).

#### Band Alignment

```tsx
import React, { useState, Fragment } from "react";
import { createRoot } from "react-dom/client";
import { AgCharts } from "ag-charts-react";
import {
  AgBandAlignment,
  AgCartesianChartOptions,
  AgCategoryAxisOptions,
  BarSeriesModule,
  CategoryAxisModule,
  LegendModule,
  ModuleRegistry,
  NumberAxisModule,
} from "ag-charts-enterprise";
import { DataType, getData } from "./data";
import clone from "clone";

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

const ChartExample = () => {
  const [options, setOptions] = useState<AgCartesianChartOptions<DataType>>({
    data: getData(),
    title: {
      text: "Total Visitors to Museums and Galleries",
    },
    footnote: {
      text: "Source: Department for Digital, Culture, Media & Sport",
    },
    series: [
      {
        type: "bar",
        xKey: "quarter",
        yKey: "museums",
        yName: "Museums",
        width: 10,
      },
      {
        type: "bar",
        xKey: "quarter",
        yKey: "galleries",
        yName: "Galleries",
        width: 10,
      },
      {
        type: "bar",
        xKey: "quarter",
        yKey: "heritage",
        yName: "Heritage Sites",
        width: 10,
      },
    ],
    axes: {
      x: {
        type: "category",
        bandAlignment: "start",
      },
      y: {
        type: "number",
        title: {
          text: "Total Visitors (Millions)",
        },
      },
    },
    formatter: {
      y(params) {
        const value = params.value as number;
        const millions = value / 1000000;
        const accuracy = ["series-label", "axis-label"].includes(params.source)
          ? 0
          : 1;
        return `${millions.toFixed(accuracy)}M`;
      },
    },
  });

  const alignmentChange = (event: Event) => {
    const nextOptions = clone(options);

    const alignment = (event.target as HTMLInputElement)
      .value as AgBandAlignment;
    (nextOptions.axes!.x! as AgCategoryAxisOptions).bandAlignment = alignment;

    setOptions(nextOptions);
  };

  return (
    <Fragment>
      <div className="example-controls">
        <div className="controls-row">
          <div
            className="button-group"
            role="group"
            aria-label="Band Alignment"
          >
            <input
              type="radio"
              id="alignment-justify"
              name="band-alignment"
              defaultValue="justify"
              onChange={(event) => alignmentChange(event)}
            />
            <label htmlFor="alignment-justify">Justify</label>
            <input
              type="radio"
              id="alignment-start"
              name="band-alignment"
              defaultValue="start"
              defaultChecked
              onChange={(event) => alignmentChange(event)}
            />
            <label htmlFor="alignment-start">Start</label>
            <input
              type="radio"
              id="alignment-center"
              name="band-alignment"
              defaultValue="center"
              onChange={(event) => alignmentChange(event)}
            />
            <label htmlFor="alignment-center">Center</label>
            <input
              type="radio"
              id="alignment-end"
              name="band-alignment"
              defaultValue="end"
              onChange={(event) => alignmentChange(event)}
            />
            <label htmlFor="alignment-end">End</label>
          </div>
        </div>
      </div>
      <AgCharts options={options} />
    </Fragment>
  );
};

const root = createRoot(document.getElementById("root")!);
root.render(<ChartExample />);
```

[Live example: Band Alignment](https://www.ag-grid.com/charts/archive/14.2.0/reactFunctionalTs/axes-position/examples/band-alignment/)

```js
{
    axes: {
        x: {
            type: 'category',
            bandAlignment: 'start',
        },
    },
}
```

See the [Series Bars](https://www.ag-grid.com/charts/archive/14.2.0/react/bars/#band-alignment) documentation for more details.
