CSS-Grid布局详解
前言
Grid 栅格布局 是 CSS 语言中非常强大的种布局,它提供了丰富的工具属性,可以轻松实现复杂且灵活的布局设计,因此想要完美使用CSS Grid 也有一定的难度和复杂性,我自己也是花了不少时间才真正掌握它的使用,在这篇教程中,我会分享在学习和使用 CSS Grid 时的一些关键体会和收获,通过这些希望能够帮助各位了解到 CSS Grid 的基础知识,并学会如何用它实现一些复杂的布局效果。
兼容性怎么样?
CSS Grid 是使用 CSS 构建布局的一种前言方式,实际上也并不完全是“前沿”的,自 2017 年以来,所有主流浏览器都支持它!据 caniuse 称,97.8% 的用户支持 CSS Grid(在新标签页中打开),这是算是非常出色的浏览器兼容率,Flexbox(弹性盒子) 的兼容率仅高出约 0.5%!
简介
CSS是由几种不同的布局算法组成,每种算法都针对不同类型的用户界面而设计。默认布局算法 Flow 布局专为数字文档而设计,Table表格布局专为表格数据而设计,Flexbox 专为沿单个轴分布布局而设计。
而CSS Grid 算是一种最新、最出色的布局算法,它非常强大,可以使用它来构建复杂的布局,并且可以根据许多复杂约束条件流畅地进行布局调整,在我看来CSS Grid 最不寻常的部分是网格结构、行和列完全在 CSS 中定义:

使用 grid布局之后,单个 DOM 节点被细分为行和列,上图用虚线突出显示行/列,但实际上,它们是不可见的,为了方便展示我加了border属性,在其他所有布局模式中,创建此类布局的唯一方法是添加更多 DOM 节点。例如,在表格布局中,每行都使用 <tr> 创建,该行中的每个单元格使用 <td> 或 <th> 创建:
<table><tbody><tr> <td></td><td></td><td></td></tr><tr> <td></td><td></td><td></td></tr></tbody>
</table>
与表格布局不同的是grid布局允许浏览器完全在 CSS 内部管理布局,能够随意分割容器,创建网格子元素可以用作锚点的隔间
.wrapper {display: grid;
}
默认情况下,grid布局使用单列,并根据子元素的数量根据需要创建行,这称为隐式网格,因为没有明确定义任何布局结构,工作原理如下:
隐式网格是动态的;行数将根据子项的数量添加和删除,每个子项都有自己的行,默认情况下网格父元素的高度由其子元素决定,它会动态增加和减少,有意思的是这甚至不是grid的属性,网格父元素仍然使用流布局,流布局中的块元素会垂直增长以包含其内容!只有子元素使用网格布局排列。
但是如果我们给网格一个固定的高度会怎么样?在这种情况下,整体高度将被分成大小相等的行:

使用Grid布局
默认情况下,Grid 将创建单列布局,可以使用 grid-template-columns 属性指定列:

为了清晰起见,所以这里添加了虚线
在上面的所有内容的示例中都使用了虚线来显示列和行之间的划分,在 CSS 网格中实际是没有这些虚线的。
通过给 grid-template-columns 设置两个属性值(25% 和 75%),意思是告诉 CSS grid 算法将元素分成两列。
可以使用任何有效的 CSS <length-percentage> value(在新选项卡中打开)定义列,包括px、rem、vw单位等。此外grid还可以使用一个新单位 fr 单位:

fr 可以理解为'份数'在此示例中,表示第一列应占用 1 份的空间,而第二列应占用 3份的空,这意味着整个元素总共被分为了 4 个份的空间把着看做分母,第一列占用了可用空间的 ¼,而第二列占用了 ¾。fr 单位为 CSS Grid 布局带来了 Flexbox 布局的灵活性,百分比和 <length> 值会创建硬约束,而 fr 列可以根据需要自由增长和收缩以完全占用父元素。
具体差异如下:
在这种情况下,左边第一列有一个固定宽度的图片,其宽度被明确指定为 55px。但是如果列太小而无法容纳它怎么办?
基于百分比的列是固定的,因此会出现图像溢出。
基于 fr 的列是灵活的,就算破坏了预先规定的宽度比例也不会缩小到图片内容大小以下,
更准确地说:fr 单位分配额外的空间。首先列宽将根据其内容计算,如果有剩余空间,它将根据 fr 值进行分配,这与 flex-grow 非常相似,这种灵活性在实际使用场景中是一种更好更方便的选择。
我们可以通过 gap 看到一个完美的例子。gap 是一个神奇的 CSS 属性,它在我们的网格中的所有列和行之间添加了固定量的空间。
看看在百分比和fr之间切换时会发生什么:

