跳到主内容
UniKit

布局网格生成器

生成 12 / 16 / 24 列的布局栅格系统:容器宽度、列数、gutter、外边距与响应式断点,输出 .container / .row / .col-* 类,flex 与 CSS Grid 两种实现可切换。

浏览器本地运行所有计算都在你的浏览器里完成,数据不会离开本机。

栅格参数

列宽 = 容器宽 ÷ 列数 × 跨度。flex 实现用负外边距抵消列内边距,CSS Grid 实现用 repeat(n, minmax(0, 1fr)) + gap。

实现方式

响应式断点

每个断点生成一条 @media:容器最大宽度加 .col-断点-跨度 类。断点列数留空表示沿用全局列数。

实时预览

预览按当前参数渲染,列宽、gutter 与容器宽度跟生成的 CSS 完全一致。

1
2
3
4
5
6
7
8
9
10
11
12
6
6
4
4
4
3
3
3
3
整行(每格 1 列)示例行:6+6 / 4+4+4 / 3+3+3+3

结果

类名跨度宽度
.col-118.333333%
.col-2216.666667%
.col-3325%
.col-4433.333333%
.col-5541.666667%
.col-6650%
.col-7758.333333%
.col-8866.666667%
.col-9975%
.col-101083.333333%
.col-111191.666667%
.col-1212100%
完整 CSS
: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栅格系统布局网格栅格列宽响应式前端工具

同类工具