Fix: Transparent Header Cells on Horizontal Scroll with TanStack Table + TanStack Virtual

The Problem
When using TanStack Table with TanStack Virtual and many columns that extend beyond the viewport, scrolling horizontally causes the header cells to appear transparent. Body row content bleeds through behind the sticky header as you scroll right.
This happens even though the header row itself has bg-background.
Why It Happens
In a typical virtualized data grid setup, the structure looks like this:
<div role="rowgroup" class="sticky top-0 z-10 grid"> <!-- header rowgroup -->
<div role="row" class="bg-background flex min-w-full"> <!-- header row -->
<div role="columnheader" class="relative shrink-0"> <!-- header cell (no bg!) -->
The header row has bg-background, but individual header cells only get bg-background conditionally — typically when header.column.getIsPinned() is true. Non-pinned header cells have no background.
When columns extend past the viewport width, the row's background doesn't fully cover all cells in certain rendering scenarios. The sticky positioning combined with min-w-full on the row and shrink-0 on cells creates a situation where the background doesn't paint behind overflow cells.
The Fix
Two changes, both in the data grid component where headers are rendered:
1. Add bg-background to the header rowgroup
<div
role="rowgroup"
data-slot="grid-header"
ref={headerRef}
- className="sticky top-0 z-10 grid"
+ className="bg-background sticky top-0 z-10 grid"
>
2. Give all header cells bg-background, not just pinned ones
<div
role="columnheader"
- className={cn('relative shrink-0', {
+ className={cn('bg-background relative shrink-0', {
grow: stretchColumns && header.column.id !== 'select' && header.column.id !== 'actions',
- 'bg-background': header.column.getIsPinned(),
})}
>
The pinned-only conditional was the root cause. Every header cell needs an opaque background so nothing bleeds through when scrolling horizontally — not just the ones pinned to the left/right edge.





