Skip to content
全部文档

布局

简介

Filament 的网格系统允许你使用任意布局组件创建响应式多列布局。Filament 提供一组内置布局组件来帮助你构建:

你也可以 创建自己的自定义布局组件,按任意方式展示组件。

网格系统

所有布局组件都有 columns() 方法,可用几种不同方式使用:

  • 可传入整数,如 `columns(2)`。该整数是 `lg` 断点及以上使用的列数。更小的设备将只有 1 列。
  • 可传入数组,键为断点,值为列数。例如,`columns(['md' => 2, 'xl' => 4])` 会在中等设备上创建 2 列布局,在超大设备上创建 4 列布局。更小设备的默认断点使用 1 列,除非使用 `default` 数组键。

断点(smmdlgxl2xl)由 Tailwind 定义,详见 Tailwind 文档

TIP

除了接受静态值外,columns() 方法也接受函数以动态计算。你可以将各种工具作为参数注入该函数。

网格列跨度

除了指定布局组件应有多少列外,还可使用 columnSpan() 方法指定组件在父网格中应占多少列。该方法接受整数,或断点与列跨度的数组:

  • 可传入整数,如 `columnSpan(2)`。该整数是 `lg` 断点及以上占用的列数。更小的设备仅跨 1 列。
  • `columnSpan(['md' => 2, 'xl' => 4])` 会使组件在中等设备上最多占 2 列,在超大设备上最多占 4 列。更小设备的默认断点使用 1 列,除非使用 `default` 数组键。
  • `columnSpan('full')` 会使组件在 `lg` 断点及以上占满父网格全宽,无论有多少列。更小的设备仅跨 1 列。
  • `columnSpanFull()` 会使组件在所有设备上占满父网格全宽,无论有多少列。

TIP

除了接受静态值外,columnSpan() 方法也接受函数以动态计算。你可以将各种工具作为参数注入该函数。

带列跨度的网格带列跨度的网格

网格列起始位置

若希望组件在网格中从特定列开始,可使用 columnStart() 方法。该方法接受整数,或断点与起始列的数组:

  • 可传入整数,如 `columnStart(2)`。该整数是组件在 `lg` 断点及以上的起始列。更小的设备从第一列开始。
  • `columnStart(['md' => 2, 'xl' => 4])` 会使组件在中等设备上从第 2 列开始,在超大设备上从第 4 列开始。更小设备的默认断点使用 1 列,除非使用 `default` 数组键。
php
use Filament\Forms\Components\TextInput;
use Filament\Schemas\Components\Grid;

Grid::make()
    ->columns([
        'sm' => 3,
        'xl' => 6,
        '2xl' => 8,
    ])
    ->schema([
        TextInput::make('name')
            ->columnStart([
                'sm' => 2,
                'xl' => 3,
                '2xl' => 4,
            ]),
        // ...
    ])

本例中,网格在小设备上有 3 列,在超大设备上有 6 列,在超超大设备上有 8 列。文本输入在小设备上从第 2 列开始,在超大设备上从第 3 列开始,在超超大设备上从第 4 列开始。这本质上产生一种布局:无论网格有多少列,文本输入总是从网格中部开始。

TIP

除了接受静态值外,columnStart() 方法也接受函数以动态计算。你可以将各种工具作为参数注入该函数。

带列起始位置的网格带列起始位置的网格

网格列排序

若希望在不改变标记中位置的情况下控制网格中组件的视觉顺序,可使用 columnOrder() 方法。该方法接受整数、闭包,或断点与顺序值的数组:

  • 可传入整数,如 `columnOrder(2)`。该整数是组件在 `lg` 断点及以上的出现顺序。更小的设备使用默认顺序,除非使用 `default` 数组键。
  • `columnOrder(['md' => 2, 'xl' => 4])` 会将组件顺序在中等设备上设为 2,在超大设备上设为 4。更小设备的默认断点使用默认顺序,除非使用 `default` 数组键。
  • `columnOrder(fn () => 1)` 会使用闭包动态计算顺序。
php
use Filament\Forms\Components\TextInput;
use Filament\Schemas\Components\Grid;

Grid::make()
    ->columns(3)
    ->schema([
        TextInput::make('first')
            ->columnOrder(3), // This will appear last
        TextInput::make('second')
            ->columnOrder(1), // This will appear first
        TextInput::make('third')
            ->columnOrder(2), // This will appear second
    ])
重新排序列的网格重新排序列的网格

也可使用响应式排序,根据屏幕尺寸更改组件的视觉顺序:

php
use Filament\Forms\Components\TextInput;
use Filament\Schemas\Components\Grid;

Grid::make()
    ->columns([
        'sm' => 2,
        'lg' => 3,
    ])
    ->schema([
        TextInput::make('title')
            ->columnOrder([
                'default' => 1,
                'lg' => 3,
            ]),
        TextInput::make('description')
            ->columnOrder([
                'default' => 2,
                'lg' => 1,
            ]),
        TextInput::make('category')
            ->columnOrder([
                'default' => 3,
                'lg' => 2,
            ]),
    ])

本例中,小屏幕上的顺序为:title、description、category。大屏幕上的顺序为:description、category、title。

