布局
传统表格布局的问题
传统表格以响应性差而著称。在移动端,渲染横向较长的内容时,可用的灵活性相当有限:
- 允许用户水平滚动以查看更多表格内容
- 在较小设备上隐藏不重要的列
这两点在 Filament 中都可以实现。表格溢出时会自动水平滚动,你也可以根据浏览器的响应式 breakpoint 选择显示和隐藏列。为此,可以使用 visibleFrom() 或 hiddenFrom() 方法:
use Filament\Tables\Columns\TextColumn;
TextColumn::make('slug')
->visibleFrom('md')这样可以,但仍有一个明显问题——在移动端,用户若不滚动,一次只能在表格行中看到很少信息。
Filament 提供两种解决方案:
- **简单堆叠** - 使用 `stackedOnMobile()` 在移动端自动垂直堆叠所有单元格,无需更改列定义
- **自定义布局** - 使用 `Split`、`Stack` 及其他布局组件,精细控制内容在各断点的呈现方式
在移动端堆叠表格单元格
让表格响应式的最简单方式是在表格上使用 stackedOnMobile() 方法。这会在移动屏幕上将传统水平表格布局自动转换为垂直卡片式布局,同时在较大屏幕上保留标准表格外观:
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Table;
public function table(Table $table): Table
{
return $table
->columns([
TextColumn::make('name')
->searchable()
->sortable(),
TextColumn::make('email'),
TextColumn::make('phone'),
TextColumn::make('job'),
])
->stackedOnMobile();
}



在移动端,每行显示为卡片,列标签位于其值上方。若有可排序列,移动端表格顶部会出现排序下拉框,让用户无需传统表头即可排序。也支持批量选择,复选框会出现在页眉区域。
当你希望快速实现响应式且无需重构列时,此方法很合适。不过,对于更复杂的布局,或需精细控制内容在不同断点的呈现方式时,你可能更想使用下文所述的布局组件。
自定义列布局
Filament 让你无需改动 HTML 或 CSS 即可构建响应式类表格界面。这些布局让你精确指定内容在表格行中、在每个响应式断点上出现的位置。




允许列在移动端堆叠
我们来介绍一个组件——Split:
use Filament\Support\Enums\FontWeight;
use Filament\Tables\Columns\Layout\Split;
use Filament\Tables\Columns\TextColumn;
Split::make([
ImageColumn::make('avatar')
->circular(),
TextColumn::make('name')
->weight(FontWeight::Bold)
->searchable()
->sortable(),
TextColumn::make('email'),
])



Split 组件用于包裹列,并允许它们在移动端堆叠。
默认情况下,split 内的列会始终并排显示。不过,你可以选择该行为从哪个响应式 breakpoint 开始 from()。在此之前,列会上下堆叠:
use Filament\Support\Enums\FontWeight;
use Filament\Tables\Columns\Layout\Split;
use Filament\Tables\Columns\ImageColumn;
use Filament\Tables\Columns\TextColumn;
Split::make([
ImageColumn::make('avatar')
->circular(),
TextColumn::make('name')
->weight(FontWeight::Bold)
->searchable()
->sortable(),
TextColumn::make('email'),
])->from('md')在本例中,列仅从 md breakpoint 设备起水平并排显示:




阻止列产生空白
Split 与表格列一样,会自动调整空白以确保每列有适当间距。你可以使用 grow(false) 阻止此行为。在本例中,我们确保头像图片紧贴姓名列:
use Filament\Support\Enums\FontWeight;
use Filament\Tables\Columns\Layout\Split;
use Filament\Tables\Columns\ImageColumn;
use Filament\Tables\Columns\TextColumn;
Split::make([
ImageColumn::make('avatar')
->circular()
->grow(false),
TextColumn::make('name')
->weight(FontWeight::Bold)
->searchable()
->sortable(),
TextColumn::make('email'),
])允许 grow() 的其他列会调整以占用新腾出的空间:




在 Split 内堆叠
在 split 内,你可以将多列垂直堆叠。这让你能在桌面端用更少的列显示更多数据:
use Filament\Support\Enums\FontWeight;
use Filament\Tables\Columns\Layout\Split;
use Filament\Tables\Columns\Layout\Stack;
use Filament\Tables\Columns\ImageColumn;
use Filament\Tables\Columns\TextColumn;
Split::make([
ImageColumn::make('avatar')
->circular(),
TextColumn::make('name')
->weight(FontWeight::Bold)
->searchable()
->sortable(),
Stack::make([
TextColumn::make('phone')
->icon('heroicon-m-phone'),
TextColumn::make('email')
->icon('heroicon-m-envelope'),
]),
])



