zeeshantariq/filament-sticky-columns
Add sticky (frozen) columns to Filament tables (v3–v5). Pin one or more columns left or right with automatic offsets, dark-mode friendly styling, and scroll shadows. Use the StickyColumn drop-in or call ->sticky() on any column.
Sticky (frozen) table columns for Filament v3, v4, and v5.
Pin one or more columns to the left or right edge while the rest of the table scrolls horizontally — just like Excel or Google Sheets.
StickyColumn drop-in, or add stickiness to any column using ->sticky()| Dependency | Version |
|---|---|
| PHP | ≥ 8.1 |
| Laravel | ≥ 10 |
| Filament | ^3.0 || ^4.0 || ^5.0 |
composer require zeeshantariq/filament-sticky-columns
filament:assets, no hard refreshIf your Filament panel uses a Vite theme (->viteTheme(...)), import the package CSS/JS into your theme build.
This gives you automatic cache-busting (hashed filenames) and avoids running php artisan filament:assets.
Add to your Filament theme CSS (example: resources/css/filament/admin/theme.css):
@import "../../../../vendor/zeeshantariq/filament-sticky-columns/resources/css/filament-sticky-columns.css";
Import the JS in a file that is loaded by your panel (example: a Filament theme JS entry, or your panel JS bundle):
import '../../../../vendor/zeeshantariq/filament-sticky-columns/resources/js/filament-sticky-columns.js'
Then rebuild your assets:
npm run dev
# or
npm run build
php artisan vendor:publish --tag="filament-sticky-columns-config"
This package also registers JS/CSS via Filament assets.
Filament v3/v4 publish all registered assets with this command:
php artisan filament:assets
Cache busting (no hard refresh): asset filenames include your installed package version and the built files’ last-modified time, so after composer update or a fresh install, run php artisan filament:assets (or rely on filament:upgrade in your app’s Composer scripts) and do a normal page reload — the browser should request new CSS/JS URLs automatically.
StickyColumn drop-inStickyColumn is a drop-in replacement for Filament’s TextColumn. It is sticky left by default.
use Filament\Tables\Table;
use Filament\Tables\Columns\TextColumn;
use ZeeshanTariq\FilamentStickyColumns\Columns\StickyColumn;
public function table(Table $table): Table
{
return $table->columns([
// Sticky LEFT (default)
StickyColumn::make('id')->sortable(),
StickyColumn::make('name')->searchable(),
// Regular scrollable columns
TextColumn::make('email'),
TextColumn::make('phone'),
TextColumn::make('department'),
// Sticky RIGHT
StickyColumn::make('status')->right()->badge(),
]);
}
->sticky() / ->stickyRight()This package registers macros on Filament\Tables\Columns\Column, so you can pin any column type without switching to StickyColumn.
use Filament\Tables\Table;
use Filament\Tables\Columns\IconColumn;
use Filament\Tables\Columns\ImageColumn;
use Filament\Tables\Columns\TextColumn;
public function table(Table $table): Table
{
return $table->columns([
TextColumn::make('id')->label('ID')->sticky(),
ImageColumn::make('avatar')->circular()->sticky(),
TextColumn::make('name')->searchable()->sticky(),
TextColumn::make('email'),
TextColumn::make('phone'),
IconColumn::make('active')->boolean()->stickyRight(),
]);
}
When auto-compute isn't accurate (e.g. beside a checkbox column):
StickyColumn::make('id')->sticky(offset: 0), // starts at 0
StickyColumn::make('name')->sticky(offset: 60), // after a 60 px ID column
StickyColumnStickyColumn::make('name') // sticky left
StickyColumn::make('name')->right() // sticky right
StickyColumn::make('name')->sticky() // sticky left (explicit)
StickyColumn::make('name')->stickyRight() // sticky right
StickyColumn::make('name')->sticky(offset: 120)
TextColumn::make('name')->sticky(condition: true, offset: null, zIndex: null)
TextColumn::make('actions')->stickyRight(condition: true, offset: null, zIndex: null)
// config/filament-sticky-columns.php
return [
'z_index' => 10, // z-index for sticky cells
'background' => 'auto', // 'auto' = Filament surface colour
'shadow' => true, // directional scroll shadow
'shadow_color' => 'rgba(0, 0, 0, 0.12)', // shadow CSS colour
];
If you dynamically add columns or swap table content outside of normal Livewire updates:
window.FilamentStickyColumns.refresh();
Checklist:
php artisan filament:assets
Filament v4 note (important):
extraHeaderAttributes() (<th>) and extraCellAttributes() (<td>).extraAttributes() is applied to inner column markup (e.g. TextColumn’s wrapper), which is not always enough for sticky positioning.data-sticky="left" / data-sticky="right" on the actual <th> / <td> elements in your table (not only on a nested <div>).If you use the Filament assets pipeline, refresh once after publishing.
If you use Vite (recommended), you should not need hard refresh because Vite cache-busts.
Inspect the table DOM and confirm your sticky columns have data-sticky="left" / data-sticky="right" somewhere inside the cell.
If you use selection/checkbox columns or very dynamic columns, auto offsets can be off. Use manual offsets:
TextColumn::make('id')->sticky(offset: 0)
TextColumn::make('name')->sticky(offset: 80)
See CHANGELOG.md.
MIT — see LICENSE.md.
How can I help you explore Laravel packages today?