⚡️ Flash Grid:通过构建网格系统学习 CSS Grid

2025-05-24

⚡️ Flash Grid:通过构建网格系统学习 CSS Grid

最近,我一直在尝试构建基于 CSS Grid 的轻量级网格系统。

CodyFrame中确实有一个基于 Flexbox 的网格系统。然而,CSS Grid 有很多 Flexbox 所不具备的强大功能,所以我最终创建了 Flash Grid。

我将分享创建 Flash Grid 的整个过程。如果你想了解更多关于 CSS Grid 的知识,这里是一个很好的起点,因为我们将介绍 CSS Grid 的主要属性,并分享一些实用技巧,让你能够充分利用这个强大的布局系统。

如果您想跳过教程并直接获取代码:


开始吧!🙌

第一步是创建.grid类:

$grid-columns: 12 !default;

.grid {
  --grid-cols: #{$grid-columns};
  display: grid;
  grid-gap: var(--grid-gap, 0); // default grid-gap = 0
  grid-template-columns: repeat(var(--grid-cols), 1fr); // grid of 12 flexible columns

  > * {
    grid-column-end: span var(--grid-cols); // each grid item takes full-width by default
  }
}
Enter fullscreen mode Exit fullscreen mode

在定义网格列数时,如果网格系统作为模块导入,我们使用!default SCSS 标志,并且我们希望该值是可定制的。

grid-template-columns是我们定义网格布局的属性:我们需要 12 个响应式列。每列的宽度为 1fr。Fr(分数单位)是一个智能单位,等于可用空间的 1/10。因为我们的网格由 12 个 1fr 列组成,所以每个灵活列占用可用宽度的 1/12。

repeat() 函数允许我们传递单个宽度值 (1fr)。定义相同网格的另一种方法是:

.grid {
  grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr; // 🙈
}
Enter fullscreen mode Exit fullscreen mode

...但是,你知道...不那么优雅!

以下是我们刚刚创建的网格的简要概述:
12列网格

在上面的截图中,请注意列之间的数字(目前只需关注顶部的正数)。这些行号可用于放置网格项。

.grid代码片段中,我们还针对所有网格子项,并将它们的grid-column-end值设置为span 12

默认情况下,我们希望每个子元素占据整个可用宽度。grid-column-end用于指定网格项的结束位置。您可以使用此属性设置结束线(例如grid-column-end: 3;)。但是,如果您使用“span”魔法词,则可以定义网格项应占用多少列。例如,grid-column-end: span 12;表示“将此元素跨越 12 列”。

为什么要为网格项设置默认的 12 列跨度?因为我们的工作以移动设备为先。我们可以假设,在大多数情况下,我们的网格项最初会占据全宽(12 列),然后在更大的屏幕上占据较少的列数。我们的默认值使我们无需.col-12手动指定每个网格项(跨度 12)。

列数设置为 CSS 自定义属性,以便你想在组件级别(或通过创建其他实用程序类)更改它。例如:

.grid--2 {
  --grid-cols: 2;
}
Enter fullscreen mode Exit fullscreen mode

接下来,我们可以为该属性定义实用程序类grid-gap

.grid-gap-xxxxs { --grid-gap: var(--space-xxxxs, 0.125rem); }
.grid-gap-xxxs  { --grid-gap: var(--space-xxxs, 0.25rem); }
.grid-gap-xxs   { --grid-gap: var(--space-xxs, 0.375rem); }
.grid-gap-xs    { --grid-gap: var(--space-xs, 0.5rem); }
.grid-gap-sm    { --grid-gap: var(--space-sm, 0.75rem); }
.grid-gap-md    { --grid-gap: var(--space-md, 1.25rem); }
.grid-gap-lg    { --grid-gap: var(--space-lg, 2rem); }
.grid-gap-xl    { --grid-gap: var(--space-xl, 3.25rem); }
.grid-gap-xxl   { --grid-gap: var(--space-xxl, 5.25rem); }
.grid-gap-xxxl  { --grid-gap: var(--space-xxxl, 8.5rem); }
.grid-gap-xxxxl { --grid-gap: var(--space-xxxxl, 13.75rem); }
Enter fullscreen mode Exit fullscreen mode

间距变量是CodyFrame的一部分。您可以用自己的间距比例替换它们,或者使用每个变量中指定的后备值(如果变量未定义,则应用逗号后的值)。

grid-gap属性用于定义网格项之间的空间。

为了完成基本的网格系统,我们应该定义以下.col类:

