📄 tanstack/table/latest/docs/framework/react/examples/column-sizing

File: column-sizing.md | Updated: 11/15/2025

Source: https://tanstack.com/table/latest/docs/framework/react/examples/column-sizing



TanStack

Table v8v8

Search...

+ K

Auto

Log In

TanStack StartRC

Docs Examples GitHub Contributors

TanStack Router

Docs Examples GitHub Contributors

TanStack Query

Docs Examples GitHub Contributors

TanStack Table

Docs Examples Github Contributors

TanStack Formnew

Docs Examples Github Contributors

TanStack DBbeta

Docs Github Contributors

TanStack Virtual

Docs Examples Github Contributors

TanStack Paceralpha

Docs Examples Github Contributors

TanStack Storealpha

Docs Examples Github Contributors

TanStack Devtoolsalpha

Docs Github Contributors

More Libraries

Maintainers Partners Support Learn StatsBETA Discord Merch Blog GitHub Ethos Brand Guide

Documentation

Framework

React logo

React

Version

Latest

Search...

+ K

Menu

Getting Started

Core Guides

Feature Guides

Core APIs

Feature APIs

Enterprise

Examples

Framework

React logo

React

Version

Latest

Menu

Getting Started

Core Guides

Feature Guides

Core APIs

Feature APIs

Enterprise

Examples

React Example: Column Sizing

Github StackBlitz CodeSandbox

===========================================================================================================================================================================================================================================================================================================================================================================================================================

Code ExplorerCode

Interactive SandboxSandbox

  • src

    • index.css file iconindex.css

    • main.tsx file iconmain.tsx

  • .gitignore file icon.gitignore

  • README.md file iconREADME.md

  • index.html file iconindex.html

  • package.json file iconpackage.json

  • tsconfig.json file icontsconfig.json

  • vite.config.js file iconvite.config.js

tsx

import React from 'react'
import ReactDOM from 'react-dom/client'

import './index.css'

import {
  useReactTable,
  ColumnResizeMode,
  getCoreRowModel,
  ColumnDef,
  flexRender,
  ColumnResizeDirection,
} from '@tanstack/react-table'

type Person = {
  firstName: string
  lastName: string
  age: number
  visits: number
  status: string
  progress: number
}

const defaultData: Person[] = [\
  {\
    firstName: 'tanner',\
    lastName: 'linsley',\
    age: 24,\
    visits: 100,\
    status: 'In Relationship',\
    progress: 50,\
  },\
  {\
    firstName: 'tandy',\
    lastName: 'miller',\
    age: 40,\
    visits: 40,\
    status: 'Single',\
    progress: 80,\
  },\
  {\
    firstName: 'joe',\
    lastName: 'dirte',\
    age: 45,\
    visits: 20,\
    status: 'Complicated',\
    progress: 10,\
  },\
]

const defaultColumns: ColumnDef<Person>[] = [\
  {\
    header: 'Name',\
    footer: props => props.column.id,\
    columns: [\
      {\
        accessorKey: 'firstName',\
        cell: info => info.getValue(),\
        footer: props => props.column.id,\
      },\
      {\
        accessorFn: row => row.lastName,\
        id: 'lastName',\
        cell: info => info.getValue(),\
        header: () => <span>Last Name</span>,\
        footer: props => props.column.id,\
      },\
    ],\
  },\
  {\
    header: 'Info',\
    footer: props => props.column.id,\
    columns: [\
      {\
        accessorKey: 'age',\
        header: () => 'Age',\
        footer: props => props.column.id,\
      },\
      {\
        header: 'More Info',\
        columns: [\
          {\
            accessorKey: 'visits',\
            header: () => <span>Visits</span>,\
            footer: props => props.column.id,\
          },\
          {\
            accessorKey: 'status',\
            header: 'Status',\
            footer: props => props.column.id,\
          },\
          {\
            accessorKey: 'progress',\
            header: 'Profile Progress',\
            footer: props => props.column.id,\
          },\
        ],\
      },\
    ],\
  },\
]