在移动端隐藏 Stack
与单独的列类似,你可以根据浏览器的响应式 breakpoint 选择隐藏 stack。为此,可以使用 visibleFrom() 方法:
use Filament\Support\Enums\FontWeight;
use Filament\Tables\Columns\Layout\Split;
use Filament\Tables\Columns\Layout\Stack;
use Filament\Tables\Columns\ImageColumn;
use Filament\Tables\Columns\TextColumn;
Split::make([
ImageColumn::make('avatar')
->circular(),
TextColumn::make('name')
->weight(FontWeight::Bold)
->searchable()
->sortable(),
Stack::make([
TextColumn::make('phone')
->icon('heroicon-m-phone'),
TextColumn::make('email')
->icon('heroicon-m-envelope'),
])->visibleFrom('md'),
])



对齐堆叠内容
默认情况下,stack 内的列对齐到起始端。你也可以选择将 stack 内的列对齐到 Alignment::Center 或 Alignment::End:
use Filament\Support\Enums\Alignment;
use Filament\Support\Enums\FontWeight;
use Filament\Tables\Columns\Layout\Split;
use Filament\Tables\Columns\Layout\Stack;
use Filament\Tables\Columns\ImageColumn;
use Filament\Tables\Columns\TextColumn;
Split::make([
ImageColumn::make('avatar')
->circular(),
TextColumn::make('name')
->weight(FontWeight::Bold)
->searchable()
->sortable(),
Stack::make([
TextColumn::make('phone')
->icon('heroicon-m-phone')
->grow(false),
TextColumn::make('email')
->icon('heroicon-m-envelope')
->grow(false),
])
->alignment(Alignment::End)
->visibleFrom('md'),
])确保 stack 内的列设置了 grow(false),否则它们会拉伸以填满 stack 的整个宽度,并遵循各自的对齐配置而非 stack 的对齐。


堆叠内容间距
默认情况下,堆叠内容的列之间没有垂直内边距。要添加间距,可以使用 space() 方法,接受 1、2 或 3,对应 Tailwind 的间距比例:
use Filament\Tables\Columns\Layout\Stack;
use Filament\Tables\Columns\TextColumn;
Stack::make([
TextColumn::make('phone')
->icon('heroicon-m-phone'),
TextColumn::make('email')
->icon('heroicon-m-envelope'),
])->space(1)

使用网格控制列宽
有时,当列包含大量内容时,使用 Split 会产生不一致的宽度。这是因为它内部由 Flexbox 驱动,每行单独控制分配给内容的空间。
相反,你可以使用 Grid 布局,它使用 CSS Grid Layout,让你控制列宽:
use Filament\Tables\Columns\Layout\Grid;
use Filament\Tables\Columns\TextColumn;
Grid::make([
'lg' => 2,
])
->schema([
TextColumn::make('phone')
->icon('heroicon-m-phone'),
TextColumn::make('email')
->icon('heroicon-m-envelope'),
])从 lg breakpoint 起,这些列在网格中始终占用相等宽度。


