☰
Oat Grid 栅格系统详解:基于 CSS Grid 的 12 列响应式布局实践
2026/10/12 7:43:56 网站建设 项目流程

【免费下载链接】oat

Ultra-lightweight, zero dependency, semantic HTML, CSS, JS UI library. ~10KB min+gz.

项目地址:https://gitcode.com/gh_mirrors/oat5/oat
点击查看免费下载

Oat 是一个极轻量、零依赖的语义化 HTML/CSS/JS UI 组件库,其栅格系统(Grid)提供了一套基于 CSS Grid 的 12 列响应式布局方案。本文以 docs/content/components/grid.md 为骨架,结合 src/css/grid.css 源码逐行剖析.container、.row、.col-{n}、.offset-{n}与.col-end的用法与底层实现,让你读完即可在 Oat 项目中快速搭建页面布局,并掌握如何通过 CSS 变量自定义栅格行为。

栅格系统速览

Oat 的栅格系统由三个层次构成:

  • .container:居中的内容容器,负责限制页面宽度并控制左右内边距;
  • .row:一行栅格轨道,使用 CSS Grid 的grid-template-columns: repeat(12, 1fr)切分 12 等份;
  • .col-{n}:列单元,通过n(1~12)指定该列在行内占据的轨道数量。

官方文档原文(grid.md)对它的定义是:"A 12-column grid system using CSS grid. Use.container,.row, and.colclasses. Column widths use.col-{n}where n is 1-12."——即整套系统完全建立在原生 CSS Grid 之上,不依赖任何 JavaScript,也不引入框架级的栅格生成代码。

引入方式

Oat 的 CSS 通过 npm 包@knadh/oat分发(见 package.json),或直接以 CDN 方式引入(详见 docs/content/usage.md):

<link rel="stylesheet" href="https://unpkg.com/@knadh/oat/oat.min.css">

本地开发时,栅格样式位于源码的 src/css/grid.css,并由 Makefile 中的css目标将其与其余组件样式按固定顺序合并、压缩为dist/oat.min.css(grid.css位于table.css与card.css之间)。由于栅格只涉及样式、不涉及交互,使用它无需引入oat.min.js,这一点与 Oat 中多数动态组件(如 toast、dropdown)不同。

基础用法:container / row / col

栅格的最小结构如下:

<div class="container"> <div class="row"> <div class="col-4">col-4</div> <div class="col-4">col-4</div> <div class="col-4">col-4</div> </div> </div>

这会在页面内生成一行三列的布局,每列恰好占据 12 列中的 4 列。列数之和不超过 12 时,各列按序排列;不足 12 时右侧留白。

官方示例全集

grid.md 给出了覆盖等分、不对称、偏移与右对齐等典型场景的完整示例,以下代码可直接复制运行(demo-grid仅为演示页的着色辅助类,实际项目中可去掉):

<div class="container demo-grid"> <div class="row"> <div class="col-4">col-4</div> <div class="col-4">col-4</div> <div class="col-4">col-4</div> </div> <div class="row"> <div class="col-6">col-6</div> <div class="col-6">col-6</div> </div> <div class="row"> <div class="col-3">col-3</div> <div class="col-6">col-6</div> <div class="col-3">col-3</div> </div> <div class="row"> <div class="col-4 offset-2">col-4 offset-2</div> <div class="col-4">col-4</div> </div> <div class="row"> <div class="col-8">col-8</div> <div class="col-3 offset-1">col-3 offset-1</div> </div> <div class="row"> <div class="col-3">col-3</div> <div class="col-4 col-end">col-4 col-end</div> </div> </div>

其中四行依次演示了:

  1. 三等分:col-4× 3,总宽 12;
  2. 二等分:col-6× 2,各占半行;
  3. 对称布局:col-3+col-6+col-3,中间内容区加宽;
  4. 偏移列:col-4 offset-2将首列向右推 2 格,再接一个col-4;
  5. 不对称 + 偏移:col-8打头,col-3 offset-1从末尾侧开始,实际总占用 8 + 1 + 3 = 12;
  6. 右对齐收尾:col-3在前,col-4 col-end被钉在行的最右端。

列宽与偏移的类名清单

类名作用取值范围
.container居中定宽容器宽度由--container-max决定
.row12 列栅格轨道—
.col-1~.col-12指定列跨度n∈ [1, 12]
.offset-1~.offset-6列左侧偏移n∈ [1, 6]
.col-end将列对齐到行尾与col-{n}组合使用

需要说明的是,偏移类目前只提供了 1~6 六档(见 src/css/grid.css),而不是与列宽对称的 1~11 档;若需要 7 格以上的偏移,可在自己的样式表中为.offset-7等自定义类设置--offset变量(机制见下文"源码级原理")。

源码级原理:CSS 变量驱动的列与偏移

Oat 栅格没有采用"为每个断点生成一打媒体查询类"的经典做法,而是用一套极简的 CSS 自定义属性完成了列跨度与偏移的组合。核心实现集中在 src/css/grid.css:

:root { --grid-cols: 12; --grid-gap: 1.5rem; --container-max: 1280px; --container-pad: 1rem; } .row { display: grid; grid-template-columns: repeat(var(--grid-cols), 1fr); gap: var(--grid-gap); width: 100%; }

列跨度:--span的叠加

每一列的跨度并不直接写死为grid-column: span 4,而是通过--span变量间接表达:

.col, [class*="col-"] { grid-column-end: span calc(var(--span, var(--grid-cols)) + var(--offset, 0)); } .col-1 { --span: 1; } /* ... */ .col-12 { --span: 12; }

col-{n}类只负责设置--span变量,而真正的跨度计算集中在统一定义里:grid-column-end: span calc(var(--span) + var(--offset))。这意味着偏移量被合并进了网格跨度计算——一个col-4 offset-2的元素实际在网格上占用 6 个轨道(4 列内容 + 2 列空白),从而保证偏移不会破坏 12 列的对齐节奏。

不带数字的裸.col类默认取--span: var(--grid-cols),即占满整行 12 列,等价于col-12。

偏移:margin 公式与 CSS Grid 的配合

既然偏移已计入grid-column-end的 span,为什么还需要额外的margin-inline-start?看这段源码:

[class*="offset-"] { margin-inline-start: calc(var(--offset) * (100% + var(--grid-gap)) / (var(--span) + var(--offset))); }

该公式把"单列轨道宽度 + 间隙"作为基准宽度(100% + gap) / (span + offset),再乘以偏移格数--offset,得到的左边距恰好等于 n 个轨道加间隙的总宽度。这样偏移列在网格中"占据"的轨道与视觉上被推开的距离完全一致,无论栅格总宽或列数如何变化都能保持精确对齐——这是整个系统最精妙的一处设计。

右对齐:.col-end

.col-end { grid-column-start: span var(--span, 1); grid-column-end: -1; }

.col-end使用 CSS Grid 的负索引-1(即最后一条网格线)作为grid-column-end,让列被钉在行的右端;配合col-{n}时,--span决定该列从右侧向左占用的轨道数。例如col-4 col-end表示"从右端向左占据 4 列",实现单侧顶格的效果,无需手动数偏移值。

移动端降级

在max-width: 768px媒体查询内(src/css/grid.css),栅格自动切换为4 列模式:

@media (max-width: 768px) { .row { --grid-cols: 4; --grid-gap: 1rem; } .col, [class*="col-"] { --span: 4; } [class*="offset-"] { --offset: 0; margin-inline-start: 0; } }

三个动作同时发生:

  • 轨道数从 12 降到 4,间隙从1.5rem收紧到1rem;
  • 所有列(包括col-1~col-12)统一回退为--span: 4,即占满整行、纵向堆叠,避免小屏上列宽过窄;
  • 所有偏移类归零,偏移边距重置为 0。

效果是:桌面端 12 列精细排版,手机端自动折叠为单列流式布局,全程无需添加任何断点类。值得注意的是,官方文档元数据中描述为 "using container queries",但从 src/css/grid.css 的实际实现看,响应式切换目前由传统@media媒体查询完成。

自定义栅格:覆盖四个 CSS 变量

栅格的四个设计参数全部暴露为:root上的 CSS 自定义属性(src/css/grid.css),你可以在自己的样式表中直接覆盖,无需改动源码:

:root { --grid-cols: 12; /* 栅格总列数(默认 12) */ --grid-gap: 1.5rem; /* 列间隙(默认 1.5rem) */ --container-max: 1280px; /* 容器最大宽度(默认 1280px) */ --container-pad: 1rem; /* 容器左右内边距(默认 1rem) */ }

例如改成 16 列栅格:将--grid-cols: 16即可,此时col-4等价于原系统的三分之一宽;调整--grid-gap可全局改变列间距而无需触碰任何col-*类。Oat 的文档演示站也在 docs/static/demo.css 中把.container的max-width覆盖为 1200px 以适配演示页面,说明这套变量在业务项目中按需覆写是完全常规的做法。

实战组合:用 Grid 拼装指标卡片

栅格很少单独使用,Oat 官方在 docs/content/recipes.md 的 "Stats cards" 一节演示了如何用grid、card、badge、progress组合出仪表盘指标区:

<div class="container"> <div class="row"> <article class="card col-4"> <header class="hstack justify-between items-center"> <h4>Revenue</h4> <span class="badge">

【免费下载链接】oat

Ultra-lightweight, zero dependency, semantic HTML, CSS, JS UI library. ~10KB min+gz.

项目地址:https://gitcode.com/gh_mirrors/oat5/oat
点击查看免费下载
上一篇:如何高效开发Asynq中间件:扩展Go分布式任务队列的终极指南
下一篇:Rampart的未来发展:隐私保护技术的演进路线图

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询