当前位置: 首页 > news >正文

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-columngrid-row。这种方式使得布局更加灵活和易于理解,因为可以通过区域名称来指定子元素的位置和大小,而无需关心具体的行列号。

当某个区域需要跨越多行或多列时,只需在网格模板中重复该区域的名称即可。例如,在示例中,“侧边栏”区域跨越了两行,因此在第一列中连续为两个单元格指定了“侧边栏”作为它们的名称。

至于应该使用区域还是行/列来构建布局,这主要取决于具体的需求和场景。在构建具有明确语义含义和显式布局的网格时,使用区域(如通过grid-template-areasgrid-area)通常是一个更好的选择。它不仅能够使布局更加清晰易懂,还能为网格的不同部分赋予有意义的名称,从而提高代码的可维护性和可读性。

然而,当网格的行数和列数可能发生变化,或者需要更灵活地控制子元素的具体位置时,使用grid-columngrid-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 语言中非常强大的种布局&#xff0c;它提供了丰富的工具属性&#xff0c;可以轻松实现复杂且灵活的布局设计&#xff0c;因此想要完美使用CSS Grid 也有一定的难度和复杂性&#xff0c;我自己也是花了不少时间才真正掌握它的使用&#xff0c;在这篇…...

Give azure openai an encyclopedia of information

题意&#xff1a;给 Azure OpenAI 提供一部百科全书式的信息 问题背景&#xff1a; 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)

漏洞原理&#xff1a; 影响版本内默认配置模块的Nginx只需要开启缓存&#xff0c;攻击者可以通过发送包含恶意构造range域的header请求进行远程攻击造成信息泄露。 影响范围&#xff1a; Nginx 0.5.6 – 1.13.2 漏洞复现&#xff1a; 开启靶场&#xff0c;访问8080端口 中间…...

【MySQL】查询语句之inner、left、right、full join 的区别

前言&#xff1a; INNER JOIN 和 OUTER JOIN 是SQL中常用的两种连接方式&#xff0c;用于从两表活多表中提取相关的数据。两者区别主要在于返回的 结果集 如何处理 匹配 与 不匹配 的行。 目录 1、INNER JOIN 2、OUTER JOIN 3、总结 1、INNER JOIN 称为内连接&#xff0c;只…...

Submariner 部署全过程

Submariner 部署全过程 部署集群配置 broker 集群&#xff1a; pod-cidr&#xff1a;11.244.0.0/16 service-cidr 11.96.0.0/12 broker 172.100.0.109 node 172.100.0.108 集群 1&#xff08; pve3 &#xff09;&#xff1a; pod-cidr&#xff1a;10.244.0.0/16 service-…...

驼峰命名法

一、驼峰命名法简介 驼峰命名法&#xff08;Camel Case&#xff09;是一种在编程和人类语言中广泛使用的书写方式&#xff0c;通过将单词连接在一起&#xff0c;并使每个单词的首字母大写来表示复合词或短语。这种命名法有小驼峰法和大驼峰法两种变种。 二、小驼峰命名法&…...

Android IME输入法启动显示隐藏流程梳理

阅读Android AOSP 12版本代码&#xff0c;对输入法IME整体框架模块进行学习梳理&#xff0c;内容包含输入法框架三部分IMM、IMMS、IMS的启动流程、点击弹出流程、显示/隐藏流程&#xff0c;以及常见问题和调试技巧。 1. IME整体框架​​​​​​​ IME整体分为三个部分&#xf…...

Java 入门指南:JVM(Java虚拟机)——类的生命周期与加载过程

文章目录 类的生命周期类加载过程1&#xff09;载入&#xff08;Loading&#xff09;2&#xff09;验证&#xff08;Verification&#xff09;文件格式验证符号引用验证 3&#xff09;准备&#xff08;Preparation&#xff09;4&#xff09;解析&#xff08;Resolution&#xf…...

Unity射击游戏开发教程:(36)敌人关卡生成器的设计和开发

丰富多样地游戏关卡生成器能自动生成不同的关卡地图和游戏内容,以增加游戏的可玩性和挑战性。关卡生成可以基于随机算法或者预设的规则生成不同的地图布局、敌人位置、道具位置等。 定义关卡生成器WaveSpawner 如何设置通用的 Wave Spawner?我将此 Wave Spawner 脚本附加到…...