注意使用基于百分比的列时内容会溢出网格的父级,发生这种情况是因为百分比是使用总网格面积计算的,两列占用了父级内容区域的 100%,并且不允许缩小,当添加 16px 的间隙时列别无选择只能溢出容器。
相比之下,fr 单位是根据额外空间计算的。在这种情况下,额外空间已减少了 16px间隙,grid算法将剩余空间分配到两个网格列之间。
gapVS grid-gap
grid 首次推出时,grid-gap 属性用于在列和行之间添加空间。然而大家很快意识到,如果 Flexbox 也拥有此功能那效果将会更好,因此该属性被赋予了一个更通用的名称 gap。
如今,grid-gap 已被标记为弃用,浏览器已将其更改为 gap,这两个属性的作用完全相同,而且它们浏览器兼容率都为96%,因此无论使用的是 Flexbox 还是 CSS Grid,我都建议使用 gap 而不是 grid-gap!
隐式和显式行
如果在两列网格中添加两个以上的子元素,会发生什么情况?
上面网格增加了第二行,网格算法确保每个子元素都有自己的网格单元,它会根据需要生成新行来实现此目标,这在元素数量可变(例如照片网格)并且希望网格自动扩展的情况下非常方便,
但是,在其他情况下希望明确定义行,以创建特定的布局,就可以使用 grid-template-rows 属性来实现这一点:

通过定义 grid-template-rows 和 grid-template-columns,可以创建一个显式网格。
实用案例
使用grid布局构建一个日历:

CSS Grid 是处理此类问题的绝佳工具。我们可以将其构造为 7 列网格,每列占用 1 个单位:
.calendar {display: grid;grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr;
}
虽然上述方案也可行,但必须计算每个 1fr,这有点烦人。想象一下,如果我们有 50 列该怎么办呢?有一种更好的方法可以解决这个问题:
<style>.calendar {display: grid;grid-template-columns:repeat(7, 1fr);gap: 4px;}
</style><ol class="calendar"><li class="day">1</li><li class="day">2</li><li class="day">3</li><li class="day">4</li><li class="day">5</li><li class="day">6</li><li class="day">7</li><li class="day">8</li><li class="day">9</li><li class="day">10</li><li class="day">11</li><li class="day">12</li><li class="day">13</li><li class="day">14</li><li class="day">15</li><li class="day">16</li><li class="day">17</li><li class="day">18</li><li class="day">19</li><li class="day">20</li><li class="day">21</li><li class="day">22</li><li class="day">23</li><li class="day">24</li><li class="day">25</li><li class="day">26</li><li class="day">27</li><li class="day">28</li><li class="day">29</li><li class="day">30</li><li class="day">31</li>
</ol>

此日历是如何使用 CSS Grid 创建特定布局的简单示例,它并不适用于生产环境。
分配子元素
默认情况下,grid算法会将每个子元素分配到第一个未占用的网格单元,可以将子元素分配到想要的任何单元!子元素甚至可以跨越多行/列:

grid-row 和 grid-column 属性允许指定网格子元素应占据哪些位置,如果希望子元素占据一行或一列,可以通过其编号指定,grid-column: 3 将设置子项位于第三列。
网格子项还可以跨越多行/列,此语法使用斜线来划分开始和结束:
.child {grid-column: 1 / 4;
}
乍一看,这看起来像一个分数¼。但在 CSS 中,斜线字符不用于除法,而是用于分隔值组。在本例中,它允许我们在单个声明中设置起始列和结束列,它本质上是以下代码的简写:
.child {grid-column-start: 1;grid-column-end: 4;
}
这里有一个小小的陷阱:提供的数字是基于列数量,而不是列索引,为了方便理解,这里用一张图来解释这个更容易:

