- 前端
- UI组件
【免费下载链接】Metro-UI-CSS
A progressive front-end framework for creating high-performance responsive reactive web applications!
Grid 是 Metro UI CSS 中用于构建复杂响应式布局的纯 CSS 网格组件,它基于 Flexbox 实现了一套 12 列栅格系统,并借助 CSS 容器查询(Container Queries)在组件层面完成断点自适应。阅读本文后,你将掌握.grid/.row/.cell的完整用法、响应式与偏移类名的取用规则、间距控制机制,以及如何通过--grid-gap变量定制属于自己的网格系统。
组件定位与依赖
Grid 组件位于 source/components/grid/,其入口文件 index.js 只有一行:
import "./grid.less";这说明它是一个纯 CSS 组件:样式全部定义在 grid.less 中,不依赖任何 JavaScript 运行时逻辑,也因此没有插件参数、API 方法和事件。使用时只需引入编译后的 lib/metro.css(或从 source 自行编译),即可直接使用全部网格类名。
快速上手:基础网格布局
网格的基本结构是三层嵌套:.grid容器 →.row行 →.cell-*单元格。以cell-6为例,数字代表该单元格占据 12 列中的 6 列,即一半宽度:
<div class="grid"> <div class="row"> <div class="cell-6">Half width column</div> <div class="cell-6">Half width column</div> </div> <div class="row"> <div class="cell-4">One third</div> <div class="cell-4">One third</div> <div class="cell-4">One third</div> </div> </div>在 examples/grid.html 与 examples/grid-new.html 两个示例页面中,可以看到完整的实战用法:12 个cell-sm-1拼满一行、cell-md-one-third三等分、cell-md-one-fifth五等分、cell-3 offset-md-6组合等。
列宽计算原理:从源码看 12 列是如何算出来的
grid.less顶部定义了一个关键常量:
@gridCellBaseSize: 8.333335%;这是 100% ÷ 12 的近似值,即每一"列"的基准宽度。随后通过 Less 的each(range(0, 12))循环批量生成所有列宽类:
each(range(0, 12), .(@k) { .cell-@{k}, .col-@{k} { flex: 0 0 calc(@gridCellBaseSize * @k - var(--grid-gap)); max-width: calc(@gridCellBaseSize * @k - var(--grid-gap)); } .offset-@{k} { margin-left: calc(@gridCellBaseSize * @k); } })由源码可以推断出三个重要细节:
- 宽度 = 列基准 × 列数 − 间距:
cell-6的实际宽度为8.333335% × 6 − var(--grid-gap),间距被从单元格宽度中扣除,从而保证列与列之间在 flex 布局中不会因gap而溢出换行。 - 偏移只加列宽、不减间距:
offset-3的margin-left为8.333335% × 3,恰好推过 3 列的位置。 .row > *默认占满整行:未指定列宽的任意子元素默认flex: 0 0 100%,即一行一个;只有显式添加cell-*类才会进入多列排布。
自动宽度与弹性列
当你不希望使用固定列数时,可以用以下两类单元格:
<div class="grid"> <div class="row"> <div class="cell-auto">Auto width (takes only needed space)</div> <div class="cell">Flexible width (takes remaining space)</div> </div> </div>.cell-auto/.col-auto:flex: 0 0 auto; width: auto; max-width: none,宽度由内容撑开,只占所需空间;.cell/.col:flex-basis: 0; flex-grow: 1,弹性分配行内剩余空间。
源码中.cell-auto, .col-auto, .v-cell-auto, .v-col-auto四个类共用同一组声明(grid.less),v-前缀类与无前缀类等价,可视为同一能力的别名。
响应式网格:基于容器查询的断点机制
这是 Grid 组件最值得关注的实现特性。README 中列举了xs / sm / md / lg / xl / xxl六个断点,而 vars.less 中实际定义的断点更为完整:
| 断点 | 生效宽度 | 断点 | 生效宽度 |
|---|---|---|---|
fs | 0 | lg | 992px |
xs | 360px | xl | 1200px |
sm | 576px | xxl | 1400px |
ld | 640px | xxxl | 2000px |
md | 768px |
与常见的媒体查询(@media)不同,grid.less中的响应式规则使用容器查询(@container)实现:
each(@media-rules, { @container (width >= @value) { .cell-@{key}-half, .col-@{key}-half { ... } each(range(1, 12), .(@k) { .cell-@{key}-@{k}, .col-@{key}-@{k} { flex: 0 0 calc( @gridCellBaseSize * @k - var(--grid-gap) ); max-width: calc( @gridCellBaseSize * @k - var(--grid-gap) ); } .offset-@{key}-@{k} { margin-left: calc( @gridCellBaseSize * @k ); } }) } })容器查询的"容器"来自.row自身的声明(grid.less):
.row { display: flex; flex-flow: row wrap; gap: var(--grid-gap); container-type: inline-size; container-name: row; min-width: 100%; }这意味着断点依据的是.row所在容器的内联宽度,而非浏览器视口宽度——组件被嵌入任意宽度的卡片、侧栏或面板时,其响应行为跟随父容器变化,这正是 README"Container query support for component-level responsiveness"(容器查询支持组件级响应)的含义。
响应式用法示例(小屏占满整行、中屏起各占一半):
<div class="grid"> <div class="row"> <!-- Full width on small screens, half width on medium and up --> <div class="cell-12 cell-md-6">Responsive column</div> <!-- Full width on small screens, half width on medium and up --> <div class="cell-12 cell-md-6">Responsive column</div> </div> </div>每一个断点都拥有与基础类一一对应的响应式版本:.cell-{breakpoint}-{1-12}、.cell-{breakpoint}、.cell-{breakpoint}-auto、.offset-{breakpoint}-{1-12},以及-half、-one-fifth、-two-fifth、-three-fifth、-four-fifth分数类。
列偏移:精确控制起始位置
偏移用于把单元格从行首"推"到指定列位置,offset-{1-12}以列数为单位:
<div class="grid"> <div class="row"> <div class="cell-6 offset-3">Centered column with offset</div> </div> <div class="row"> <div class="cell-4">First column</div> <div class="cell-4 offset-4">Column with offset</div> </div> </div>第一行中cell-6 offset-3会水平居中显示;第二行中第二个cell-4被offset-4推到第 5 列起始。偏移同样支持响应式版本(如offset-md-6),且偏移量不受--grid-gap影响(源码中margin-left只乘列基准宽度)。
分数宽度:非 12 等分场景
当布局不需要按 12 等分对齐时,可直接使用五等分或对半类:
<div class="grid"> <div class="row"> <div class="cell-one-fifth">20% width</div> <div class="cell-four-fifth">80% width</div> </div> <div class="row"> <div class="cell-two-fifth">40% width</div> <div class="cell-three-fifth">60% width</div> </div> </div>| 类名 | 宽度 | 类名 | 宽度 |
|---|---|---|---|
.cell-half/.col-half | 50% | .cell-one-fifth/.col-one-fifth | 20% |
.cell-two-fifth/.col-two-fifth | 40% | .cell-three-fifth/.col-three-fifth | 60% |
.cell-four-fifth/.col-four-fifth | 80% |
由源码可见,分数类在响应式断点下同样可用(-half为flex: 0 0 50%,五等分类为flex: 0 0 calc(20% - var(--grid-gap))等)。
控制列间距:gap 系列与 no-gap
默认情况下.row使用gap: var(--grid-gap),而--grid-gap在:root上默认定义为16px。三种间距控制方式如下:
<div class="grid"> <!-- Default gap (16px) --> <div class="row"> <div class="cell-6">Column</div> <div class="cell-6">Column</div> </div> <!-- Custom gap (8px) --> <div class="row gap-2"> <div class="cell-6">Column</div> <div class="cell-6">Column</div> </div> <!-- No gap --> <div class="row no-gap"> <div class="cell-6">Column</div> <div class="cell-6">Column</div> </div> </div>.row.gap-{0-12}:按 4px 步进设置间距,即gap-1 = 4px、gap-2 = 8px、gap-3 = 12px……源码通过unit(@v * 4, px)生成(grid.less),最终反映为行级--grid-gap覆盖;.row.no-gap:等价于--grid-gap: 0px,完全去除列间距;- 行与行之间同样以
var(--grid-gap)作为margin-top(.row + .row规则),因此行距与列距保持一致; - 单元格默认
padding: 0,间距完全由gap承担。
用 CSS 变量定制网格
间距并非写死,而是由变量驱动,便于整体或局部定制:
| 变量 | 默认值(浅色模式) | 深色模式 | 说明 |
|---|---|---|---|
--grid-gap | 16px | 16px | 网格列之间的间距 |
在任意作用域覆盖该变量即可改变网格间距:
/* Custom styling example */ .my-custom-grid { --grid-gap: 24px; }<div class="grid my-custom-grid"> <div class="row"> <div class="cell-6">Column</div> <div class="cell-6">Column</div> </div> </div>由于列宽公式(8.333335% × k − var(--grid-gap))和行距(margin-top: var(--grid-gap))都引用该变量,一处修改即可让整组网格的间距与列宽同步适配。
可用 CSS 类速查表
网格容器
| 类名 | 作用 |
|---|---|
.grid | 主网格容器,display: flex; flex-flow: column |
行
| 类名 | 作用 |
|---|---|
.row | 行容器,flex 横向换行排布 |
.row.gap-{0-12} | 自定义间距(gap-0 = 0px,gap-1 = 4px,gap-2 = 8px,以此类推) |
.row.no-gap | 移除列间距 |
列
| 类名 | 作用 |
|---|---|
.cell-{1-12}/.col-{1-12} | 固定列宽(1–12 列) |
.cell/.col | 弹性列,占满剩余空间 |
.cell-auto/.col-auto | 自动宽度列,只占内容所需空间 |
.offset-{1-12} | 列偏移(1–12 列) |
分数列
.cell-one-fifth/.col-one-fifth(20%)、.cell-two-fifth/.col-two-fifth(40%)、.cell-three-fifth/.col-three-fifth(60%)、.cell-four-fifth/.col-four-fifth(80%)、.cell-half/.col-half(50%)。
响应式列:对每个断点(fs / xs / sm / ld / md / lg / xl / xxl / xxxl,README 仅列示 xs–xxl,实际断点全集以 vars.less 为准)提供.cell-{breakpoint}-{1-12}、.cell-{breakpoint}、.cell-{breakpoint}-auto、.offset-{breakpoint}-{1-12},以及-half与四个-fifth分数版本。
间距规则:列默认间距 16px;行距等于列距;单元格默认无内边距。
源码、示例与测试验证
- 样式实现:source/components/grid/grid.less
- 组件入口(纯样式导入):source/components/grid/index.js
- 断点变量定义:source/include/vars.less
- 编译产物(可直接引用):lib/metro.css
- 实战示例页:examples/grid.html、examples/grid-new.html(后者覆盖了 12 等分、三等分、五等分、偏移、
no-gap等组合场景) - 自动化测试:tests/grid.test.js 通过 examples/grid.html 页面加载与运行时错误检查验证组件可用性
总而言之,Metro UI CSS 的 Grid 组件以".grid纵向、.row横向、.cell定宽"的三层模型,配合容器查询驱动的断点体系和变量化的间距控制,为响应式布局提供了一套零 JavaScript 依赖、可在任意父容器内自适应的完整方案。需要组件级响应布局时,它是最直接的选择。
- 前端
- UI组件
【免费下载链接】Metro-UI-CSS
A progressive front-end framework for creating high-performance responsive reactive web applications!
相关推荐
Naive UI 栅格(Grid)组件完全指南:基于 CSS Grid 的响应式布局系统
Naive UI 栅格(Grid)组件完全指南:基于 CSS Grid 的响应式布局系统 Naive UI 的 n grid / n grid item 是一套
前端UI组件Material UI Grid 组件详解:基于 Flexbox 的响应式布局系统
Material UI Grid 组件详解:基于 Flexbox 的响应式布局系统 本文以 Material UI(MUI)文档中 Grid 组件的官方指南为主
前端UI组件设计系统Material Design Lite Grid 组件完整指南:12/8/4 列响应式网格布局
Material Design Lite Grid 组件完整指南:12/8/4 列响应式网格布局 Material Design Lite(MDL)的 grid
前端UI组件
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考