TIP

除了接受静态值外,columnOrder() 方法也接受函数以动态计算。你可以将各种工具作为参数注入该函数。

响应式网格布局示例

本例中,我们有一个带 分区 布局组件的 schema。由于所有布局组件都支持 columns() 方法,可用它在分区本身内创建响应式网格布局。

我们向 columns() 传入数组,因为要为不同断点指定不同列数。小于 sm Tailwind 断点 的设备使用默认的 1 列。大于 sm 断点的设备使用 3 列。大于 xl 断点的设备使用 6 列。大于 2xl 断点的设备使用 8 列。

分区内有一个 文本输入。由于文本输入是表单字段且所有组件都有 columnSpan() 方法,可用它指定文本输入应占多少列。小于 sm 断点的设备使用默认的 1 列。大于 sm 断点占 2 列,大于 xl 断点占 3 列,大于 2xl 断点占 4 列。

此外,我们使用 columnOrder() 方法根据屏幕尺寸控制网格中组件的视觉顺序。这样可不改标记结构就更改显示顺序。

php
use Filament\Forms\Components\TextInput;
use Filament\Schemas\Components\Section;

Section::make()
    ->columns([
        'sm' => 3,
        'xl' => 6,
        '2xl' => 8,
    ])
    ->schema([
        TextInput::make('name')
            ->columnSpan([
                'default' => 1,
                'sm' => 2,
                'xl' => 3,
                '2xl' => 4,
            ])
            ->columnOrder([
                'default' => 2,
                'xl' => 1,
            ]),
        TextInput::make('email')
            ->columnSpan([
                'default' => 1,
                'xl' => 2,
            ])
            ->columnOrder([
                'default' => 1,
                'xl' => 2,
            ]),
        // ...
    ])

本例中,小于 xl 断点的屏幕上,email 字段先出现,然后是 name 字段。大于 xl 断点的屏幕上顺序相反:name 字段先出现,然后是 email 字段。

基础布局组件

Grid 组件

所有布局组件都支持 columns() 方法,此外还可使用 Grid 组件。若希望 schema 使用无额外样式的显式网格语法,它会很有用。可不使用 columns() 方法,而将列配置直接传给 Grid::make()

php
use Filament\Schemas\Components\Grid;

Grid::make([
    'default' => 1,
    'sm' => 2,
    'md' => 3,
    'lg' => 4,
    'xl' => 6,
    '2xl' => 8,
])
    ->schema([
        // ...
    ])
网格网格

Flex 组件

Flex 组件允许你使用 flexbox 定义弹性宽度布局。该组件不使用 Filament 的 网格系统

php
use Filament\Forms\Components\Textarea;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\Toggle;
use Filament\Schemas\Components\Section;
use Filament\Schemas\Components\Flex;

Flex::make([
    Section::make([
        TextInput::make('title'),
        Textarea::make('content'),
    ]),
    Section::make([
        Toggle::make('is_published'),
        Toggle::make('is_featured'),
    ])->grow(false),
])->from('md')

本例中,第一个分区会 grow() 以占用可用水平空间,而不影响渲染第二个分区所需的空间。这会产生弹性宽度侧边栏效果。

from() 方法用于控制应使用水平分割布局的 Tailwind 断点smmdlgxl2xl)。本例中,中等及以上设备使用水平分割布局。更小的设备上,分区会上下堆叠。

TIP

除了接受静态值外,grow()from() 方法也接受函数以动态计算。你可以将各种工具作为参数注入这些函数。

FlexFlex

Fieldset 组件

你可能希望将字段分组到 Fieldset 中。每个 fieldset 默认有标签、边框和两列网格:

php
use Filament\Schemas\Components\Fieldset;

Fieldset::make('Label')
    ->columns([
        'default' => 1,
        'md' => 2,
        'xl' => 3,
    ])
    ->schema([
        // ...
    ])

TIP

除了接受静态标签外,make() 方法也接受函数以动态计算。你可以将各种工具作为参数注入该函数。

FieldsetFieldset

移除 fieldset 边框

可使用 contained(false) 方法移除 fieldset 的容器边框:

php
use Filament\Schemas\Components\Fieldset;

Fieldset::make('Label')
    ->contained(false)
    ->schema([
        // ...
    ])

TIP

除了接受静态值外,contained() 方法也接受函数以动态计算。你可以将各种工具作为参数注入该函数。

无容器边框的 Fieldset无容器边框的 Fieldset

控制组件间距

减小组件间距

dense() 方法通过将组件间距减小 50% 来创建更紧凑的布局:

php
use Filament\Schemas\Components\Fieldset;

Fieldset::make('Dense')
    ->dense()
    ->schema([
        // ...
    ])
紧凑间距的布局紧凑间距的布局

移除组件间距

gap(false) 方法移除组件之间的间距:

php
use Filament\Schemas\Components\Fieldset;

Fieldset::make('No gap')
    ->gap(false)
    ->schema([
        // ...
    ])
无间距的布局无间距的布局

使用容器查询

