普通视图

发现新文章,点击刷新页面。
昨天以前首页

Sass 进阶:当 CSS 学会了编程,变量函数循环全都安排上

作者 kyriewen
2026年3月18日 18:05

昨天我们用Sass告别了手工作坊,学会了变量和嵌套。今天咱们继续深入,看看Sass还有哪些骚操作——模块化、内置函数、条件循环,让你的CSS代码像程序一样聪明。准备好,我们要从“会用”进化到“玩出花”了。

前言

还记得你第一次写CSS时的样子吗?一个属性一个属性地敲,一个颜色一个颜色地复制,改个主题色就像在玩“大家来找茬”。昨天学了Sass基础,你已经能像模像样地用变量和嵌套了,感觉自己有点东西了是吧?

但Sass的真正威力远不止于此。今天我们要学的这些东西,会让你忍不住喊出:“卧槽,CSS还能这样写?”——模块化让你的代码像乐高一样拼装,内置函数让颜色和数字自动计算,循环让你批量生成样式就像打印传单。准备好了吗?上车!

一、模块化:别再写一个几千行的巨型文件了

你有没有见过那种一个文件几千行的CSS?看到就想吐对吧?维护起来更是噩梦。Sass的模块化功能就是来拯救你的。

1. @use:新一代的模块引入

以前Sass用@import,但@import有个问题:它会把你引入的所有东西都混到一个全局作用域里,变量重名就覆盖,混乱不堪。现在推荐用@use,它创建了命名空间,隔离了变量。

// _variables.scss
$primary-color: #8A2BE2;
$font-stack: 'Helvetica', sans-serif;

// _buttons.scss
@use 'variables';
.button {
  background: variables.$primary-color;  // 通过命名空间访问
  font-family: variables.$font-stack;
}

看到没,通过variables.前缀访问,清清楚楚,妈妈再也不用担心我变量重名了。

2. 下划线开头的“部分文件”

你发现上面文件名是_variables.scss,有个下划线。这是Sass的约定:下划线开头的文件是“部分文件”,不会被单独编译成CSS,只用来被别的文件引入。就像厨房里的半成品食材,不直接上桌,但做菜要用。

3. @forward:合并转发

如果你有一堆工具函数,想打包成一个入口文件让别人用,就用@forward

// _mixins.scss
@mixin flex-center { ... }

// _variables.scss
$primary: #8A2BE2;

// _index.scss
@forward 'variables';
@forward 'mixins';

// main.scss
@use 'index' as *;  // 直接使用所有转发的成员,无需命名空间

这样别人只要引入index,就能用你所有的变量和混入,方便又优雅。

二、内置函数:Sass自带的神兵利器

Sass内置了很多函数,让你能操作颜色、数字、字符串,就像JavaScript一样。这些函数能帮你省掉无数计算和手工调整。

1. 颜色函数:调色盘在手

颜色是CSS里最烦人的东西之一。你要一个颜色变暗10%?用darken()。变亮?用lighten()。混合两个颜色?用mix()

$primary: #8A2BE2;

.btn {
  background: $primary;
  
  &:hover {
    background: darken($primary, 10%);  // 变暗10%
  }
  
  &.disabled {
    background: lighten($primary, 20%);  // 变亮20%
  }
}

.card {
  border: 1px solid rgba($primary, 0.3);  // 转成半透明
}

还有adjust-hue()调整色相,saturate()增加饱和度,desaturate()降低饱和度……总之,调色不再靠肉眼,全交给Sass计算。

2. 数字函数:算清楚

percentage(0.3) 转成30%,round(3.14) 取整,min(1, 2, 3) 取最小值,max()取最大值。这些函数在处理响应式尺寸时尤其好用。

$container-width: 1200px;
$gutter: 20px;

.item {
  width: percentage(1/3);  // 33.33333%
  margin-right: $gutter;
  
  &:nth-child(3n) {
    margin-right: 0;
  }
}

3. 字符串函数:玩文字

quote()加引号,unquote()去引号,str-index()查找位置,str-insert()插入。虽然不是天天用,但需要的时候真香。

4. 检查函数:知己知彼

