表格
布局
传统表格布局的问题
传统的表格因响应性差而臭名昭著。在移动端上,渲染水平方向较长的内容时,灵活性有限:
- 允许用户水平滚动以查看更多表格内容
- 在较小的设备上隐藏不重要的列
这两中在 Filament 中都能实现。当表溢出时,它们会自动水平滚动,你可以选择根据浏览器的响应断点显示和隐藏列。为此,你可以使用 visibleFrom()
或 hiddenFrom()
方法:
use Filament\Tables\Columns\TextColumn;
TextColumn::make('slug')
->visibleFrom('md')
这很好,但仍然存在一个明显的问题 —— 在移动设备上,用户如果不滚动,就无法一次看到表格行中的很多信息。
值得庆幸的是,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
中的列将始终并排显示。但是你可以选择一个该行为开始(form()
)的响应式断点。在此之前,列将堆叠在一起:
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
断点以上的设备中水平并排展示:


防止列创建空格
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'),
]),
])


在移动设备上隐藏堆叠
与单个列类似,你可以根据浏览器的响应式断点选择隐藏堆叠。为此,你可以使用 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'),
])


对齐堆叠内容
默认情况下,堆叠中的列对齐到起始位置。你可以选择将堆叠中的列对齐到 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'),
])
请确保堆栈内的列已设置 grow(false)
,否则它们将拉伸以填充堆栈的整个宽度并遵循它们自己的对齐配置而不是堆栈的对齐配置。

Spacing stacked content
By default, stacked content has no vertical padding between columns. To add some, you may use the space()
method, which accepts either 1
, 2
, or 3
, corresponding to Tailwind’s spacing scale:
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)
Controlling column width using a grid
Sometimes, using a Split
creates inconsistent widths when columns contain lots of content. This is because it’s powered by Flexbox internally and each row individually controls how much space is allocated to content.
Instead, you may use a Grid
layout, which uses CSS Grid Layout to allow you to control column widths:
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'),
])
These columns will always consume equal width within the grid, from the lg
breakpoint.
You may choose to customize the number of columns within the grid at other breakpoints:
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'),
])
And you can even control how many grid columns will be consumed by each component at each 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'),
])
Collapsible content
When you’re using a column layout like split or stack, then you can also add collapsible content. This is very useful for when you don’t want to display all data in the table at once, but still want it to be accessible to the user if they need to access it, without navigating away.
Split and stack components can be made collapsible()
, but there is also a dedicated Panel
component that provides a pre-styled background color and border radius, to separate the collapsible content from the rest:
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(),
]
You can expand a panel by default using the collapsed(false)
method:
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)


Arranging records into a grid
Sometimes, you may find that your data fits into a grid format better than a list. Filament can handle that too!
Simply use the $table->contentGrid()
method:
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,
]);
}
In this example, the rows will be displayed in a grid:
- On mobile, they will be displayed in 1 column only.
- From the
md
breakpoint, they will be displayed in 2 columns. - From the
xl
breakpoint onwards, they will be displayed in 3 columns.
These settings are fully customizable, any breakpoint from sm
to 2xl
can contain 1
to 12
columns.


Custom HTML
You may add custom HTML to your table using a View
component. It can even be 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(),
]
Now, create a /resources/views/users/table/collapsible-row-content.blade.php
file, and add in your HTML. You can access the table record using $getRecord()
:
<p class="px-4 py-3 bg-gray-100 rounded-lg">
<span class="font-medium">
Email address:
</span>
<span>
{{ $getRecord()->email }}
</span>
</p>
Embedding other components
You could even pass in columns or other layout components to the components()
method:
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(),
]
Now, render the components in the Blade file:
<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>
Edit on GitHubStill need help? Join our Discord community or open a GitHub discussion