@for $i from 1 through $grid-columns {
  .col-#{$i}  { grid-column-end: span #{$i}; }
}
Enter fullscreen mode Exit fullscreen mode

我们使用 SASS @for.col循环根据变量中指定的列数生成类$grid-columns

编译后的 CSS 为:

.col-1  { grid-column-end: span 1; }
.col-2  { grid-column-end: span 2; }
.col-3  { grid-column-end: span 3; }
.col-4  { grid-column-end: span 4; }
.col-5  { grid-column-end: span 5; }
.col-6  { grid-column-end: span 6; }
.col-7  { grid-column-end: span 7; }
.col-8  { grid-column-end: span 8; }
.col-9  { grid-column-end: span 9; }
.col-10 { grid-column-end: span 10; }
.col-11 { grid-column-end: span 11; }
.col-12 { grid-column-end: span 12; }
Enter fullscreen mode Exit fullscreen mode

col 类指定网格项占用的列数。记住,“span”表示“元素跨越 x 列”,其中 x 是 span 后面指定的数字。

添加一些 CSS Grid 元素

回顾一下,Flash Grid 的准系统版本包括网格、网格间隙和 col 实用程序类的定义:

现在是时候加点料了!💃

这是.grid-auto-cols实用程序类:

.grid-auto-cols { // cols = same size
  display: grid;
  grid-gap: var(--grid-gap, 0);
  grid-template-columns: repeat(auto-fit, minmax(0, 1fr));
}
Enter fullscreen mode Exit fullscreen mode

这个类与 类类似.grid,只是我们没有设置列数。auto-fit替换了 类中的 12。.grid这意味着让 CSS Grid 根据列的宽度值(repeat() 函数的第二个值)来决定列数。

可是等等!宽度值(.grid类中的 1fr)现在被 minmax() 函数替换了。字面意思是,列的最小宽度为 0,最大值为 1fr。我们正在为列宽设置一个值范围。

结果是:您得到一个网格,其中所有列都具有相同的宽度,无论其内容或网格项的数量如何。

网格自动列

使用类似的方法,我们创建.grid-auto-{size}实用程序类:

.grid-auto-xs, .grid-auto-sm, .grid-auto-md, .grid-auto-lg, .grid-auto-xl { // auto-sized grid
  display: grid;
  grid-gap: var(--grid-gap, 0);
  grid-template-columns: repeat(auto-fit, minmax(var(--col-min-width), 1fr));
}

.grid-auto-xs { --col-min-width: 8rem; }
.grid-auto-sm { --col-min-width: 10rem; }
.grid-auto-md { --col-min-width: 15rem; }
.grid-auto-lg { --col-min-width: 20rem; }
.grid-auto-xl { --col-min-width: 25rem; }
Enter fullscreen mode Exit fullscreen mode

与 不同.grid-auto-cols,这些新类的最小宽度值等于--col-min-width。结果是一个响应式网格,当有足够空间时,会添加一个新列(minmax() 函数中指定的最小宽度)。

替代文本

🔥 使用 .grid-auto 实用程序类(.grid-auto-cols.grid-auto-{size}),您可以创建响应式布局,而无需.col在网格项上使用类。实际上,.col如果您希望 .grid-auto 类正常工作,则根本不应该使用类。

最后,为了利用网格线号,我们可以创建一组新的实用程序类:col-start-{line-number}.col-end-{line-number}

@for $i from 1 through $grid-columns {
  .col-start-#{$i} { grid-column-start: #{$i}; }
  .col-end-#{$i+1} { grid-column-end: #{$i+1}; }
}
Enter fullscreen mode Exit fullscreen mode

.col-start 类从.col-start-1col-start-12,而 .col-end 类从.col-end-2.col-end-13

如果您希望网格项跨越特定的起点和终点线,请使用它们。

请记住这些是行号:
12列网格

底部的负数是定位相同行的另一种方法。它们为何有用:如果您想定位最后一行,而不管列数是多少,您可以执行以下操作:

.col-end { 
  grid-column-end: -1; 
}
Enter fullscreen mode Exit fullscreen mode

.col-start/end 类允许您创建高级网格:

类断点修饰符

为了使网格在不同的断点处可编辑,我们可以添加类修饰符。在CodyFrame中,我们的惯例是为类添加 @{breakpoint} 后缀(例如col-4@sm)来定位断点。

以下是 x-small 断点处的类修饰符的示例:

$breakpoints: (
  xs: 32rem, 
  sm: 48rem,
  md: 64rem,
  lg: 80rem,
  xl: 90rem
) !default;