AI对汽车行业的冲击和比亚迪新能源汽车市场占比

人工智能&#xff08;AI&#xff09;对汽车行业的冲击正在迅速改变该行业的面貌&#xff0c;从智能驾驶到生产自动化&#xff0c;再到个性化的消费者体验&#xff0c;AI带来的技术革新在各个层面影响着汽车产业。与此同时&#xff0c;新能源汽车市场&#xff0c;特别是以比亚迪…...

2024年中国电子学会青少年软件编程(Python)等级考试(一级)核心考点速查卡

考前练习&#xff1a; 2024年06月中国电子学会青少年软件编程&#xff08;Python&#xff09;等级考试试卷&#xff08;一级&#xff09;答案 解析-CSDN博客 2024年03月中国电子学会青少年软件编程&#xff08;Python&#xff09;等级考试试卷&#xff08;一级&#xff09;答…...

游戏开发引擎__游戏场景(灯光,摄像机)

1.灯光 重要参数介绍 类型: 控制灯光的类型&#xff0c;有“定向”“点”“区域”和“聚光”4种模式。颜色: 控制灯光的颜色。模式: 控制灯光的光照模式&#xff0c;有“实时”“混合”和“烘焙”3种模式。强度: 控制灯光的明亮程度。间接乘数: 改变间接光的强度。阴影类型: …...

2024 Snap 新款ar眼镜介绍

2024 snap 新款ar眼镜介绍 2024 Snap 新款ar眼镜介绍 咨询合作 DataBall 项目&#xff0c;欢迎加以下微信。 助力快速掌握数据集的信息和使用方式。...

uni-app生命周期

目录 一、页面生命周期 1、onLoad 【常用】 2、onShow【常用】 3、onReady【常用】 4、onHide【常用】 5、onPullDownRefresh【常用】 6、onReachBottom【常用】 二、应用生命周期 1、onLaunch【常用】 2、onShow【常用】 3、onHide【常用】 三、组件生命周期 1、…...

LabVIEW机械产品几何精度质检系统

随着制造业的发展&#xff0c;对产品质量的要求越来越高&#xff0c;机械产品的几何精度成为衡量其品质的重要指标。为了提高检测效率和精度&#xff0c;开发了一套基于LabVIEW的几何精度质检系统&#xff0c;该系统不仅可以自动化地进行几何尺寸的测量&#xff0c;而且能实时分…...

java 检测图片链接有没有效

实际需求&#xff1a;发送调用微信图片发送接口前检验图片有效性。 在 Java 中&#xff0c;检测图片链接是否有效可以通过发送 HTTP 请求来判断服务器返回的状态码。通过 HttpURLConnection 类&#xff0c;可以轻松地实现这个功能。以下是一个简单的示例代码来检测图片链接是否…...

测试工程师学历路径:从功能测试到测试开发

现在软件从业者越来越多&#xff0c;测试工程师的职位也几近饱和&#xff0c;想要获得竞争力还是要保持持续学习。基本学习路径可以从功能测试-自动化测试-测试开发工程师的路子来走。 功能测试工程师&#xff1a; 1、软件测试基本概念&#xff1a; 学习软件测试的定义、目的…...

JavaEE---Spring IOC(2)

DI之三种注入 属性注入 构造方法注入 Setter注入 当程序中同一个类有多个对象的时候会报错解决方法如下: AutoWired和Resource的区别...

Oracle字符集

select userenv(language) from dual;如果显示如下&#xff0c;一个汉字占用两个字节 SIMPLIFIED CHINESE_CHINA.ZHS16GBK如果显示如下&#xff0c;一个汉字占用三个字节 SIMPLIFIED CHINESE_CHINA.AL32UTF8可以用以下语句查询一个汉字占用的字节长度 select lengthb(你) fr…...

RabbitMQ 常见使用模式详解

RabbitMQ 常见使用模式详解 RabbitMQ 是一个强大的消息队列中间件&#xff0c;支持多种消息通信模式&#xff0c;能够适应不同的业务场景。在这篇文章中&#xff0c;我们将详细介绍 RabbitMQ 的几种常见使用方法及其对应的场景。 1. 发布/订阅&#xff08;Publish/Subscribe&a…...

JavaEE初阶——初识EE(Java诞生背景,CPU详解)

阿华代码&#xff0c;不是逆风&#xff0c;就是我疯&#xff0c;你们的点赞收藏是我前进最大的动力&#xff01;&#xff01;希望本文内容能帮到你&#xff01; 目录 零&#xff1a;Java的发展背景介绍 一&#xff1a;EE的概念 二&#xff1a;计算机的构成 1&#xff1a;CU…...

iOS界面布局:屏幕尺寸与安全区域全面指南

引言 随着iPhone和iPad的更新迭代&#xff0c;iOS设备的屏幕尺寸和设计也在不断变化。无论是iPhone X系列的刘海屏&#xff0c;还是最新的iPhone 14&#xff0c;开发者都需要面对适配不同设备布局的问题。在项目开发中&#xff0c;导航栏、状态栏、TabBar的高度以及安全区域的…...

javascript-代码执行原理

js 是解释型语言 js 引擎执行流程 分为两个阶段: 语法分析执行阶段执行阶段涉及的数据结构: 调用栈。处理执行上下文和执行代码内存堆。给对象分配内存任务队列。暂存待执行的任务,分为宏任务队列和微任务队列语法分析 词法分析 > 语法分析 > 代码生成(字节码) …...

【C++ | tips】const Date* operator() const中这两个const有什么区别?他们的作用是什么?

const Date* operator&() const { return this; } 我们要明白operator&()这个函数是做什么的。 在C中&#xff0c;&操作符通常用于获取一个对象的地址。但是&#xff0c;有时候我们想要自定义这个行为&#xff0c;比如说&#xff0c;我们想要控制别人怎么获取…...

开放的数据时代:Web3和个人隐私的未来

在数字化和信息化的时代&#xff0c;数据隐私成为了公众关注的焦点。随着Web3技术的兴起&#xff0c;个人隐私保护进入了一个新的阶段。Web3作为去中心化的互联网架构&#xff0c;提出了对数据控制和隐私保护的新方案。本文将探讨Web3如何影响个人隐私的未来&#xff0c;并分析…...

Kafka 安全机制详解及配置指南

个人名片 &#x1f393;作者简介&#xff1a;java领域优质创作者 &#x1f310;个人主页&#xff1a;码农阿豪 &#x1f4de;工作室&#xff1a;新空间代码工作室&#xff08;提供各种软件服务&#xff09; &#x1f48c;个人邮箱&#xff1a;[2435024119qq.com] &#x1f4f1…...

渗透测试综合靶场 DC-2 通关详解

一、准备阶段 准备工具如Kali Linux&#xff0c;下载并设置DC-2靶场机。确保攻击机和靶机在同一网络段&#xff0c;通常设置为桥接模式或NAT模式。 1.1 靶机描述 Much like DC-1, DC-2 is another purposely built vulnerable lab for the purpose of gaining experience in …...

「iOS」——单例模式

iOS学习 前言单例模式的概念单例模式的优缺点单例模式的两种模式懒汉模式饿汉模式单例模式的写法 总结 前言 在一开始学习OC的时候&#xff0c;我们初步接触过单例模式。在学习定时器与视图移动的控件中&#xff0c;我们初步意识到单例模式的重要性。对于我们需要保持的控件&a…...

Selenium自动化测试面试必备:高频面试题及答案整理

自动化测试已经成为现代软件测试中不可或缺的一部分。在自动化测试中&#xff0c;Selenium是最受欢迎的工具之一&#xff0c;因为它可以模拟用户与Web应用程序的交互。因此&#xff0c;对于许多测试工程师来说&#xff0c;熟练掌握Selenium框架是非常重要的。如果你正在寻找一份…...

kettle 数据库迁移 使用分页原理实现 数据库mysql

使用 kettle 9.0 先修改配置文件: C:\Users\xx\.kettle 新增如下配置,解决mysql 空字符串 自动转 null bug KETTLE_EMPTY_STRING_DIFFERS_FROM_NULLY git地址: GitHub - 2292011451/kettle_tool 第一步: 先把要迁移的表进行读取,循环查询每个表的最大数量以及页数,追加到…...