除了基于视口尺寸的传统断点外,还可使用 容器查询 根据父容器尺寸创建响应式布局。当父容器尺寸与视口尺寸不直接相关时尤其有用。例如,在内容旁使用可折叠侧边栏时,内容区域会根据侧边栏折叠状态动态调整大小。

容器查询的基础是容器本身。容器是其宽度决定布局的元素。要将元素指定为容器,对其使用 gridContainer() 方法。例如,若要根据 Grid 组件 的宽度定义网格列数:

php
use Filament\Schemas\Components\Grid;

Grid::make()
    ->gridContainer()
    ->columns([
        // ...
    ])
    ->schema([
        // ...
    ])

一旦元素被指定为网格容器,该元素或其任意子元素都可使用 容器断点 而非标准断点。例如,可用 @md 在容器宽度至少为 448px 时定义网格列数,用 @xl 在宽度至少为 576px 时定义。

php
use Filament\Schemas\Components\Grid;

Grid::make()
    ->gridContainer()
    ->columns([
        '@md' => 3,
        '@xl' => 4,
    ])
    ->schema([
        // ...
    ])

也可在 columnSpan()columnStart()columnOrder() 方法中使用容器断点:

php
use Filament\Forms\Components\TextInput;
use Filament\Schemas\Components\Grid;

Grid::make()
    ->gridContainer()
    ->columns([
        '@md' => 3,
        '@xl' => 4,
    ])
    ->schema([
        TextInput::make('name')
            ->columnSpan([
                '@md' => 2,
                '@xl' => 3,
            ])
            ->columnOrder([
                'default' => 2,
                '@xl' => 1,
            ]),
        TextInput::make('email')
            ->columnSpan([
                'default' => 1,
                '@xl' => 1,
            ])
            ->columnOrder([
                'default' => 1,
                '@xl' => 2,
            ]),
        // ...
    ])

本例中,当容器宽度小于 @xl 断点(576px)时,email 字段先出现,然后是 name 字段。当容器宽度至少为 576px 时,顺序相反:name 字段先出现,然后是 email 字段。

在旧版浏览器上支持容器查询

与传统断点相比,容器查询尚未被浏览器广泛 支持。为支持旧版浏览器,可在容器断点旁定义额外一层断点。通过在传统断点前加上 !@ 前缀,可指定在浏览器不支持容器查询时使用回退断点。

例如,若要对网格列使用 @md 容器断点同时又支持旧版浏览器,可定义 !@md 回退断点,在容器查询不可用时应用:

php
use Filament\Schemas\Components\Grid;

Grid::make()
    ->gridContainer()
    ->columns([
        '@md' => 3,
        '@xl' => 4,
        '!@md' => 2,
        '!@xl' => 3,
    ])
    ->schema([
        // ...
    ])

也可在 columnSpan()columnStart()columnOrder() 方法中使用 !@ 回退断点:

php
use Filament\Forms\Components\TextInput;
use Filament\Schemas\Components\Grid;

Grid::make()
    ->gridContainer()
    ->columns([
        '@md' => 3,
        '@xl' => 4,
        '!@md' => 2,
        '!@xl' => 3,
    ])
    ->schema([
        TextInput::make('name')
            ->columnSpan([
                '@md' => 2,
                '@xl' => 3,
                '!@md' => 2,
                '!@xl' => 2,
            ])
            ->columnOrder([
                'default' => 2,
                '@xl' => 1,
                '!@xl' => 1,
            ]),
        TextInput::make('email')
            ->columnOrder([
                'default' => 1,
                '@xl' => 2,
                '!@xl' => 2,
            ]),
        // ...
    ])

本例中,回退断点确保即使在不支持容器查询的浏览器中,布局仍能响应视口尺寸变化,在较大屏幕上 name 字段先出现,email 字段其次。

延迟加载布局的子 schema

若布局包含渲染成本较高的组件,可向其 schema() 方法传入 Schema 对象并使用 deferLoading()。子 schema 最初会渲染加载指示器,并在进入视口时加载:

php
use Filament\Forms\Components\TextInput;
use Filament\Schemas\Components\Group;
use Filament\Schemas\Schema;

Group::make()
    ->key('customerDetails')
    ->schema(
        Schema::make()
            ->components([
                TextInput::make('name'),
                TextInput::make('email')
                    ->email(),
            ])
            ->deferLoading(),
    )

本例中使用 Group,因为它本身没有视觉样式。对其他接受子 schema 的布局组件可采用相同做法。每个延迟的 schema 都必须有唯一 key,可像本例一样从带 key 的父组件继承。更多信息见 schema 概览

为布局组件添加额外 HTML 属性

可通过 extraAttributes() 方法向组件传入额外 HTML 属性,它们会合并到其外层 HTML 元素上。属性应以数组表示,键为属性名,值为属性值:

php
use Filament\Schemas\Components\Section;

Section::make()
    ->extraAttributes(['class' => 'custom-section-style'])

TIP

除了接受静态值外,extraAttributes() 方法也接受函数以动态计算。你可以将各种工具作为参数注入该函数。

默认情况下,多次调用 extraAttributes() 会覆盖先前的属性。若希望合并属性,可向该方法传入 merge: true