@mixin breakpoint($breakpoint) {
  @media (min-width: map-get($map: $breakpoints, $key: $breakpoint)) { @content; }
}

@include breakpoint(xs) {
  .grid-auto-xs\@xs { --col-min-width: 8rem; }
  .grid-auto-sm\@xs { --col-min-width: 10rem; }
  .grid-auto-md\@xs { --col-min-width: 15rem; }
  .grid-auto-lg\@xs { --col-min-width: 20rem; }
  .grid-auto-xl\@xs { --col-min-width: 25rem; }

  .grid-auto-cols\@xs { grid-template-columns: repeat(auto-fit, minmax(0, 1fr)); }

  @for $i from 1 through $grid-columns {
    .col-#{$i}\@xs  { grid-column-end: span #{$i}; }
    .col-start-#{$i}\@xs { grid-column-start: #{$i}; }
    .col-end-#{$i+1}\@xs { grid-column-end: #{$i+1}; }
  }

  .col-start-auto\@xs { grid-column-start: auto; }
  .col-end-auto\@xs { grid-column-end: auto; }
}
Enter fullscreen mode Exit fullscreen mode

⚡️ Flash Grid 的 Beta 版本

Flash Grid 测试版已准备就绪!

在 Codepen 上尝试一下:

最终的 SCSS 代码:

// ⚡️ Flash Grid
$grid-columns: 12 !default;

.grid, [class*="grid-auto-"] {
  display: grid;
  grid-gap: var(--grid-gap, 0);
}

.grid {
  --grid-cols: #{$grid-columns};
  grid-template-columns: repeat(var(--grid-cols), 1fr);

  > * {
    grid-column-end: span var(--grid-cols);
  }
}

.grid-auto-xs, .grid-auto-sm, .grid-auto-md, .grid-auto-lg, .grid-auto-xl { // auto-sized grid
  grid-template-columns: repeat(auto-fit, minmax(var(--col-min-width), 1fr));
}

.grid-auto-xs { --col-min-width: 8rem; }
.grid-auto-sm { --col-min-width: 10rem; }
.grid-auto-md { --col-min-width: 15rem; }
.grid-auto-lg { --col-min-width: 20rem; }
.grid-auto-xl { --col-min-width: 25rem; }

.grid-auto-cols { // cols = same size
  grid-template-columns: repeat(auto-fit, minmax(0, 1fr));
}

.grid-gap-xxxxs { --grid-gap: var(--space-xxxxs, 0.125rem); }
.grid-gap-xxxs  { --grid-gap: var(--space-xxxs, 0.25rem); }
.grid-gap-xxs   { --grid-gap: var(--space-xxs, 0.375rem); }
.grid-gap-xs    { --grid-gap: var(--space-xs, 0.5rem); }
.grid-gap-sm    { --grid-gap: var(--space-sm, 0.75rem); }
.grid-gap-md    { --grid-gap: var(--space-md, 1.25rem); }
.grid-gap-lg    { --grid-gap: var(--space-lg, 2rem); }
.grid-gap-xl    { --grid-gap: var(--space-xl, 3.25rem); }
.grid-gap-xxl   { --grid-gap: var(--space-xxl, 5.25rem); }
.grid-gap-xxxl  { --grid-gap: var(--space-xxxl, 8.5rem); }
.grid-gap-xxxxl { --grid-gap: var(--space-xxxxl, 13.75rem); }

@for $i from 1 through $grid-columns {
  .col-#{$i}  { grid-column-end: span #{$i}; }
  .col-start-#{$i} { grid-column-start: #{$i}; }
  .col-end-#{$i+1} { grid-column-end: #{$i+1}; }
}

.col-start { grid-column-start: 1; }
.col-end { grid-column-end: -1; }

// breakpoints
$breakpoints: (
  xs: 32rem, 
  sm: 48rem,
  md: 64rem,
  lg: 80rem,
  xl: 90rem
) !default;

@mixin breakpoint($breakpoint) {
  @media (min-width: map-get($map: $breakpoints, $key: $breakpoint)) { @content; }
}