你也可以在其他断点自定义网格内的列数:
use Filament\Tables\Columns\Layout\Grid;
use Filament\Tables\Columns\Layout\Stack;
use Filament\Tables\Columns\TextColumn;
Grid::make([
'lg' => 2,
'2xl' => 4,
])
->schema([
Stack::make([
TextColumn::make('name'),
TextColumn::make('job'),
]),
TextColumn::make('phone')
->icon('heroicon-m-phone'),
TextColumn::make('email')
->icon('heroicon-m-envelope'),
])你甚至可以控制每个组件在各 breakpoint 占用多少网格列:
use Filament\Tables\Columns\Layout\Grid;
use Filament\Tables\Columns\Layout\Stack;
use Filament\Tables\Columns\TextColumn;
Grid::make([
'lg' => 2,
'2xl' => 5,
])
->schema([
Stack::make([
TextColumn::make('name'),
TextColumn::make('job'),
])->columnSpan([
'lg' => 'full',
'2xl' => 2,
]),
TextColumn::make('phone')
->icon('heroicon-m-phone')
->columnSpan([
'2xl' => 2,
]),
TextColumn::make('email')
->icon('heroicon-m-envelope'),
])可折叠内容
使用 split 或 stack 等列布局时,你还可以添加可折叠内容。当你不想一次在表格中显示全部数据,但仍希望用户在需要时无需离开即可访问时,这非常有用。
Split 和 stack 组件可以设为 collapsible(),此外还有专用的 Panel 组件,提供预设样式的背景色和圆角,以将可折叠内容与其余部分分隔开:
use Filament\Support\Enums\FontWeight;
use Filament\Tables\Columns\Layout\Panel;
use Filament\Tables\Columns\Layout\Split;
use Filament\Tables\Columns\Layout\Stack;
use Filament\Tables\Columns\ImageColumn;
use Filament\Tables\Columns\TextColumn;
[
Split::make([
ImageColumn::make('avatar')
->circular(),
TextColumn::make('name')
->weight(FontWeight::Bold)
->searchable()
->sortable(),
]),
Panel::make([
Stack::make([
TextColumn::make('phone')
->icon('heroicon-m-phone'),
TextColumn::make('email')
->icon('heroicon-m-envelope'),
]),
])->collapsible(),
]你可以使用 collapsed(false) 方法默认展开面板:
use Filament\Tables\Columns\Layout\Panel;
use Filament\Tables\Columns\Layout\Split;
use Filament\Tables\Columns\TextColumn;
Panel::make([
Split::make([
TextColumn::make('phone')
->icon('heroicon-m-phone'),
TextColumn::make('email')
->icon('heroicon-m-envelope'),
])->from('md'),
])->collapsed(false)



将记录排列为网格
有时你会发现数据更适合网格格式而非列表。Filament 也能处理!
只需使用 $table->contentGrid() 方法:
use Filament\Tables\Columns\Layout\Stack;
use Filament\Tables\Table;
public function table(Table $table): Table
{
return $table
->columns([
Stack::make([
// Columns
]),
])
->contentGrid([
'md' => 2,
'xl' => 3,
]);
}在本例中,行会以网格显示:
- 在移动端,仅显示为 1 列。
- 从 `md` [breakpoint](https://tailwindcss.com/docs/responsive-design#overview) 起,显示为 2 列。
- 从 `xl` [breakpoint](https://tailwindcss.com/docs/responsive-design#overview) 起,显示为 3 列。
这些设置完全可自定义,从 sm 到 2xl 的任意 breakpoint 都可以包含 1 到 12 列。




自定义 HTML
你可以使用 View 组件向表格添加自定义 HTML。它甚至可以是 collapsible():
use Filament\Support\Enums\FontWeight;
use Filament\Tables\Columns\Layout\Split;
use Filament\Tables\Columns\Layout\View;
use Filament\Tables\Columns\ImageColumn;
use Filament\Tables\Columns\TextColumn;
[
Split::make([
ImageColumn::make('avatar')
->circular(),
TextColumn::make('name')
->weight(FontWeight::Bold)
->searchable()
->sortable(),
]),
View::make('users.table.collapsible-row-content')
->collapsible(),
]现在,创建 /resources/views/users/table/collapsible-row-content.blade.php 文件并加入你的 HTML。你可以使用 $getRecord() 访问表格记录:
<p class="px-4 py-3 bg-gray-100 rounded-lg">
<span class="font-medium">
Email address:
</span>
<span>
{{ $getRecord()->email }}
</span>
</p>嵌入其他组件
你甚至可以将列或其他布局组件传给 components() 方法:
use Filament\Support\Enums\FontWeight;
use Filament\Tables\Columns\Layout\Split;
use Filament\Tables\Columns\Layout\View;
use Filament\Tables\Columns\ImageColumn;
use Filament\Tables\Columns\TextColumn;
[
Split::make([
ImageColumn::make('avatar')
->circular(),
TextColumn::make('name')
->weight(FontWeight::Bold)
->searchable()
->sortable(),
]),
View::make('users.table.collapsible-row-content')
->components([
TextColumn::make('email')
->icon('heroicon-m-envelope'),
])
->collapsible(),
]现在,在 Blade 文件中渲染这些组件:
<div class="px-4 py-3 bg-gray-100 rounded-lg">
@foreach ($getComponents() as $layoutComponent)
{{ $layoutComponent
->record($getRecord())
->recordKey($getRecordKey())
->rowLoop($getRowLoop())
->renderInLayout() }}
@endforeach
</div>