function App() {
  const [data] = React.useState(() => [...defaultData])
  const [columns] = React.useState<typeof defaultColumns>(() => [\
    ...defaultColumns,\
  ])

  const [columnResizeMode, setColumnResizeMode] =
    React.useState<ColumnResizeMode>('onChange')

  const [columnResizeDirection, setColumnResizeDirection] =
    React.useState<ColumnResizeDirection>('ltr')

  const rerender = React.useReducer(() => ({}), {})[1]

  const table = useReactTable({
    data,
    columns,
    columnResizeMode,
    columnResizeDirection,
    getCoreRowModel: getCoreRowModel(),
    debugTable: true,
    debugHeaders: true,
    debugColumns: true,
  })

  return (
    <div className="p-2">
      <select
        value={columnResizeMode}
        onChange={e => setColumnResizeMode(e.target.value as ColumnResizeMode)}
        className="border p-2 border-black rounded"
      >
        <option value="onEnd">Resize: "onEnd"</option>
        <option value="onChange">Resize: "onChange"</option>
      </select>
      <select
        value={columnResizeDirection}
        onChange={e =>
          setColumnResizeDirection(e.target.value as ColumnResizeDirection)
        }
        className="border p-2 border-black rounded"
      >
        <option value="ltr">Resize Direction: "ltr"</option>
        <option value="rtl">Resize Direction: "rtl"</option>
      </select>
      <div style={{ direction: table.options.columnResizeDirection }}>
        <div className="h-4" />
        <div className="text-xl">{'<table/>'}</div>
        <div className="overflow-x-auto">
          <table
            {...{
              style: {
                width: table.getCenterTotalSize(),
              },
            }}
          >
            <thead>
              {table.getHeaderGroups().map(headerGroup => (
                <tr key={headerGroup.id}>
                  {headerGroup.headers.map(header => (
                    <th
                      {...{
                        key: header.id,
                        colSpan: header.colSpan,
                        style: {
                          width: header.getSize(),
                        },
                      }}
                    >
                      {header.isPlaceholder
                        ? null
                        : flexRender(
                            header.column.columnDef.header,
                            header.getContext()
                          )}
                      <div
                        {...{
                          onDoubleClick: () => header.column.resetSize(),
                          onMouseDown: header.getResizeHandler(),
                          onTouchStart: header.getResizeHandler(),
                          className: `resizer ${
                            table.options.columnResizeDirection
                          } ${
                            header.column.getIsResizing() ? 'isResizing' : ''
                          }`,
                          style: {
                            transform:
                              columnResizeMode === 'onEnd' &&
                              header.column.getIsResizing()
                                ? `translateX(${
                                    (table.options.columnResizeDirection ===
                                    'rtl'
                                      ? -1
                                      : 1) *
                                    (table.getState().columnSizingInfo
                                      .deltaOffset ?? 0)
                                  }px)`
                                : '',
                          },
                        }}
                      />
                    </th>
                  ))}
                </tr>
              ))}
            </thead>
            <tbody>
              {table.getRowModel().rows.map(row => (
                <tr key={row.id}>
                  {row.getVisibleCells().map(cell => (
                    <td
                      {...{
                        key: cell.id,
                        style: {
                          width: cell.column.getSize(),
                        },
                      }}
                    >
                      {flexRender(
                        cell.column.columnDef.cell,
                        cell.getContext()
                      )}
                    </td>
                  ))}
                </tr>
              ))}
            </tbody>
          </table>
        </div>
        <div className="h-4" />
        <div className="text-xl">{'<div/> (relative)'}</div>
        <div className="overflow-x-auto">
          <div
            {...{
              className: 'divTable',
              style: {
                width: table.getTotalSize(),
              },
            }}
          >
            <div className="thead">
              {table.getHeaderGroups().map(headerGroup => (
                <div
                  {...{
                    key: headerGroup.id,
                    className: 'tr',
                  }}
                >
                  {headerGroup.headers.map(header => (
                    <div
                      {...{
                        key: header.id,
                        className: 'th',
                        style: {
                          width: header.getSize(),
                        },
                      }}
                    >
                      {header.isPlaceholder
                        ? null
                        : flexRender(
                            header.column.columnDef.header,
                            header.getContext()
                          )}
                      <div
                        {...{
                          onDoubleClick: () => header.column.resetSize(),
                          onMouseDown: header.getResizeHandler(),
                          onTouchStart: header.getResizeHandler(),
                          className: `resizer ${
                            table.options.columnResizeDirection
                          } ${
                            header.column.getIsResizing() ? 'isResizing' : ''
                          }`,
                          style: {
                            transform:
                              columnResizeMode === 'onEnd' &&
                              header.column.getIsResizing()
                                ? `translateX(${
                                    (table.options.columnResizeDirection ===
                                    'rtl'
                                      ? -1
                                      : 1) *
                                    (table.getState().columnSizingInfo
                                      .deltaOffset ?? 0)
                                  }px)`
                                : '',
                          },
                        }}
                      />
                    </div>
                  ))}
                </div>
              ))}
            </div>
            <div
              {...{
                className: 'tbody',
              }}
            >
              {table.getRowModel().rows.map(row => (
                <div
                  {...{
                    key: row.id,
                    className: 'tr',
                  }}
                >
                  {row.getVisibleCells().map(cell => (
                    <div
                      {...{
                        key: cell.id,
                        className: 'td',
                        style: {
                          width: cell.column.getSize(),
                        },
                      }}
                    >
                      {flexRender(
                        cell.column.columnDef.cell,
                        cell.getContext()
                      )}
                    </div>
                  ))}
                </div>
              ))}
            </div>
          </div>
        </div>
        <div className="h-4" />
        <div className="text-xl">{'<div/> (absolute positioning)'}</div>
        <div className="overflow-x-auto">
          <div
            {...{
              className: 'divTable',
              style: {
                width: table.getTotalSize(),
              },
            }}
          >
            <div className="thead">
              {table.getHeaderGroups().map(headerGroup => (
                <div
                  {...{
                    key: headerGroup.id,
                    className: 'tr',
                    style: {
                      position: 'relative',
                    },
                  }}
                >
                  {headerGroup.headers.map(header => (
                    <div
                      {...{
                        key: header.id,
                        className: 'th',
                        style: {
                          position: 'absolute',
                          left: header.getStart(),
                          width: header.getSize(),
                        },
                      }}
                    >
                      {header.isPlaceholder
                        ? null
                        : flexRender(
                            header.column.columnDef.header,
                            header.getContext()
                          )}
                      <div
                        {...{
                          onDoubleClick: () => header.column.resetSize(),
                          onMouseDown: header.getResizeHandler(),
                          onTouchStart: header.getResizeHandler(),
                          className: `resizer ${
                            table.options.columnResizeDirection
                          } ${
                            header.column.getIsResizing() ? 'isResizing' : ''
                          }`,
                          style: {
                            transform:
                              columnResizeMode === 'onEnd' &&
                              header.column.getIsResizing()
                                ? `translateX(${
                                    (table.options.columnResizeDirection ===
                                    'rtl'
                                      ? -1
                                      : 1) *
                                    (table.getState().columnSizingInfo
                                      .deltaOffset ?? 0)
                                  }px)`
                                : '',
                          },
                        }}
                      />
                    </div>
                  ))}
                </div>
              ))}
            </div>
            <div
              {...{
                className: 'tbody',
              }}
            >
              {table.getRowModel().rows.map(row => (
                <div
                  {...{
                    key: row.id,
                    className: 'tr',
                    style: {
                      position: 'relative',
                    },
                  }}
                >
                  {row.getVisibleCells().map(cell => (
                    <div
                      {...{
                        key: cell.id,
                        className: 'td',
                        style: {
                          position: 'absolute',
                          left: cell.column.getStart(),
                          width: cell.column.getSize(),
                        },
                      }}
                    >
                      {flexRender(
                        cell.column.columnDef.cell,
                        cell.getContext()
                      )}
                    </div>
                  ))}
                </div>
              ))}
            </div>
          </div>
        </div>
      </div>
      <div className="h-4" />
      <button onClick={() => rerender()} className="border p-2">
        Rerender
      </button>
      <pre>
        {JSON.stringify(
          {
            columnSizing: table.getState().columnSizing,
            columnSizingInfo: table.getState().columnSizingInfo,
          },
          null,
          2
        )}
      </pre>
    </div>
  )
}