让人不解的是,虽然说是4列的网格布局,但实际上包含了5条分隔列的线。在分配子元素到网格中时,会依据这些线来确定它们的位置,如果想让一个子元素占据前3列的空间,那么它的起始位置应是第1条列线,而结束位置则需延伸到第4条列线之后。
负数行号
在左到右的语言中,习惯从左到右计数列,但是使用负数行号,实际上也可以按相反方向计数,即从右到左。
.child { grid-column: -2;
}
更有意思的是实际上你可以正数负数一起使用!!!
即使没有特别指定子元素应占据的列数,它有时也会自动跨越整个网格的宽度,这确实是一个值得注意的现象。在这种情况下,如果想要子元素从第一列线开始,并一直延伸到最后一列线,可以采用一种简便的声明方式来实现 Full-Bleed 布局
网格区域
如何使用grid布局实现如下页面结构呢?

.grid {display: grid;grid-template-columns: 2fr 5fr;grid-template-rows: 50px 1fr;
}.sidebar {grid-column: 1;grid-row: 1 / 3;
}
.header {grid-column: 2;grid-row: 1;
}
.main {grid-column: 2;grid-row: 2;
}



和之前一样,使用 grid-template-columns 和 grid-template-rows 定义网格结构。但是这里有个奇怪的声明:
.parent {grid-template-areas:'sidebar header''sidebar main';
}
它的工作原理确实非常直观还很有创意,通过一种类似于制作ASCII艺术的方式来规划网格布局。每一行代表网格中的一行,而每个“单词”或标识符则是为网格中特定区域所指定的名称。这样,整个布局在视觉上就能清晰地呈现出网格的结构。
在分配子元素到网格时,采用grid-area属性,而不是单独使用grid-column和grid-row。这种方式使得布局更加灵活和易于理解,因为可以通过区域名称来指定子元素的位置和大小,而无需关心具体的行列号。
当某个区域需要跨越多行或多列时,只需在网格模板中重复该区域的名称即可。例如,在示例中,“侧边栏”区域跨越了两行,因此在第一列中连续为两个单元格指定了“侧边栏”作为它们的名称。
至于应该使用区域还是行/列来构建布局,这主要取决于具体的需求和场景。在构建具有明确语义含义和显式布局的网格时,使用区域(如通过grid-template-areas和grid-area)通常是一个更好的选择。它不仅能够使布局更加清晰易懂,还能为网格的不同部分赋予有意义的名称,从而提高代码的可维护性和可读性。
然而,当网格的行数和列数可能发生变化,或者需要更灵活地控制子元素的具体位置时,使用grid-column和grid-row等属性可能更为合适。这些属性允许直接指定子元素应该占据哪些行和列,从而提供了更高的灵活性和控制力。
总的来说,无论是使用区域还是行/列来构建网格布局,关键在于根据具体需求和场景选择最合适的方法。
用户体验
在网格分配方面有一个很大的问题:选项卡顺序仍然基于 DOM 位置,而不是网格位置。当使用CSS Grid布局时,一个容易被忽视但非常重要的问题,特别是关于Tab键的导航顺序。在CSS Grid中,虽然可以自由地排列元素以实现视觉上的布局效果,但Tab键的导航顺序仍然是基于DOM中的元素顺序,而不是它们在网格中的视觉位置。
假设有一个包含多个按钮的网页,使用CSS Grid来布局这些按钮,使它们在视觉上呈现出一种特定的排列方式。然而,当使用键盘上的Tab键来导航这些按钮时,会发现它们并不是按照在网格中看到的顺序来被选中的。相反,它们会按照它们在HTML文档(即DOM)中出现的顺序被依次选中

为了解决这个问题,应该重新排列 DOM 中的网格子元素,使它们与视觉顺序相匹配,这样我就可以从左到右、从上到下进行切换。
CSS 开发人员也意识到这是 网格布局的一个缺陷。必须将 DOM 顺序与视觉顺序相匹配,这有点违背了将子元素分配给特定网格单元的目的!
据说是正在修复中。将来阅读顺序 CSS 属性应该允许指示浏览器忽略 DOM 顺序,并按照元素在屏幕上出现的顺序聚焦元素。
截至 2024 年 9 月,任何浏览器都尚未实现此属性
相关文章:
CSS-Grid布局详解
前言 Grid 栅格布局 是 CSS 语言中非常强大的种布局,它提供了丰富的工具属性,可以轻松实现复杂且灵活的布局设计,因此想要完美使用CSS Grid 也有一定的难度和复杂性,我自己也是花了不少时间才真正掌握它的使用,在这篇…...
Give azure openai an encyclopedia of information
题意:给 Azure OpenAI 提供一部百科全书式的信息 问题背景: I am currently dabbling in the Azure OpenAI service. I want to take the default model and knowledge base and now add on to it my own unique information. So, for example, for mak…...
Nginx越界读取缓存漏洞(CVE-2017-7529)
漏洞原理: 影响版本内默认配置模块的Nginx只需要开启缓存,攻击者可以通过发送包含恶意构造range域的header请求进行远程攻击造成信息泄露。 影响范围: Nginx 0.5.6 – 1.13.2 漏洞复现: 开启靶场,访问8080端口 中间…...
【MySQL】查询语句之inner、left、right、full join 的区别
前言: INNER JOIN 和 OUTER JOIN 是SQL中常用的两种连接方式,用于从两表活多表中提取相关的数据。两者区别主要在于返回的 结果集 如何处理 匹配 与 不匹配 的行。 目录 1、INNER JOIN 2、OUTER JOIN 3、总结 1、INNER JOIN 称为内连接,只…...
Submariner 部署全过程
Submariner 部署全过程 部署集群配置 broker 集群: pod-cidr:11.244.0.0/16 service-cidr 11.96.0.0/12 broker 172.100.0.109 node 172.100.0.108 集群 1( pve3 ): pod-cidr:10.244.0.0/16 service-…...
驼峰命名法
一、驼峰命名法简介 驼峰命名法(Camel Case)是一种在编程和人类语言中广泛使用的书写方式,通过将单词连接在一起,并使每个单词的首字母大写来表示复合词或短语。这种命名法有小驼峰法和大驼峰法两种变种。 二、小驼峰命名法&…...
Android IME输入法启动显示隐藏流程梳理
阅读Android AOSP 12版本代码,对输入法IME整体框架模块进行学习梳理,内容包含输入法框架三部分IMM、IMMS、IMS的启动流程、点击弹出流程、显示/隐藏流程,以及常见问题和调试技巧。 1. IME整体框架 IME整体分为三个部分…...
Java 入门指南:JVM(Java虚拟机)——类的生命周期与加载过程
文章目录 类的生命周期类加载过程1)载入(Loading)2)验证(Verification)文件格式验证符号引用验证 3)准备(Preparation)4)解析(Resolution…...
Unity射击游戏开发教程:(36)敌人关卡生成器的设计和开发
丰富多样地游戏关卡生成器能自动生成不同的关卡地图和游戏内容,以增加游戏的可玩性和挑战性。关卡生成可以基于随机算法或者预设的规则生成不同的地图布局、敌人位置、道具位置等。 定义关卡生成器WaveSpawner 如何设置通用的 Wave Spawner?我将此 Wave Spawner 脚本附加到…...
AI对汽车行业的冲击和比亚迪新能源汽车市场占比
人工智能(AI)对汽车行业的冲击正在迅速改变该行业的面貌,从智能驾驶到生产自动化,再到个性化的消费者体验,AI带来的技术革新在各个层面影响着汽车产业。与此同时,新能源汽车市场,特别是以比亚迪…...
2024年中国电子学会青少年软件编程(Python)等级考试(一级)核心考点速查卡
考前练习: 2024年06月中国电子学会青少年软件编程(Python)等级考试试卷(一级)答案 解析-CSDN博客 2024年03月中国电子学会青少年软件编程(Python)等级考试试卷(一级)答…...
游戏开发引擎__游戏场景(灯光,摄像机)
1.灯光 重要参数介绍 类型: 控制灯光的类型,有“定向”“点”“区域”和“聚光”4种模式。颜色: 控制灯光的颜色。模式: 控制灯光的光照模式,有“实时”“混合”和“烘焙”3种模式。强度: 控制灯光的明亮程度。间接乘数: 改变间接光的强度。阴影类型: …...
2024 Snap 新款ar眼镜介绍
2024 snap 新款ar眼镜介绍 2024 Snap 新款ar眼镜介绍 咨询合作 DataBall 项目,欢迎加以下微信。 助力快速掌握数据集的信息和使用方式。...
uni-app生命周期
目录 一、页面生命周期 1、onLoad 【常用】 2、onShow【常用】 3、onReady【常用】 4、onHide【常用】 5、onPullDownRefresh【常用】 6、onReachBottom【常用】 二、应用生命周期 1、onLaunch【常用】 2、onShow【常用】 3、onHide【常用】 三、组件生命周期 1、…...
LabVIEW机械产品几何精度质检系统
随着制造业的发展,对产品质量的要求越来越高,机械产品的几何精度成为衡量其品质的重要指标。为了提高检测效率和精度,开发了一套基于LabVIEW的几何精度质检系统,该系统不仅可以自动化地进行几何尺寸的测量,而且能实时分…...
java 检测图片链接有没有效
实际需求:发送调用微信图片发送接口前检验图片有效性。 在 Java 中,检测图片链接是否有效可以通过发送 HTTP 请求来判断服务器返回的状态码。通过 HttpURLConnection 类,可以轻松地实现这个功能。以下是一个简单的示例代码来检测图片链接是否…...
测试工程师学历路径:从功能测试到测试开发
现在软件从业者越来越多,测试工程师的职位也几近饱和,想要获得竞争力还是要保持持续学习。基本学习路径可以从功能测试-自动化测试-测试开发工程师的路子来走。 功能测试工程师: 1、软件测试基本概念: 学习软件测试的定义、目的…...
JavaEE---Spring IOC(2)
DI之三种注入 属性注入 构造方法注入 Setter注入 当程序中同一个类有多个对象的时候会报错解决方法如下: AutoWired和Resource的区别...
Oracle字符集
select userenv(language) from dual;如果显示如下,一个汉字占用两个字节 SIMPLIFIED CHINESE_CHINA.ZHS16GBK如果显示如下,一个汉字占用三个字节 SIMPLIFIED CHINESE_CHINA.AL32UTF8可以用以下语句查询一个汉字占用的字节长度 select lengthb(你) fr…...
RabbitMQ 常见使用模式详解
RabbitMQ 常见使用模式详解 RabbitMQ 是一个强大的消息队列中间件,支持多种消息通信模式,能够适应不同的业务场景。在这篇文章中,我们将详细介绍 RabbitMQ 的几种常见使用方法及其对应的场景。 1. 发布/订阅(Publish/Subscribe&a…...
生成xcframework
打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式,可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...
golang循环变量捕获问题
在 Go 语言中,当在循环中启动协程(goroutine)时,如果在协程闭包中直接引用循环变量,可能会遇到一个常见的陷阱 - 循环变量捕获问题。让我详细解释一下: 问题背景 看这个代码片段: fo…...
连锁超市冷库节能解决方案:如何实现超市降本增效
在连锁超市冷库运营中,高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术,实现年省电费15%-60%,且不改动原有装备、安装快捷、…...
2.Vue编写一个app
1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...
Rust 异步编程
Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...
React---day11
14.4 react-redux第三方库 提供connect、thunk之类的函数 以获取一个banner数据为例子 store: 我们在使用异步的时候理应是要使用中间件的,但是configureStore 已经自动集成了 redux-thunk,注意action里面要返回函数 import { configureS…...
并发编程 - go版
1.并发编程基础概念 进程和线程 A. 进程是程序在操作系统中的一次执行过程,系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中…...
【Android】Android 开发 ADB 常用指令
查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...
密码学基础——SM4算法
博客主页:christine-rr-CSDN博客 专栏主页:密码学 📌 【今日更新】📌 对称密码算法——SM4 目录 一、国密SM系列算法概述 二、SM4算法 2.1算法背景 2.2算法特点 2.3 基本部件 2.3.1 S盒 2.3.2 非线性变换 编辑…...
边缘计算网关提升水产养殖尾水处理的远程运维效率
一、项目背景 随着水产养殖行业的快速发展,养殖尾水的处理成为了一个亟待解决的环保问题。传统的尾水处理方式不仅效率低下,而且难以实现精准监控和管理。为了提升尾水处理的效果和效率,同时降低人力成本,某大型水产养殖企业决定…...