@include breakpoint(xs) {
  .grid-auto-xs\@xs { --col-min-width: 8rem; }
  .grid-auto-sm\@xs { --col-min-width: 10rem; }
  .grid-auto-md\@xs { --col-min-width: 15rem; }
  .grid-auto-lg\@xs { --col-min-width: 20rem; }
  .grid-auto-xl\@xs { --col-min-width: 25rem; }

  .grid-auto-cols\@xs { grid-template-columns: repeat(auto-fit, minmax(0, 1fr)); }

  @for $i from 1 through $grid-columns {
    .col-#{$i}\@xs  { grid-column-end: span #{$i}; }
    .col-start-#{$i}\@xs { grid-column-start: #{$i}; }
    .col-end-#{$i+1}\@xs { grid-column-end: #{$i+1}; }
  }

  .col-start-auto\@xs { grid-column-start: auto; }
  .col-end-auto\@xs { grid-column-end: auto; }
}

@include breakpoint(sm) {
  .grid-auto-xs\@sm { --col-min-width: 8rem; }
  .grid-auto-sm\@sm { --col-min-width: 10rem; }
  .grid-auto-md\@sm { --col-min-width: 15rem; }
  .grid-auto-lg\@sm { --col-min-width: 20rem; }
  .grid-auto-xl\@sm { --col-min-width: 25rem; }

  .grid-auto-cols\@sm { grid-template-columns: repeat(auto-fit, minmax(0, 1fr)); }

  @for $i from 1 through $grid-columns {
    .col-#{$i}\@sm  { grid-column-end: span #{$i}; }
    .col-start-#{$i}\@sm { grid-column-start: #{$i}; }
    .col-end-#{$i+1}\@sm { grid-column-end: #{$i+1}; }
  }

  .col-start-auto\@sm { grid-column-start: auto; }
  .col-end-auto\@sm { grid-column-end: auto; }
}

@include breakpoint(md) {
  .grid-auto-xs\@md { --col-min-width: 8rem; }
  .grid-auto-sm\@md { --col-min-width: 10rem; }
  .grid-auto-md\@md { --col-min-width: 15rem; }
  .grid-auto-lg\@md { --col-min-width: 20rem; }
  .grid-auto-xl\@md { --col-min-width: 25rem; }

  .grid-auto-cols\@md { grid-template-columns: repeat(auto-fit, minmax(0, 1fr)); }

  @for $i from 1 through $grid-columns {
    .col-#{$i}\@md  { grid-column-end: span #{$i}; }
    .col-start-#{$i}\@md { grid-column-start: #{$i}; }
    .col-end-#{$i+1}\@md { grid-column-end: #{$i+1}; }
  }

  .col-start-auto\@md { grid-column-start: auto; }
  .col-end-auto\@md { grid-column-end: auto; }
}

@include breakpoint(lg) {
  .grid-auto-xs\@lg { --col-min-width: 8rem; }
  .grid-auto-sm\@lg { --col-min-width: 10rem; }
  .grid-auto-md\@lg { --col-min-width: 15rem; }
  .grid-auto-lg\@lg { --col-min-width: 20rem; }
  .grid-auto-xl\@lg { --col-min-width: 25rem; }

  .grid-auto-cols\@lg { grid-template-columns: repeat(auto-fit, minmax(0, 1fr)); }

  @for $i from 1 through $grid-columns {
    .col-#{$i}\@lg  { grid-column-end: span #{$i}; }
    .col-start-#{$i}\@lg { grid-column-start: #{$i}; }
    .col-end-#{$i+1}\@lg { grid-column-end: #{$i+1}; }
  }

  .col-start-auto\@lg { grid-column-start: auto; }
  .col-end-auto\@lg { grid-column-end: auto; }
}

@include breakpoint(xl) {
  .grid-auto-xs\@xl { --col-min-width: 8rem; }
  .grid-auto-sm\@xl { --col-min-width: 10rem; }
  .grid-auto-md\@xl { --col-min-width: 15rem; }
  .grid-auto-lg\@xl { --col-min-width: 20rem; }
  .grid-auto-xl\@xl { --col-min-width: 25rem; }

  .grid-auto-cols\@xl { grid-template-columns: repeat(auto-fit, minmax(0, 1fr)); }

  @for $i from 1 through $grid-columns {
    .col-#{$i}\@xl  { grid-column-end: span #{$i}; }
    .col-start-#{$i}\@xl { grid-column-start: #{$i}; }
    .col-end-#{$i+1}\@xl { grid-column-end: #{$i+1}; }
  }

  .col-start-auto\@xl { grid-column-start: auto; }
  .col-end-auto\@xl { grid-column-end: auto; }
}
Enter fullscreen mode Exit fullscreen mode
文章来源:https://dev.to/codyhouse/flash-grid-learn-css-grid-by-building-a-grid-system-2c4f
PREV
CSS 中的 Ubuntu 终端
NEXT
如何通过写文章赚到 600 美元——从零开始到天才。还有一件事: