前言
-
1、本文中的绝大部分内容来源于以下参考资料:
-
2、有一些好的 demo不再重复写,引用原文链接做参考
一、简介
2011年发布 CSS Grid第一版; 2017年,主要的现代浏览器,如Chrome、Firefox、Safari和Edge,都支持了CSS Grid; 2020 年 12 月 18 日 W3C 发布了 css-grid 第二版的发布草案。 以下是 w3c中的说明: 网格布局通过使用网格来控制其内容的布局:一组相交的水平线和垂直线,为网格容器的内容创建大小和定位坐标系。在网格布局模型中,网格容器的子级可以放置在预定义的灵活或固定大小的布局网格中的任意槽中。 网格布局是 CSS 的布局模型,具有强大的能力来控制框及其内容的大小和位置。与面向单轴的灵活框布局不同,网格布局针对二维布局进行了优化:是在两个维度上对齐内容的布局。
二、特点
- 网格强制执行二维对齐,使用自上而下的布局方法,允许项目的显式重叠,并具有更强大的跨越功能。(而Flexbox 专注于轴内的空间分布,使用更简单的自下而上的布局方法,可以使用基于内容大小的换行系统来控制其辅助轴,并依赖底层标记层次结构来构建更复杂的布局)
- 网格布局可用于智能地调整网页中元素的大小。(fr)
- 网格的结构、行和列纯粹在 CSS 中定义,可天然减少布局用的 dom
- repeat函数可以重复布局。
- cell 单元格支持命名
三、概念
3.1 容器和项目(container & item)
xml
<div class="container">
<div class="child" ><p>我是第一个</p></div>
<div class="child" ><p>我是第二个</p></div>
</div>
container 容器 指父级dom 。item 项目: 是指容器中的第一个子元素。(p 就是个 p,它不是 item)。
3.2 行和列(column & row)
网格的轨道(行和列)可以通过显式网格属性显式声明和调整大小,也可以在将项目放置在显式网格之外时隐式创建。容器里面的水平区域称为"行 "(row),垂直区域称为"列"(column)。
3.3 网格线和单元格
行和列的交叉区域,称为"单元格"(cell)。
3.4 网格区域
网格区域是用于布局一个或多个网格项的逻辑空间。网格区域由一个或多个相邻的网格单元组成。它由四条网格线界定,网格区域的每一侧各一条,并参与与其相交的网格轨道的大小调整。网格区域可以使用网格容器的 grid-template-areas 属性显式命名,也可以通过其边界网格线隐式引用。使用网格放置属性将网格项分配给网格区域。
四、使用
开胃小菜: grid布局可将单个父DOM 节点细分为行和列
css
...,
<style>
.wrapper {
...
display: grid;
grid-template-columns: 1fr 3fr; // 加了这行
}
.child {
border: 1px solid red;
padding: 4px;
}
</style>
<body>
<div class="wrapper">
<div class="child">1</div>
<div class="child">2</div>
<div class="child">3</div>
<div class="child">4</div>
</div>
</body>
结果如下: 说明:体会下将单个父DOM 节点细分为行和列,这在之前的任何布局中都是没有过的。这里只需要将父div,设好column 是 1::3 的比例,即可实现其子 div 都是这个比例。如果只有三个子div ,是如下图所示效果:
4.1 容器属性
4.1.1 display: grid
grid布局可将单个父DOM 节点细分为行和列。 默认情况下,CSS grid 就是单列布局,并根据项目的数量等分容器,容器高度由项目总高度决定。 此外有display: inline-grid 表示内联级别的网格容器框。
4.1.1.1 父容器有高度,均分父容器
css
<style>
...
.wrapper {
display: grid;
height: 100px;
}
</style>
<body>
<div class="wrapper">
<div class="child">1</div>
<div class="child">2</div>
</div>
</body>
说明:可以看到,两个子 div 均分父容器
4.1.1.2 父容器没高度,由子决定其高度,和默认的流式布局效果一样
css
<style>
...
.wrapper {
display: grid;
/* height: 100px; */
}
</style>
<body>
<div class="wrapper">
<div class="child">1</div>
<div class="child">2</div>
</div>
</body>
4.1.2 grid-template-columns 和 grid-template-rows
w3c 原文:The grid-template-columns property specifies the track list for the grid's columns, while grid-template-rows specifies the track list for the grid's rows (ps: 其中的 track list 就是指column 和 row)
默认情况下,CSS Grid 将创建单列布局。可以使用 grid-template-columns 属性指定列。其中单位"fr",是指"fraction", 可简单理解(等分的情况下)为将父容器要分的 "份数"。相比于 "%","fr"是柔性的,更灵活,而"%"是刚性的,可参考文章这个 👻溢出demo, 总的来说:列不会缩小到其最小内容宽度以下,类似于 flex布局中的flex-flow。 grid-template-columns 和 grid-template-rows 是显式指定列/行的数量和大小,他们的值完全一样。这里以 grid-template-columns 为例,列举一些常用值,可查看w3c中支持的所有值
4.1.2.1 固定宽度
js
// 固定宽度的三列
grid-template-columns: 100px 100px 100px
4.1.2.2 fr(fraction),自适应宽度
js
// 撑满容器的三列,列宽比例是 1 :2 :1
grid-template-columns: 1fr 2fr <img src="1fr" alt="" width="50%" />
4.1.2.3 百分比(%)
js
grid-template-columns: 50% 50% 25%
说明:% 和 fr 的区别, demo-frComparePercent 或者参考 文章例子
4.1.2.4 repeat() 函数
js
// 等分 5 列
grid-template-columns: repeat(5, 1fr);
// 等同于
grid-template-columns: 1fr 1fr 1fr 1fr 1fr;
4.1.2.5 minmax()
js
// 最小 100px,最大 auto, auto 表示大小将取决于内容的大小
grid-auto-rows: minmax(100px, auto);
4.1.2.6 subgrid
js
// 创建嵌套网格,使用父网格的轨道。(demo-gridTemplateColumns-subgrid)
grid-template-columns: subgrid
4.1.3 grid-auto-columns 和 grid-auto-rows
指的是除显式指定的列/行以外的行/列,如果一个表格项目被定位在没有使用 grid-template-columns 显式指定尺寸的列中,隐式的 grid 轨道就会被创建出来支撑它 (demo-Implicit)
4.1.4 grid-template-area
每个项目要设置 grid-area,非常直观,适合显式的行列数固定的布局(demo-gridTemplateArea)
4.1.5 grid
grid 和 grid-template 属性是可用于同时设置所有三个显式网格属性(grid-template-rows、grid-template-columns 和 grid-template-areas)的简写
4.1.6 gap(空隙控制)
在网格内的所有列和行之间添加固定的空间量(可使用 demo-gridTemplateArea 查看例子)
4.1.7 grid-auto-flow (怎么排列)
- 控制自动放置算法的工作方式,准确指定自动放置的项目如何流入网格。
- 可取三个值:[ 'row' | 'column'] | dense
- row: 自动按行排序;
- column:自动按列排序;
- dense: "稠密",自动填补之前的网格空白
- 可以两个关键字同时使用,比如 grid-auto-flow: column row, 意为先行后列
4.1.8 justify/align/place-items (项目在轴线的位置) 轴线 demo
4.1.9 justify/align/place-content (整个内容区域在轴线的位置) 轴线 demo
4.2 项目属性
4.2.1 grid-column/row(怎么占格)
- 是grid-column/row-start/end 的简写,
- 线轴序号从 1 开始,而不是 0
- grid-column: 1 / -1, 表示从头到尾,也可以倒着写
- 可以用网格线号/网格线名 (demo-classicLayout)
4.2.2 grid-area (指定项目所占区域)
是 grid-row 和 grid-column 的简写,举个例子:
css
grid-area: 2/4
/* 等同于* /
grid-row: 2; grid-column: 4;
/* 等同于* /
grid-row-start: 2
grid-row-end: 3
grid-column-start: 4
grid-column-end: 5
4.2.3 justify/align/place-self
设置单个项目在其布局容器相应轴中的对其方式 align-self综合例子
五、其他
5.1 布局顺序问题
键盘操作 是走Dom 顺序,grid 布局是视觉顺序,一般情况下应使视觉顺序和 dom 顺序一致 (键盘操作问题)
5.2 使用 gird 布局,有些不生效的属性
网格容器不是块容器,因此一些基于块布局假设而设计的属性不适用于网格布局的上下文
容器子元素(项目)的float、display: inline-block、display: table-cell、vertical-align和column-*等设置都将失效 float 和clear 对网格项没有影响。但是,浮动属性仍然会影响网格容器子级上显示的计算值,因为这发生在确定网格项之前。 ::first-line 和 ::first-letter 伪元素不适用于网格容器
5.3 网格项重叠 使用 z-index
当网格项放置在相交的网格区域中时,或者甚至由于负边距或定位而放置在非相交的区域中时,网格项可能会重叠。z-index 属性可以轻松地用于控制网格项的 z 轴顺序
5.4 网格线的索引是从 1 开始的
5.6 嵌套 (demo-subgird)
网格项本身可以是一个网格容器,通过给它设置 display: grid。在一般情况下,该嵌套网格内容的布局将独立于它参与的父网格的布局。 在某些情况下,多个网格项的内容可能需要彼此对齐。嵌套网格可以将其行和/或列的定义推迟到其父网格容器,从而使其成为子网格。在这种情况下,子网格的网格项参与调整父网格的大小,从而允许两个网格的内容对齐 子网格由 grid-template-rows 或 grid-template-column 的 subgrid 关键字建立,并且可以在任一轴或两个轴上进行子网格化。没有子网格轴的网格是独立网格.
5.7 极简水平垂直居中写法
css
.container {
display: grid;
place-content: center;
}
5.8 显式命名
虽然网格线始终可以通过其数字索引来引用,但线名称可以使网格放置属性更易于理解和维护。行名称可以使用 grid-template-rows 和 grid-template-columns 属性显式指定,也可以使用 grid-template-areas 属性通过命名网格区域隐式指定。
六、最后
文中 13 个 demo,请各位看官在 css-grid-demo 自取, 如果对你有帮助的,点个赞就是对我最大的支持 🙏