type-of($var)返回变量类型,unit(10px)返回单位,unitless(10px)判断是否有单位。写mixin时常用到,比如:

@mixin size($value) {
  @if unitless($value) {
    // 如果没单位,默认px
    width: #{$value}px;
  } @else {
    width: $value;
  }
}

三、控制指令:让CSS长脑子

这才是Sass最像编程语言的地方——有了条件判断和循环,你就能批量生成样式,再也不用一个一个手写了。

1. @if:聪明的条件判断

根据不同的情况输出不同的样式。

@mixin theme($mode) {
  @if $mode == 'light' {
    background: white;
    color: black;
  } @else if $mode == 'dark' {
    background: #333;
    color: white;
  } @else {
    background: gray;
    color: black;
  }
}

.light-theme { @include theme(light); }
.dark-theme { @include theme(dark); }

这个例子在真实项目中很有用,比如根据主题切换颜色。

2. @for:循环造样式

你写过这样的代码吗?

.m-1 { margin: 4px; }
.m-2 { margin: 8px; }
.m-3 { margin: 12px; }
.m-4 { margin: 16px; }
.m-5 { margin: 20px; }

写了五行手就酸了。用@for:

@for $i from 1 through 5 {
  .m-#{$i} {
    margin: #{$i * 4}px;
  }
}

一行代码生成了五个类,想生成到100也是分分钟的事。through包括结束值,to不包括。

3. @each:遍历列表

如果你要基于一个列表生成样式,比如不同颜色的按钮:

$colors: (primary: #8A2BE2, success: #28a745, danger: #dc3545);

@each $name, $color in $colors {
  .btn-#{$name} {
    background: $color;
    color: white;
    
    &:hover {
      background: darken($color, 10%);
    }
  }
}

一键生成三个按钮样式,想加新的颜色?往列表里加一项就行。

4. @while:用条件控制循环

虽然不如for常用,但遇到动态条件时很有用。比如生成一个步长递增的系列:

$i: 6;
@while $i > 0 {
  .item-#{$i} {
    width: 2px * $i;
  }
  $i: $i - 2;
}

四、实战:用Sass生成一个完整的工具类库

我们来做点实在的。比如你要做一个工具类库,包含外边距、内边距、文字颜色、背景色,而且要有不同的尺寸和状态。手动写?那得写到明年。用Sass的循环和函数,分分钟搞定。

// 定义配置
$spacing-sizes: (0, 4, 8, 12, 16, 20, 24);
$colors: (
  primary: #8A2BE2,
  success: #28a745,
  danger: #dc3545,
  warning: #ffc107
);

// 生成外边距工具类
@each $size in $spacing-sizes {
  .m-#{$size} {
    margin: #{$size}px !important;
  }
  
  .mt-#{$size} {
    margin-top: #{$size}px !important;
  }
  
  .mb-#{$size} {
    margin-bottom: #{$size}px !important;
  }
  
  .ml-#{$size} {
    margin-left: #{$size}px !important;
  }
  
  .mr-#{$size} {
    margin-right: #{$size}px !important;
  }
  
  .mx-#{$size} {
    margin-left: #{$size}px !important;
    margin-right: #{$size}px !important;
  }
  
  .my-#{$size} {
    margin-top: #{$size}px !important;
    margin-bottom: #{$size}px !important;
  }
}

// 生成颜色工具类
@each $name, $color in $colors {
  .text-#{$name} {
    color: $color !important;
  }
  
  .bg-#{$name} {
    background-color: $color !important;
  }
  
  .border-#{$name} {
    border-color: $color !important;
  }
}

这段代码编译后会生成上百个工具类,够你在项目里用一辈子。而且改一个配置,所有类自动更新,爽不爽?

五、进阶技巧:让Sass更上一层楼

1. 使用&选择器的高级玩法

&代表父选择器,除了用在伪类,还能用来生成BEM风格的类名。

.block {
  background: #f5f5f5;
  
  &__element {
    padding: 10px;
  }
  
  &--modifier {
    border: 1px solid red;
  }
}

编译成:

.block { background: #f5f5f5; }
.block__element { padding: 10px; }
.block--modifier { border: 1px solid red; }

完美符合BEM命名规范,还不用手写冗长的类名。

2. 使用@error做校验

在mixin里加参数校验,提前报错,省得调试半天不知道错在哪。

@mixin size($width, $height: $width) {
  @if unitless($width) or unitless($height) {
    @error "width和height必须带单位!";
  }
  
  width: $width;
  height: $height;
}

3. 使用@debug和@warn

调试时输出变量值,或者在即将弃用的样式上给警告。

@debug $primary-color;  // 控制台输出变量值
@warn "这个mixin快过期了,别用了";  // 警告信息

六、总结

Sass真正强大之处,在于它把CSS从“描述语言”变成了“编程语言”。通过今天的内容,你学会了:

  • 模块化:用@use@forward组织代码,告别混乱
  • 内置函数:操作颜色、数字、字符串,让样式自动计算
  • 控制指令@if判断,@for循环,@each遍历,批量生成样式
  • 高级技巧&的妙用,参数校验,调试工具

掌握了这些,你写CSS的效率能提升好几倍。更重要的是,你的样式代码会变得像程序一样有逻辑、可维护。别人还在手动改颜色,你已经用循环生成了整个主题;别人还在复制粘贴,你已经用mixin封装了所有复用逻辑。

明天我们将进入JavaScript的世界,从基础开始重新认识这门“前端灵魂语言”。无论你是想巩固基础,还是查漏补缺,都值得期待。

如果你觉得今天的文章够骚够实用,点个赞让更多人看到。有问题评论区见,我们明天见!

CSS 几何美学:从基础图形到创意绘制的艺术之旅

作者 Lee川
2026年3月15日 15:38

CSS 几何美学:从基础图形到创意绘制的艺术之旅

在 Web 开发的浩瀚星空中,CSS(层叠样式表)往往被视作排版与配色的工具。然而,在资深前端工程师的眼中,CSS 更是一支神奇的画笔。无需依赖任何外部图片资源,仅凭几行代码,我们就能在浏览器画布上勾勒出千变万化的几何图形。

本文将深入解析代码中的图形奥秘,并在此基础上拓展更多高阶画法,带您领略“纯 CSS 绘图”的无限可能。


第一章:代码解码——基础图形的构建逻辑

您提供的代码片段虽然简短,却蕴含了 CSS 绘图的三大核心原理:边框 Trick(Border Trick)圆角裁剪(Border-Radius)变换旋转(Transform)。让我们逐一拆解。

1. 三角形的魔法:边框的障眼法

代码中的 .triangle 类展示了经典的“边框绘图法”。

.triangle {
    width: 5px;
    height: 5px;
    border: 15px solid transparent;
    border-top-color: #f00;
}

原理解析: 当一个元素的宽和高极小(甚至为 0),而边框(border)很宽时,浏览器的渲染引擎会将四个边框渲染为四个梯形,并在中心交汇。

  • border 设为 transparent(透明),意味着我们只保留了边框的“形状”,隐藏了颜色。
  • 单独设置 border-top-color 为红色,就只留下了上方的梯形。
  • 由于底边极窄,这个梯形最终变成了一个完美的等腰三角形注:代码中注释掉的部分展示了四色边框的效果,那是四个不同颜色的三角形拼接成的正方形,是理解此原理的绝佳实验。

2. 扇形与圆弧:圆角的极致运用

代码提供了两种扇形画法,分别代表了两种不同的思路。

思路 A:宽高比控制 (.sector)

.sector {
    width: 100px;
    height: 100px;
    border-radius: 100px 0 0; /* 左上角半径极大,其余为0 */
    background-color: #00f;
}

通过设置 border-radius 的四个值(左上、右上、右下、左下),我们可以独立控制每个角的曲率。当左上角的半径值大于元素本身宽高时,它就会形成一个 90 度的扇形(四分之一圆)。

思路 B:边框与圆角结合 (.sector2)

.sector2 {
    border: 100px solid transparent;
    width: 0;
    border-radius: 100px;
    border-top-color: #f00;
}

这是在三角形原理基础上的进化。给一个宽为 0、边框透明的元素加上 border-radius,会让原本尖锐的边框交汇处变得圆润,从而切割出弧形边缘,形成扇形。

3. 箭头与椭圆:变换与比例

  • 箭头 (.arrow):利用 border 只保留右边和下边,再通过 transform: rotate(45deg) 旋转 45 度,两条边瞬间合二为一,形成一个指向右下方的箭头。这是对话框气泡尾部的经典实现方式。
  • 椭圆 (.oval):最简单的图形。只要 width 不等于 height,再配合 border-radius: 50%,正方形就会拉伸成完美的椭圆。

第二章:进阶扩展——解锁更多 CSS 图形秘籍

基于上述原理,我们可以进一步探索更复杂的图形绘制,无需 SVG 或 Canvas,仅用 CSS 即可实现。

1. 平行四边形 (Parallelogram)

想要让矩形“倾斜”起来?不要直接旋转整个元素(否则内容也会歪斜),请使用 skew 变换。

.parallelogram {
    width: 150px;
    height: 60px;
    background: #8e44ad;
    transform: skew(-20deg); /* 水平倾斜 -20 度 */
}
/* 如果内部有文字,需要反向倾斜回来 */
.parallelogram span {
    display: block;
    transform: skew(20deg); 
}

应用场景:科技感的数据看板、动态按钮背景。

2. 六角星 (Hexagram) / 大卫之星

这是两个等边三角形的叠加。利用伪元素 ::before::after 可以轻松实现,无需额外 HTML 标签。

.star {
    position: relative;
    width: 0;
    height: 0;
    border-left: 50px solid transparent;
    border-right: 50px solid transparent;
    border-bottom: 80px solid #f1c40f; /* 正三角 */
}
.star::before, .star::after {
    content: "";
    position: absolute;
    width: 0;
    height: 0;
    border-left: 50px solid transparent;
    border-right: 50px solid transparent;
}
.star::before {
    border-bottom: 80px solid #f1c40f;
    top: 30px; /* 调整位置以重叠 */
    transform: rotate(60deg);
}
.star::after {
    border-bottom: 80px solid #f1c40f;
    top: 30px;
    transform: rotate(-60deg);
}

原理:利用绝对定位将三个三角形(一个本体,两个伪元素)以 60 度差值旋转叠加。

3. 心形 (Heart)

心形是浪漫网页设计的标配,它由两个圆形和一个旋转的正方形组合而成。

.heart {
    position: relative;
    width: 50px;
    height: 50px;
    background-color: #e74c3c;
    transform: rotate(-45deg); /* 整体旋转 45 度 */
}
.heart::before, .heart::after {
    content: "";
    position: absolute;
    width: 50px;
    height: 50px;
    background-color: #e74c3c;
    border-radius: 50%; /* 变成圆形 */
}
.heart::before {
    top: -25px; /* 向上移半个身位 */
    left: 0;
}
.heart::after {
    left: 25px; /* 向右移半个身位 */
    top: 0;
}

视觉效果:两个圆分别位于正方形的上方和右方,旋转后完美融合成心形。

4. 对话气泡 (Speech Bubble)

结合“三角形箭头”和“圆角矩形”,我们可以快速制作聊天气泡。

.bubble {
    position: relative;
    width: 120px;
    height: 80px;
    background: #3498db;
    border-radius: 10px;
    padding: 10px;
    color: white;
}
/* 利用伪元素制作尾巴 */
.bubble::after {
    content: "";
    position: absolute;
    bottom: -10px; /* 定位到底部下方 */
    left: 20px;
    width: 0;
    height: 0;
    border-left: 10px solid transparent;
    border-right: 10px solid transparent;
    border-top: 10px solid #3498db; /* 颜色与气泡一致 */
}

5. 加载动画:旋转的圆环 (Loader)

静态图形是基础,动态图形才是灵魂。利用 border 的部分透明化加上 animation,可以制作流畅的 Loading 效果。

.loader {
    width: 40px;
    height: 40px;
    border: 4px solid #f3f3f3; /* 灰色底色 */
    border-top: 4px solid #3498db; /* 蓝色高亮 */
    border-radius: 50%;
    animation: spin 1s linear infinite;
}

@keyframes spin {
    0% { transform: rotate(0deg); }
    100% { transform: rotate(360deg); }
}

原理:一个只有顶部有颜色的圆环,通过无限旋转,视觉上就像在“吃豆人”一样转动,给用户明确的等待反馈。


第三章:为什么选择纯 CSS 绘图?

在 SVG 和 Canvas 如此强大的今天,我们为什么还要钻研 CSS 画图?

  1. 性能极致:CSS 图形由浏览器原生渲染引擎直接绘制,无需下载额外的图片资源,减少了 HTTP 请求,提升了页面加载速度。
  2. 无限缩放:基于矢量的边框和圆角特性,CSS 图形在任何分辨率屏幕(Retina屏、4K屏)下都清晰锐利,绝无锯齿。
  3. 灵活可控:通过 CSS 变量(Custom Properties)和伪类(:hover, :active),图形可以轻易地响应交互、改变颜色或形状,这是静态图片难以比拟的。
  4. 代码即设计:设计师的意图直接转化为代码,减少了切图环节,让前端开发更加流畅。

结语

从那个小小的红色三角形开始,我们看到了 CSS 蕴含的巨大能量。它不仅仅是样式的描述语言,更是一套严谨的几何构建系统。

掌握这些技巧,意味着您不再受限于素材库。无论是需要一个简单的下拉箭头,还是一个复杂的动态徽章,您都可以信手拈来,用代码编织出视觉的奇迹。下一次,当您面对空白的设计稿时,请记得:您的键盘,就是最强大的画笔。

Grid 网格布局:二维世界的布局王者,像下围棋一样掌控页面

作者 kyriewen
2026年3月15日 11:22

如果说Flexbox是“一维战神”,擅长排排坐,那Grid就是“二维霸主”,能同时操控行和列。今天我们就来下这盘“布局围棋”,用网格思想彻底重构网页,让复杂布局变得像填格子一样简单。

前言

还记得小时候玩的方格本吗?一行一行,一列一列,规规矩矩。Grid布局就是把这种“方格本”思维带到了CSS里。你可以在页面上画出任意行、任意列,然后把元素放进去,想放哪格放哪格,甚至可以合并单元格——就像Excel表格,但比Excel灵活一万倍。

Grid是CSS布局的终极武器,尤其适合做页面整体架构、卡片墙、仪表盘这类需要同时控制行和列的场景。如果说Flexbox是特种兵,擅长单兵作战,那Grid就是指挥官,能调动千军万马。

一、Grid的核心概念:容器与项目,行与列

和Flexbox类似,Grid也是作用于父容器和直接子项目。只要在父元素上设置display: griddisplay: inline-grid,你就开启了一个网格世界。

.container {
  display: grid;
}

默认情况下,网格只有一列,行高由内容决定。要真正“画”出网格,你需要用grid-template-rowsgrid-template-columns定义行和列。

二、定义网格:画出你的棋盘

1. 固定行高和列宽

你可以用各种单位定义行列的尺寸,比如像素、百分比、em等。

.container {
  display: grid;
  grid-template-columns: 200px 200px 200px;  /* 三列,每列200px */
  grid-template-rows: 100px 150px;           /* 两行,第一行100px,第二行150px */
}

这样你就画了一个3列2行的网格,一共6个格子。项目会按顺序自动填充每个格子,就像表格里从左到右、从上到下填数据一样。

2. fr单位:分蛋糕神器

Grid引入了fr单位(fraction的缩写),表示剩余空间的比例分配。这比Flexbox的flex-grow更直观。

.container {
  display: grid;
  grid-template-columns: 1fr 2fr 1fr;  /* 三列,中间占两份,两边各占一份 */
}

如果父容器宽度是1200px,那么第一列占300px,第二列600px,第三列300px。fr可以和固定单位混用,比如200px 1fr 2fr,浏览器会先分配200px,剩下的按比例分。

3. repeat() 函数:偷懒必备

如果你要定义很多等宽的列,手动写很累。repeat()函数来救场。

.container {
  grid-template-columns: repeat(3, 1fr);  /* 三列等宽,相当于 1fr 1fr 1fr */
  grid-template-rows: repeat(4, 100px);   /* 四行,每行100px */
}

repeat()还可以组合不同模式,比如repeat(2, 100px 1fr)表示重复两次“100px 1fr”的序列,最终得到四列:100px、1fr、100px、1fr。

4. minmax():给尺寸一个范围

有时候我们希望列宽能在一定范围内弹性变化,比如最小200px,最大自适应。minmax()搞定。

.container {
  grid-template-columns: minmax(200px, 1fr) 2fr;  /* 第一列最小200px,可以放大到1fr,第二列固定2fr */
}

5. auto-fill 与 auto-fit:响应式利器

当列数不确定时,可以用auto-fillauto-fit配合minmax实现类似“流动布局”的效果。

  • auto-fill:尽可能多地填充列,即使某些列是空的。
  • auto-fit:也是尽可能多地填充,但会把空列收缩为0,让有内容的列伸展。
.container {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}

这段代码的意思是:每列最小200px,如果容器足够宽,就放尽可能多的列,并且每列等宽;当容器变窄时,列数自动减少,每列仍不小于200px。这就是纯CSS实现的响应式卡片墙!

三、网格线:定位的坐标系

每个网格都由网格线划分。比如3列有4条纵向网格线(从1开始编号),2行有3条横向网格线。你可以用这些线来精确放置项目。

.item {
  grid-column-start: 1;
  grid-column-end: 3;   /* 从第1条纵向线跨到第3条线,即占据前两列 */
  grid-row-start: 1;
  grid-row-end: 3;      /* 从第1条横向线跨到第3条线,即占据前两行 */
}

简写为:

.item {
  grid-column: 1 / 3;
  grid-row: 1 / 3;
}

也可以从哪条线开始,并指定跨度:

.item {
  grid-column: 1 / span 2;  /* 从第1列开始,跨2列,等同于1/3 */
  grid-row: 1 / span 2;
}

网格线也可以命名,比如grid-template-columns: [main-start] 1fr [main-end],然后使用命名来定位。

四、网格区域:给格子起名字

如果你觉得用线编号不够直观,可以给网格区域命名。用grid-template-areas属性来划分区域。

.container {
  display: grid;
  grid-template-columns: 200px 1fr 200px;
  grid-template-rows: 100px 1fr 100px;
  grid-template-areas:
    "header header header"
    "sidebar content aside"
    "footer footer footer";
}
.header {
  grid-area: header;
}
.sidebar {
  grid-area: sidebar;
}
.content {
  grid-area: content;
}
.aside {
  grid-area: aside;
}
.footer {
  grid-area: footer;
}

这个布局清晰得像图纸一样,每个区域的名字直接对应一个网格单元格。注意,grid-template-areas里的每个单元格必须填满,不能有空洞;可以用.表示空单元格。

五、间距与对齐:让网格透气

1. 行列间距

gap属性设置网格线之间的间距,可以分别设置行间距和列间距:

.container {
  gap: 20px;            /* 行列间距都是20px */
  row-gap: 10px;        /* 单独设置行间距 */
  column-gap: 15px;     /* 单独设置列间距 */
}

2. 项目在单元格内的对齐

项目默认填满整个单元格,但你可以控制它们的位置。

  • justify-items:控制项目在单元格内水平方向的对齐(左中右)。
  • align-items:控制项目在单元格内垂直方向的对齐(上中下)。
  • 取值:startendcenterstretch(默认)。
.container {
  justify-items: center;   /* 所有项目水平居中 */
  align-items: center;     /* 所有项目垂直居中 */
}

如果想单独控制某个项目,用justify-selfalign-self

3. 整个网格在容器内的对齐

如果网格的总尺寸小于容器,可以用justify-contentalign-content控制网格整体的对齐,类似于Flexbox。

.container {
  justify-content: center;   /* 网格整体水平居中 */
  align-content: center;     /* 网格整体垂直居中 */
}

取值同样是startendcenterspace-betweenspace-aroundspace-evenly

六、实战:用Grid搭建常见布局

1. 经典三栏布局(圣杯)

.container {
  display: grid;
  grid-template-columns: 200px 1fr 200px;
  gap: 20px;
}

就这么简单,三栏就出来了,而且中间自适应。

2. 响应式卡片墙

我们希望卡片最小200px,尽量填满容器,而且自动换行。

.container {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 20px;
}

无论容器多宽,卡片都会自动调整列数,完美响应式。

3. 不规则布局:杂志风格

比如一个封面图占两列,下方三个卡片各占一列。

<div class="magazine">
  <div class="feature">封面大图</div>
  <div class="card">卡片1</div>
  <div class="card">卡片2</div>
  <div class="card">卡片3</div>
</div>
.magazine {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;
}
.feature {
  grid-column: 1 / -1;  /* 从第一列线到最后一列线,即占满整行 */
}

-1表示最后一条网格线,很方便。

4. 后台管理仪表盘

后台常有复杂区域划分,用grid-template-areas最合适。

.dashboard {
  display: grid;
  grid-template-columns: 250px 1fr 300px;
  grid-template-rows: 80px 1fr 60px;
  grid-template-areas:
    "header header header"
    "sidebar main widgets"
    "footer footer footer";
  height: 100vh;
}

各区域对号入座,结构一目了然。

5. 叠加效果

Grid还可以让多个元素重叠。通过给它们设置相同的网格区域,然后利用z-index控制层级。

.container {
  display: grid;
  grid-template-columns: 1fr 1fr;
}
.item1 {
  grid-area: 1 / 1 / 2 / 3;  /* 占满整行 */
  background: red;
  z-index: 1;
}
.item2 {
  grid-area: 1 / 2 / 2 / 3;  /* 只占第二列 */
  background: blue;
  opacity: 0.5;
  z-index: 2;  /* 显示在上层 */
}

七、Grid vs Flexbox:怎么选?

很多人纠结什么时候用Grid,什么时候用Flexbox。其实很简单:

  • Flexbox:一维布局,适合控制元素在一条线上的排列(导航、按钮组、等分列表)。
  • Grid:二维布局,适合同时控制行和列(页面整体架构、卡片墙、仪表盘)。

它们不是替代关系,而是配合关系。你可以在Grid单元格里用Flexbox排列内部元素,也可以把Flexbox项目里再嵌套Grid。两者结合,天下无敌。

八、常见坑点与避坑指南

1. 默认不是严格的一行一列

如果只设置display: grid而不定义行列,默认只有一列,行数由项目数量决定(每个项目占一行)。所以一定要定义行列。

2. 项目会自动填充,但可能超出网格

如果项目数量超过网格单元格,会自动创建隐式网格(新行),行高默认auto。你可以用grid-auto-rows控制隐式行的高度。

.container {
  grid-auto-rows: 100px;  /* 隐式创建的行高100px */
}

3. fr 和 minmax 结合时注意死循环

minmax(200px, 1fr)的意思是:优先让列宽为1fr,但不会小于200px。这通常没问题,但如果你把所有列都设成这样,且容器总宽度小于列数*200px,就会出现溢出(因为每列都强制不小于200px)。这时可以改用auto-fitminmax的巧妙组合,或者用max-width限制。

4. gap 会占用 fr 空间

间隙是在分配fr之前扣除的。比如三列1fr,gap 20px,那么每列实际宽度 = (容器宽度 - 40px) / 3。所以计算时要考虑间隙。

5. 网格线编号从1开始,不是0

这个容易搞错。不过可以用-1表示最后一条线,比较方便。

九、总结

Grid布局是CSS给前端开发者的一份大礼,它把网页布局变成了一种直观、可预测的体验。核心要点:

  • grid-template-columnsgrid-template-rows定义网格结构。
  • frrepeat()minmax()灵活控制尺寸。
  • grid-column/grid-rowgrid-area放置项目。
  • gap控制间距,用justify/align控制对齐。
  • auto-fitminmax实现响应式。
  • 复杂布局用grid-template-areas命名,代码如设计图。

Grid不难,关键是多动手画格子。一旦你习惯了这种“下围棋”式的布局思维,你会发现以前那些棘手的布局都变成了填空题。

如果你喜欢这篇文章,欢迎点赞、收藏、分享。明天我们将进入CSS另一个重要话题——响应式设计与移动端适配,教你如何一套代码搞定手机、平板、电脑。


明日预告:响应式设计的核心:媒体查询、流式布局、移动端适配,从零构建一个全端兼容的页面。

❌
❌