布局网格生成器
生成 12 / 16 / 24 列的布局栅格系统:容器宽度、列数、gutter、外边距与响应式断点,输出 .container / .row / .col-* 类,flex 与 CSS Grid 两种实现可切换。
浏览器本地运行所有计算都在你的浏览器里完成,数据不会离开本机。
栅格参数
列宽 = 容器宽 ÷ 列数 × 跨度。flex 实现用负外边距抵消列内边距,CSS Grid 实现用 repeat(n, minmax(0, 1fr)) + gap。
响应式断点
每个断点生成一条 @media:容器最大宽度加 .col-断点-跨度 类。断点列数留空表示沿用全局列数。
实时预览
预览按当前参数渲染,列宽、gutter 与容器宽度跟生成的 CSS 完全一致。
结果
| 类名 | 跨度 | 宽度 |
|---|---|---|
| .col-1 | 1 | 8.333333% |
| .col-2 | 2 | 16.666667% |
| .col-3 | 3 | 25% |
| .col-4 | 4 | 33.333333% |
| .col-5 | 5 | 41.666667% |
| .col-6 | 6 | 50% |
| .col-7 | 7 | 58.333333% |
| .col-8 | 8 | 66.666667% |
| .col-9 | 9 | 75% |
| .col-10 | 10 | 83.333333% |
| .col-11 | 11 | 91.666667% |
| .col-12 | 12 | 100% |
:root {
--grid-columns: 12;
--grid-gutter: 24px;
--grid-gutter-half: 12px;
--grid-margin: 16px;
--container-max-width: 1200px;
}
.container {
width: 100%;
max-width: 1200px;
margin-inline: auto;
padding-inline: 16px;
}
.row {
display: flex;
flex-wrap: wrap;
margin-inline: -12px;
}
[class^="col-"], [class*=" col-"] {
box-sizing: border-box;
padding-inline: 12px;
}
.col-1 {
flex: 0 0 8.333333%;
max-width: 8.333333%;
}
.col-2 {
flex: 0 0 16.666667%;
max-width: 16.666667%;
}
.col-3 {
flex: 0 0 25%;
max-width: 25%;
}
.col-4 {
flex: 0 0 33.333333%;
max-width: 33.333333%;
}
.col-5 {
flex: 0 0 41.666667%;
max-width: 41.666667%;
}
.col-6 {
flex: 0 0 50%;
max-width: 50%;
}
.col-7 {
flex: 0 0 58.333333%;
max-width: 58.333333%;
}
.col-8 {
flex: 0 0 66.666667%;
max-width: 66.666667%;
}
.col-9 {
flex: 0 0 75%;
max-width: 75%;
}
.col-10 {
flex: 0 0 83.333333%;
max-width: 83.333333%;
}
.col-11 {
flex: 0 0 91.666667%;
max-width: 91.666667%;
}
.col-12 {
flex: 0 0 100%;
max-width: 100%;
}
/* sm: ≥576px */
@media (min-width: 576px) {
.container {
max-width: 576px;
}
.col-sm-1 {
flex: 0 0 8.333333%;
max-width: 8.333333%;
}
.col-sm-2 {
flex: 0 0 16.666667%;
max-width: 16.666667%;
}
.col-sm-3 {
flex: 0 0 25%;
max-width: 25%;
}
.col-sm-4 {
flex: 0 0 33.333333%;
max-width: 33.333333%;
}
.col-sm-5 {
flex: 0 0 41.666667%;
max-width: 41.666667%;
}
.col-sm-6 {
flex: 0 0 50%;
max-width: 50%;
}
.col-sm-7 {
flex: 0 0 58.333333%;
max-width: 58.333333%;
}
.col-sm-8 {
flex: 0 0 66.666667%;
max-width: 66.666667%;
}
.col-sm-9 {
flex: 0 0 75%;
max-width: 75%;
}
.col-sm-10 {
flex: 0 0 83.333333%;
max-width: 83.333333%;
}
.col-sm-11 {
flex: 0 0 91.666667%;
max-width: 91.666667%;
}
.col-sm-12 {
flex: 0 0 100%;
max-width: 100%;
}
}
/* md: ≥768px */
@media (min-width: 768px) {
.container {
max-width: 768px;
}
.col-md-1 {
flex: 0 0 8.333333%;
max-width: 8.333333%;
}
.col-md-2 {
flex: 0 0 16.666667%;
max-width: 16.666667%;
}
.col-md-3 {
flex: 0 0 25%;
max-width: 25%;
}
.col-md-4 {
flex: 0 0 33.333333%;
max-width: 33.333333%;
}
.col-md-5 {
flex: 0 0 41.666667%;
max-width: 41.666667%;
}
.col-md-6 {
flex: 0 0 50%;
max-width: 50%;
}
.col-md-7 {
flex: 0 0 58.333333%;
max-width: 58.333333%;
}
.col-md-8 {
flex: 0 0 66.666667%;
max-width: 66.666667%;
}
.col-md-9 {
flex: 0 0 75%;
max-width: 75%;
}
.col-md-10 {
flex: 0 0 83.333333%;
max-width: 83.333333%;
}
.col-md-11 {
flex: 0 0 91.666667%;
max-width: 91.666667%;
}
.col-md-12 {
flex: 0 0 100%;
max-width: 100%;
}
}
/* lg: ≥992px */
@media (min-width: 992px) {
.container {
max-width: 992px;
}
.col-lg-1 {
flex: 0 0 8.333333%;
max-width: 8.333333%;
}
.col-lg-2 {
flex: 0 0 16.666667%;
max-width: 16.666667%;
}
.col-lg-3 {
flex: 0 0 25%;
max-width: 25%;
}
.col-lg-4 {
flex: 0 0 33.333333%;
max-width: 33.333333%;
}
.col-lg-5 {
flex: 0 0 41.666667%;
max-width: 41.666667%;
}
.col-lg-6 {
flex: 0 0 50%;
max-width: 50%;
}
.col-lg-7 {
flex: 0 0 58.333333%;
max-width: 58.333333%;
}
.col-lg-8 {
flex: 0 0 66.666667%;
max-width: 66.666667%;
}
.col-lg-9 {
flex: 0 0 75%;
max-width: 75%;
}
.col-lg-10 {
flex: 0 0 83.333333%;
max-width: 83.333333%;
}
.col-lg-11 {
flex: 0 0 91.666667%;
max-width: 91.666667%;
}
.col-lg-12 {
flex: 0 0 100%;
max-width: 100%;
}
}/* sm: ≥576px */
@media (min-width: 576px) {
.container {
max-width: 576px;
}
.col-sm-1 {
flex: 0 0 8.333333%;
max-width: 8.333333%;
}
.col-sm-2 {
flex: 0 0 16.666667%;
max-width: 16.666667%;
}
.col-sm-3 {
flex: 0 0 25%;
max-width: 25%;
}
.col-sm-4 {
flex: 0 0 33.333333%;
max-width: 33.333333%;
}
.col-sm-5 {
flex: 0 0 41.666667%;
max-width: 41.666667%;
}
.col-sm-6 {
flex: 0 0 50%;
max-width: 50%;
}
.col-sm-7 {
flex: 0 0 58.333333%;
max-width: 58.333333%;
}
.col-sm-8 {
flex: 0 0 66.666667%;
max-width: 66.666667%;
}
.col-sm-9 {
flex: 0 0 75%;
max-width: 75%;
}
.col-sm-10 {
flex: 0 0 83.333333%;
max-width: 83.333333%;
}
.col-sm-11 {
flex: 0 0 91.666667%;
max-width: 91.666667%;
}
.col-sm-12 {
flex: 0 0 100%;
max-width: 100%;
}
}
/* md: ≥768px */
@media (min-width: 768px) {
.container {
max-width: 768px;
}
.col-md-1 {
flex: 0 0 8.333333%;
max-width: 8.333333%;
}
.col-md-2 {
flex: 0 0 16.666667%;
max-width: 16.666667%;
}
.col-md-3 {
flex: 0 0 25%;
max-width: 25%;
}
.col-md-4 {
flex: 0 0 33.333333%;
max-width: 33.333333%;
}
.col-md-5 {
flex: 0 0 41.666667%;
max-width: 41.666667%;
}
.col-md-6 {
flex: 0 0 50%;
max-width: 50%;
}
.col-md-7 {
flex: 0 0 58.333333%;
max-width: 58.333333%;
}
.col-md-8 {
flex: 0 0 66.666667%;
max-width: 66.666667%;
}
.col-md-9 {
flex: 0 0 75%;
max-width: 75%;
}
.col-md-10 {
flex: 0 0 83.333333%;
max-width: 83.333333%;
}
.col-md-11 {
flex: 0 0 91.666667%;
max-width: 91.666667%;
}
.col-md-12 {
flex: 0 0 100%;
max-width: 100%;
}
}
/* lg: ≥992px */
@media (min-width: 992px) {
.container {
max-width: 992px;
}
.col-lg-1 {
flex: 0 0 8.333333%;
max-width: 8.333333%;
}
.col-lg-2 {
flex: 0 0 16.666667%;
max-width: 16.666667%;
}
.col-lg-3 {
flex: 0 0 25%;
max-width: 25%;
}
.col-lg-4 {
flex: 0 0 33.333333%;
max-width: 33.333333%;
}
.col-lg-5 {
flex: 0 0 41.666667%;
max-width: 41.666667%;
}
.col-lg-6 {
flex: 0 0 50%;
max-width: 50%;
}
.col-lg-7 {
flex: 0 0 58.333333%;
max-width: 58.333333%;
}
.col-lg-8 {
flex: 0 0 66.666667%;
max-width: 66.666667%;
}
.col-lg-9 {
flex: 0 0 75%;
max-width: 75%;
}
.col-lg-10 {
flex: 0 0 83.333333%;
max-width: 83.333333%;
}
.col-lg-11 {
flex: 0 0 91.666667%;
max-width: 91.666667%;
}
.col-lg-12 {
flex: 0 0 100%;
max-width: 100%;
}
}:root {
--grid-columns: 12;
--grid-gutter: 24px;
--grid-gutter-half: 12px;
--grid-margin: 16px;
--container-max-width: 1200px;
}这个工具能做什么
- 搭新项目的基础布局:先定 12 列、容器 1200px、gutter 24px,一次拿到 .container / .row / .col-* 全套类,不用再抄一遍框架的栅格。
- 需要非 12 列体系时(16 列适合卡片列表、24 列适合细粒度排版),换成 16 或 24 列,列宽百分比会自动重算。
- 把断点与容器宽度一起生成:每个断点输出 .col-md-6 这类响应式列类和对应的容器 max-width,移动优先的 @media 顺序也排好了。
- 只想要变量做设计令牌时,复制 :root 里的 --grid-columns / --grid-gutter / --grid-margin / --container-max-width 即可。
示例
输入
列数 12、容器宽度 1200px、gutter 24px、外边距 16px、flex 实现、无断点
输出
:root { --grid-columns: 12; --grid-gutter: 24px; --grid-gutter-half: 12px; --grid-margin: 16px; --container-max-width: 1200px; } / .container { width: 100%; max-width: 1200px; margin-inline: auto; padding-inline: 16px; } / .row { display: flex; flex-wrap: wrap; margin-inline: -12px; } / .col-6 { flex: 0 0 50%; max-width: 50%; }列宽是百分比,因此 12 列的 .col-1 是 8.333333%、.col-5 是 41.666667%。
常见问题
这个和 CSS Grid 生成器有什么区别?
这里是「页面布局网格」:列宽 = 容器宽 ÷ 列数 × 跨度,产出的是 .container / .row / .col-* 这套类名,flex 与 CSS Grid 只是两种实现手段。如果要做的是 grid-template-columns / grid-area 那类具体属性,应该用 CSS Grid 生成器。
flex 实现里的负外边距是干什么的?
列用 padding-inline: gutter/2 制造间距,这会让整行的左右各多出 gutter/2 的空白,于是 .row 用 margin-inline: -gutter/2 抵消掉,让最外侧的列与容器边缘对齐。gutter 为 0 时不会出现 -0,而是直接写 margin-inline: 0。
为什么列宽有 8.333333% 这种小数?
12 列里 1 列就是 1/12 = 8.3333…%,除不尽。工具把百分比保留到 6 位小数,既贴近真实值又不会因为四舍五入让整行超过 100% 而换行。要绝对精确就用 CSS Grid 实现,它按 fr 分配空间。
响应式列类怎么用?
写了断点 md(768px)就会得到 .col-md-6 这类类名,只在 ≥768px 时生效,同时该断点下 .container 的 max-width 会被改写。典型写法是 .col-12 .col-md-6,窄屏整行、宽屏半行。
列数能改吗?
可以,1–24 之间任意整数,常见的是 12、16、24。断点还可以单独指定列数,例如小屏 16 列、大屏 12 列,工具会为每条 @media 生成对应数量的列类。
关键词:layout gridgrid systemcss gridflexboxcolumnsgutter栅格系统布局网格栅格列宽响应式前端工具