---
title: "Column Pinning"
framework: javascript
version: "36.1.0"
---

# Column Pinning

You can pin columns by setting the `pinned` attribute on the column definition to either `'left'` or `'right'`.

```js
const gridOptions = {
    columnDefs: [
        { field: 'athlete', pinned: 'left' }
    ],

    // other grid options ...
}
```

Below shows an example with three pinned columns on the left and one pinned column on the right. The example also demonstrates changing the pinning via the API at runtime.

The grid will reorder the columns so that 'left pinned' columns come first and 'right pinned' columns come last. In the example below the state of pinned columns impacts the order of the columns such that when 'Country' is pinned, it jumps to the first position.

Use `initialPinned` instead of `pinned` to only set pinning when the column is first created. When column definitions are subsequently updated, `initialPinned` will not re-apply, allowing user changes to be preserved.

#### Column Pinning

```ts
import {
  ClientSideRowModelModule,
  ColDef,
  ColumnApiModule,
  GridApi,
  GridOptions,
  ModuleRegistry,
  createGrid,
  enableDevValidations,
} from "ag-grid-community";
import { IOlympicData } from "./interfaces";

// Enable extended validations only for development
if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

ModuleRegistry.registerModules([ColumnApiModule, ClientSideRowModelModule]);

const columnDefs: ColDef[] = [
  {
    headerName: "#",
    colId: "rowNum",
    valueGetter: "node.id",
    width: 80,
    pinned: "left",
  },
  { field: "athlete", width: 150, pinned: "left" },
  { field: "age", width: 90, pinned: "left" },
  { field: "country", width: 150 },
  { field: "year", width: 90 },
  { field: "date", width: 110 },
  { field: "sport", width: 150 },
  { field: "gold", width: 100 },
  { field: "silver", width: 100 },
  { field: "bronze", width: 100 },
  { field: "total", width: 100, pinned: "right" },
];

let gridApi: GridApi<IOlympicData>;

const gridOptions: GridOptions<IOlympicData> = {
  columnDefs,
};

function clearPinned() {
  gridApi!.applyColumnState({ defaultState: { pinned: null } });
}

function resetPinned() {
  gridApi!.applyColumnState({
    state: [
      { colId: "rowNum", pinned: "left" },
      { colId: "athlete", pinned: "left" },
      { colId: "age", pinned: "left" },
      { colId: "total", pinned: "right" },
    ],
    defaultState: { pinned: null },
  });
}

function pinCountry() {
  gridApi!.applyColumnState({
    state: [{ colId: "country", pinned: "left" }],
    defaultState: { pinned: null },
  });
}

const gridDiv = document.querySelector<HTMLElement>("#myGrid")!;
gridApi = createGrid(gridDiv, gridOptions);

fetch("https://www.ag-grid.com/example-assets/olympic-winners.json")
  .then((response) => response.json())
  .then((data: IOlympicData[]) => gridApi!.setGridOption("rowData", data));

if (typeof window !== "undefined") {
  // Attach external event handlers to window so they can be called from index.html
  (<any>window).clearPinned = clearPinned;
  (<any>window).resetPinned = resetPinned;
  (<any>window).pinCountry = pinCountry;
}
```

[Live example: Column Pinning](https://www.ag-grid.com/examples/column-pinning/column-pinning/typescript)

## Pinning via Column Dragging

It is possible to pin a column by moving the column in the following ways:

- When other columns are pinned, drag the column to the existing pinned area.
- When no columns are pinned, drag the column to the edge of the grid and wait for approximately one second. The grid will then assume you want to pin and create a pinned area and place the column into it.

[Video](https://www.ag-grid.com/_astro/pinning-by-moving.CF95tIue.mp4)

## Resizing Pinned Sections

When resizing pinned columns, the size of the pinned sections (left and right) will be limited to the size of the `grid - 50px`. This will prevent the centre viewport of the grid from becoming inaccessible. For the same reason, if columns that are too wide become pinned, the grid will automatically unpin columns from the pinned sections to make the centre viewport visible again. To customise the columns being unpinned, provide the grid option `processUnpinnedColumns`.

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `processUnpinnedColumns` | `ProcessUnpinnedColumns` |  |  | Allows the user to process the columns being removed from the pinned section because the viewport is too small to accommodate them. Returns an array of columns to be removed from the pinned areas. [Initial](https://www.ag-grid.com/javascript-data-grid/grid-interface/#initial-grid-options). |

## Lock Pinned

If you do not want the user to be able to pin using the UI, set the property `lockPinned=true`. This will block the UI in the following way:

- Dragging a column to the pinned section will not pin the column.
- For AG Grid Enterprise, the column menu will not have a pin option.

The example below demonstrates columns with pinning locked. The following can be noted:

- The column **Athlete** is pinned via the configuration and has `lockPinned=true`. This means the column will be pinned always, it is not possible to drag the column out of the pinned section.
- The column **Age** is not pinned and has `lockPinned=true`. This means the column cannot be pinned by dragging the column.
- All other columns act as normal. They can be added and removed from the pinned section by dragging.

#### Lock Pinned

```ts
import {
  CellStyleModule,
  ClientSideRowModelModule,
  ColDef,
  GridApi,
  GridOptions,
  ModuleRegistry,
  createGrid,
  enableDevValidations,
} from "ag-grid-community";
import { IOlympicData } from "./interfaces";

// Enable extended validations only for development
if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

ModuleRegistry.registerModules([CellStyleModule, ClientSideRowModelModule]);

const columnDefs: ColDef[] = [
  {
    headerName: "Athlete (locked as pinned)",
    field: "athlete",
    width: 240,
    pinned: "left",
    lockPinned: true,
    cellClass: "lock-pinned",
  },
  {
    headerName: "Age (locked as not pinnable)",
    field: "age",
    width: 260,
    lockPinned: true,
    cellClass: "lock-pinned",
  },
  { field: "country", width: 150 },
  { field: "year", width: 90 },
  { field: "date", width: 150 },
  { field: "sport", width: 150 },
  { field: "gold" },
  { field: "silver" },
  { field: "bronze" },
  { field: "total" },
];

let gridApi: GridApi<IOlympicData>;

const gridOptions: GridOptions<IOlympicData> = {
  columnDefs: columnDefs,
};

const gridDiv = document.querySelector<HTMLElement>("#myGrid")!;
gridApi = createGrid(gridDiv, gridOptions);

fetch("https://www.ag-grid.com/example-assets/olympic-winners.json")
  .then((response) => response.json())
  .then((data: IOlympicData[]) => gridApi!.setGridOption("rowData", data));
```

[Live example: Lock Pinned](https://www.ag-grid.com/examples/column-pinning/lock-pinned/typescript)