const rootElement = document.getElementById('root')
if (!rootElement) throw new Error('Failed to find the root element')

ReactDOM.createRoot(rootElement).render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
)


import React from 'react'
import ReactDOM from 'react-dom/client'

import './index.css'

import {
  useReactTable,
  ColumnResizeMode,
  getCoreRowModel,
  ColumnDef,
  flexRender,
  ColumnResizeDirection,
} from '@tanstack/react-table'

type Person = {
  firstName: string
  lastName: string
  age: number
  visits: number
  status: string
  progress: number
}

const defaultData: Person[] = [\
  {\
    firstName: 'tanner',\
    lastName: 'linsley',\
    age: 24,\
    visits: 100,\
    status: 'In Relationship',\
    progress: 50,\
  },\
  {\
    firstName: 'tandy',\
    lastName: 'miller',\
    age: 40,\
    visits: 40,\
    status: 'Single',\
    progress: 80,\
  },\
  {\
    firstName: 'joe',\
    lastName: 'dirte',\
    age: 45,\
    visits: 20,\
    status: 'Complicated',\
    progress: 10,\
  },\
]

const defaultColumns: ColumnDef<Person>[] = [\
  {\
    header: 'Name',\
    footer: props => props.column.id,\
    columns: [\
      {\
        accessorKey: 'firstName',\
        cell: info => info.getValue(),\
        footer: props => props.column.id,\
      },\
      {\
        accessorFn: row => row.lastName,\
        id: 'lastName',\
        cell: info => info.getValue(),\
        header: () => <span>Last Name</span>,\
        footer: props => props.column.id,\
      },\
    ],\
  },\
  {\
    header: 'Info',\
    footer: props => props.column.id,\
    columns: [\
      {\
        accessorKey: 'age',\
        header: () => 'Age',\
        footer: props => props.column.id,\
      },\
      {\
        header: 'More Info',\
        columns: [\
          {\
            accessorKey: 'visits',\
            header: () => <span>Visits</span>,\
            footer: props => props.column.id,\
          },\
          {\
            accessorKey: 'status',\
            header: 'Status',\
            footer: props => props.column.id,\
          },\
          {\
            accessorKey: 'progress',\
            header: 'Profile Progress',\
            footer: props => props.column.id,\
          },\
        ],\
      },\
    ],\
  },\
]

