Column Pinning

Freeze columns to the left or right edge of the table so they remain visible during horizontal scrolling.

How to Enable

const table = useTable({
  data,
  columns,
  enableColumnPinning: true,
  initialState: {
    columnPinning: {
      left: ['name'],
      right: ['actions'],
    },
  },
})

Column Option

columnHelper.accessor('name', {
  header: 'Name',
  enablePinning: true,
})

Programmatic Control

// Pin a column to the left
table.getColumn('name')?.pin('left')

// Pin to the right
table.getColumn('actions')?.pin('right')

// Unpin
table.getColumn('name')?.pin(false)

// Check pin status
table.getColumn('name')?.getIsPinned() // 'left' | 'right' | false

// Set all pinning at once
table.setColumnPinning({ left: ['name', 'id'], right: ['actions'] })

// Check if any columns are pinned
table.getIsSomeColumnsPinned('left') // boolean

With Row Virtualization

Pinned columns stay frozen to the viewport edges under enableVirtualization too. The virtualized grid renders inside a single scroll container that holds both the header and the body, so pinned header and body cells share one sticky context and move together during horizontal scroll. The horizontal scrollbar sits at the bottom of the virtualViewportHeight viewport, so it is reachable without scrolling to the last row.