function App() {
  const [data] = React.useState(() => [...defaultData])
  const [columns] = React.useState<typeof defaultColumns>(() => [\
    ...defaultColumns,\
  ])

  const [columnResizeMode, setColumnResizeMode] =
    React.useState<ColumnResizeMode>('onChange')

  const [columnResizeDirection, setColumnResizeDirection] =
    React.useState<ColumnResizeDirection>('ltr')

  const rerender = React.useReducer(() => ({}), {})[1]

  const table = useReactTable({
    data,
    columns,
    columnResizeMode,
    columnResizeDirection,
    getCoreRowModel: getCoreRowModel(),
    debugTable: true,
    debugHeaders: true,
    debugColumns: true,
  })

  return (
    <div className="p-2">
      <select
        value={columnResizeMode}
        onChange={e => setColumnResizeMode(e.target.value as ColumnResizeMode)}
        className="border p-2 border-black rounded"
      >
        <option value="onEnd">Resize: "onEnd"</option>
        <option value="onChange">Resize: "onChange"</option>
      </select>
      <select
        value={columnResizeDirection}
        onChange={e =>
          setColumnResizeDirection(e.target.value as ColumnResizeDirection)
        }
        className="border p-2 border-black rounded"
      >
        <option value="ltr">Resize Direction: "ltr"</option>
        <option value="rtl">Resize Direction: "rtl"</option>
      </select>
      <div style={{ direction: table.options.columnResizeDirection }}>
        <div className="h-4" />
        <div className="text-xl">{'<table/>'}</div>
        <div className="overflow-x-auto">
          <table
            {...{
              style: {
                width: table.getCenterTotalSize(),
              },
            }}
          >
            <thead>
              {table.getHeaderGroups().map(headerGroup => (
                <tr key={headerGroup.id}>
                  {headerGroup.headers.map(header => (
                    <th
                      {...{
                        key: header.id,
                        colSpan: header.colSpan,
                        style: {
                          width: header.getSize(),
                        },
                      }}
                    >
                      {header.isPlaceholder
                        ? null
                        : flexRender(
                            header.column.columnDef.header,
                            header.getContext()
                          )}
                      <div
                        {...{
                          onDoubleClick: () => header.column.resetSize(),
                          onMouseDown: header.getResizeHandler(),
                          onTouchStart: header.getResizeHandler(),
                          className: `resizer ${
                            table.options.columnResizeDirection
                          } ${
                            header.column.getIsResizing() ? 'isResizing' : ''
                          }`,
                          style: {
                            transform:
                              columnResizeMode === 'onEnd' &&
                              header.column.getIsResizing()
                                ? `translateX(${
                                    (table.options.columnResizeDirection ===
                                    'rtl'
                                      ? -1
                                      : 1) *
                                    (table.getState().columnSizingInfo
                                      .deltaOffset ?? 0)
                                  }px)`
                                : '',
                          },
                        }}
                      />
                    </th>
                  ))}
                </tr>
              ))}
            </thead>
            <tbody>
              {table.getRowModel().rows.map(row => (
                <tr key={row.id}>
                  {row.getVisibleCells().map(cell => (
                    <td
                      {...{
                        key: cell.id,
                        style: {
                          width: cell.column.getSize(),
                        },
                      }}
                    >
                      {flexRender(
                        cell.column.columnDef.cell,
                        cell.getContext()
                      )}
                    </td>
                  ))}
                </tr>
              ))}
            </tbody>
          </table>
        </div>
        <div className="h-4" />
        <div className="text-xl">{'<div/> (relative)'}</div>
        <div className="overflow-x-auto">
          <div
            {...{
              className: 'divTable',
              style: {
                width: table.getTotalSize(),
              },
            }}
          >
            <div className="thead">
              {table.getHeaderGroups().map(headerGroup => (
                <div
                  {...{
                    key: headerGroup.id,
                    className: 'tr',
                  }}
                >
                  {headerGroup.headers.map(header => (
                    <div
                      {...{
                        key: header.id,
                        className: 'th',
                        style: {
                          width: header.getSize(),
                        },
                      }}
                    >
                      {header.isPlaceholder
                        ? null
                        : flexRender(
                            header.column.columnDef.header,
                            header.getContext()
                          )}
                      <div
                        {...{
                          onDoubleClick: () => header.column.resetSize(),
                          onMouseDown: header.getResizeHandler(),
                          onTouchStart: header.getResizeHandler(),
                          className: `resizer ${
                            table.options.columnResizeDirection
                          } ${
                            header.column.getIsResizing() ? 'isResizing' : ''
                          }`,
                          style: {
                            transform:
                              columnResizeMode === 'onEnd' &&
                              header.column.getIsResizing()
                                ? `translateX(${
                                    (table.options.columnResizeDirection ===
                                    'rtl'
                                      ? -1
                                      : 1) *
                                    (table.getState().columnSizingInfo
                                      .deltaOffset ?? 0)
                                  }px)`
                                : '',
                          },
                        }}
                      />
                    </div>
                  ))}
                </div>
              ))}
            </div>
            <div
              {...{
                className: 'tbody',
              }}
            >
              {table.getRowModel().rows.map(row => (
                <div
                  {...{
                    key: row.id,
                    className: 'tr',
                  }}
                >
                  {row.getVisibleCells().map(cell => (
                    <div
                      {...{
                        key: cell.id,
                        className: 'td',
                        style: {
                          width: cell.column.getSize(),
                        },
                      }}
                    >
                      {flexRender(
                        cell.column.columnDef.cell,
                        cell.getContext()
                      )}
                    </div>
                  ))}
                </div>
              ))}
            </div>
          </div>
        </div>
        <div className="h-4" />
        <div className="text-xl">{'<div/> (absolute positioning)'}</div>
        <div className="overflow-x-auto">
          <div
            {...{
              className: 'divTable',
              style: {
                width: table.getTotalSize(),
              },
            }}
          >
            <div className="thead">
              {table.getHeaderGroups().map(headerGroup => (
                <div
                  {...{
                    key: headerGroup.id,
                    className: 'tr',
                    style: {
                      position: 'relative',
                    },
                  }}
                >
                  {headerGroup.headers.map(header => (
                    <div
                      {...{
                        key: header.id,
                        className: 'th',
                        style: {
                          position: 'absolute',
                          left: header.getStart(),
                          width: header.getSize(),
                        },
                      }}
                    >
                      {header.isPlaceholder
                        ? null
                        : flexRender(
                            header.column.columnDef.header,
                            header.getContext()
                          )}
                      <div
                        {...{
                          onDoubleClick: () => header.column.resetSize(),
                          onMouseDown: header.getResizeHandler(),
                          onTouchStart: header.getResizeHandler(),
                          className: `resizer ${
                            table.options.columnResizeDirection
                          } ${
                            header.column.getIsResizing() ? 'isResizing' : ''
                          }`,
                          style: {
                            transform:
                              columnResizeMode === 'onEnd' &&
                              header.column.getIsResizing()
                                ? `translateX(${
                                    (table.options.columnResizeDirection ===
                                    'rtl'
                                      ? -1
                                      : 1) *
                                    (table.getState().columnSizingInfo
                                      .deltaOffset ?? 0)
                                  }px)`
                                : '',
                          },
                        }}
                      />
                    </div>
                  ))}
                </div>
              ))}
            </div>
            <div
              {...{
                className: 'tbody',
              }}
            >
              {table.getRowModel().rows.map(row => (
                <div
                  {...{
                    key: row.id,
                    className: 'tr',
                    style: {
                      position: 'relative',
                    },
                  }}
                >
                  {row.getVisibleCells().map(cell => (
                    <div
                      {...{
                        key: cell.id,
                        className: 'td',
                        style: {
                          position: 'absolute',
                          left: cell.column.getStart(),
                          width: cell.column.getSize(),
                        },
                      }}
                    >
                      {flexRender(
                        cell.column.columnDef.cell,
                        cell.getContext()
                      )}
                    </div>
                  ))}
                </div>
              ))}
            </div>
          </div>
        </div>
      </div>
      <div className="h-4" />
      <button onClick={() => rerender()} className="border p-2">
        Rerender
      </button>
      <pre>
        {JSON.stringify(
          {
            columnSizing: table.getState().columnSizing,
            columnSizingInfo: table.getState().columnSizingInfo,
          },
          null,
          2
        )}
      </pre>
    </div>
  )
}

const rootElement = document.getElementById('root')
if (!rootElement) throw new Error('Failed to find the root element')

ReactDOM.createRoot(rootElement).render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
)

Sticky Column Pinning

Performant Column Resizing

Partners Become a Partner

Code RabbitCode Rabbit CloudflareCloudflare AG GridAG Grid NetlifyNetlify NeonNeon WorkOSWorkOS ClerkClerk ConvexConvex ElectricElectric SentrySentry PrismaPrisma StrapiStrapi UnkeyUnkey

scarf analytics