多图细说 CSS grid 网格布局父元素容器相关属性

笔记哥 / 04-17 / 29点赞 / 0评论 / 696阅读
grid 网格布局与 flex 弹性盒子布局一样,都需要控制 `容器` 跟 `子元素` 的样式才能做出想要的效果,部分场景只控制 `容器` 样式也行。 ## grid 样式属性 一大堆 `属性` 来袭~~ 与网格相关的 CSS 属性有一大堆,毕竟要同时控制行和列(行、列也被称为 `网格轨道` `grid track`)。 ### 容器(父元素)相关的 CSS 属性 `display: grid` 设置容器为网格布局。 `grid-template-columns` 设置列宽(可固定、百分比、`fr` 单位或函数)。 `grid-template-rows` 设置行高。 `grid-template-areas` 通过命名区域定义布局结构。 `grid-template` 简写属性: grid-template-rows 、 grid-template-columns 与 grid-template-areas。 `column-gap` 设置列间距。 `row-gap` 设置行间距。 `gap` 简写属性:column-gap、row-gap。 `grid-auto-columns` 设置隐式创建(超出定义列)的列宽。 `grid-auto-rows` 设置隐式创建(超出定义行)的行高。 `grid-auto-flow` 控制自动放置子元素的流向。 `grid` 简写属性,可同时设置显式网格属性 grid-template-rows 、 grid-template-columns 和 grid-template-areas,隐式网格属性 grid-auto-rows 、 grid-auto-columns 和 grid-auto-flow。 `justify-items` 控制所有子元素在 **行方向** 的对齐方式(默认 `stretch`)。 `align-items` 控制所有子元素在 **列方向** 的对齐方式(默认 `stretch`)。 `justify-content` 当网格总宽度小于容器时,控制整体水平对齐。 `align-content` 当网格总高度小于容器时,控制整体垂直对齐。 ### 子元素相关的 CSS 属性 `grid-column` 设置子元素占据的列范围(简写属性)。 `grid-row` 设置子元素占据的行范围。 `grid-area` 指定子元素属于哪个命名区域或简写位置。 `justify-self` 覆盖容器的 `justify-items`,控制单个子元素的行对齐。 `align-self` 覆盖容器的 `align-items`,控制单个子元素的列对齐。 `order` 调整子元素的显示顺序(类似 Flexbox)。 `z-index` 控制子元素的层叠顺序。 ### grid 相关的函数/单位 `fr` 剩余空间分配单位(类似 Flexbox 的 `flex-grow`)。 `repeat()` 重复设置轨道(行/列)。 `minmax()` 设置轨道(行/列)尺寸范围。 `fit-content()` 将给定大小夹紧为可用大小。 `auto-fit`/`auto-fill` 自动填充轨道(响应式布局常用)。 ## 第一式:容器 本文中的默认代码,所有 grid 属性都是在此基础上增加: ```html
1
2
3
``` ### display: grid 让容器变身为网格布局 与 flex 一样,网格布局也是从 `display` 开始, display 作用就是控制元素显示方式,使用率位居第二。 ```css .box { display: grid; } ``` 显示效果: ![](https://cdn.res.knowhub.vip/c/2504/17/4d590909.png?G1MAAMTsdJzIJxGq26hD2jvFHc2ARBVBpZ71es9Z%2byb6fhdIis9offr%2b8IfWp5PVjFpIIIaEoLmgwtQEKTCr5Ms0ruE%3d) 注意第二个盒子看红色虚线,这个是 Chrome 浏览器的辅助显示 grid 网格线,就是 `display: grid` 将盒子分为了网格。 ### 控制网格行/列大小 默认情况网格的行和列都是 `auto`,即自动分配容器空间。 `grid-template-columns` 设置列的大小。 `grid-template-rows` 设置行的大小。 **使用固定像素值:** ```css .box { grid-template-columns: 130px 130px 130px; grid-template-rows: 80px 80px 80px; } ``` 显示效果: ![](https://cdn.res.knowhub.vip/c/2504/17/808ba029.png?G1QAAMTsdJzIi5Cm26hD2jvFHc2ARBVBpZ71es9Z%2byb6fmewxGe0Pn1%2f%2bEPr06lYhSkxuEAQfFIYSobWHIRN%2bDLWuIYD) **fr 单位:** `fr` 表示空间等份,`fr` 的值是相对于容器的可用空间计算得出,可食用浮点数值,比如 `0.5fr`。 ```css .box { grid-template-columns: 1fr 1fr 1fr; grid-template-rows: 1fr 1fr 1fr; } .box { grid-template-columns: 20% 80px 1fr; } ``` 以上代码将容器横向列分成 3 等分,纵向行也分成 3 等分,grid 网格很聪明,如果子元素太多,会自动调整,如下图第二项: 除了以上使用的单位,其他 CSS 的单位也支持,比如百分比、em、vw 等,单位也可以混着使用,比如下图第一项: ![](https://cdn.res.knowhub.vip/c/2504/17/0b53df65.png?G1UAAMTsdJzIC5Gm26hD2jvFHc1ARRpBpZ71es9Z%2byb6fmdwic9offr%2b8IvWp5NYhSkxWFAQQlIYhKtkDQxNSFavHNdw) ### 使用 repeat() 函数 如果有 10 列等分的子元素,是不是要写 10 个 1fr ? 懒惰使科学进步,重复工作交给 `repeat()` 函数,如下: ```css grid-template-columns: repeat(3, 1fr); /* 表示 3 列等分 */ grid-template-columns: repeat(20, 1fr); /* 表示 20 列等分 */ grid-template-columns: 50px repeat(4, 1fr) 50px; /* 表示第一列 50px 接着重复 4 个等分的列,最后再跟一个 50px 列 */ grid-template-columns: repeat(2, 50px 1fr) 100px; /* 表示重复 2 次 50px 1fr ,最后一个列 100px */ ``` fr 单位等分的空间如果不足以放下子元素内容,则会优先满足子元素大小,比如下图第一项: ![](https://cdn.res.knowhub.vip/c/2504/17/06d07fb0.png?G1QAAER17rxgpdnE%2bZ14TBMEEmwGJKoIKvWs1%2fP%2fa18i7xcENd%2bj9Rn7wx9anyHmB7wKQYMi%2bVLhMJJgKmdVU4flNQI%3d) **repeat()关键字:** `auto` 与 1fr 等效,表示等分空间。 `auto-fill` 有剩余空间会使用空行/列占位。 `auto-fit` 有剩余空间会拉伸现有行/列填充空间。 `max-content` 列宽由单元格内最长文本决定。 `min-content` 列宽由内容最小宽度决定。 使用方式如下: ```css grid-template-columns: repeat(3, auto); /* 效果与 repeat(3, 1fr) 相同 */ grid-template-columns: repeat(auto-fill, minmax(100px, 1fr)); /* 自动填充列,每列最小 100px,最大 1fr */ grid-template-columns: repeat(auto-fit, minmax(100px, 1fr)); /* 自动适应列,每列最小 100px,最大 1fr */ grid-template-columns: repeat(3, max-content); /* 列宽由单元格内最长文本决定 */ grid-template-columns: repeat(3, min-content); /* 列宽由内容最小宽度决定 */ ``` `auto-fill` 与 `auto-fit` 差异:容器空间过剩时,`auto-fill` 会创建额外的空行/列,而`auto-fit`会拉伸现有行/列填充空间。 `max-content` 与 `min-content` 差异: `max-content` 会尽可能用多的把内容放下(尽量放在一行中),`min-content` 会用尽可能少的空间存放内容。 效果如下: ![](https://cdn.res.knowhub.vip/c/2504/17/29138b3b.png?G1QAAMTW3DgpSNBH22gDdWfqnTYDElUElXrW6917rpvo%2b0NYND%2b9thHrwx9qG0HmJztIWIwVyRewsxVzHAm4ADA0zx4%3d) 注意:本例中取消了子元素的宽高设置。 ### 使用 minmax() 函数 此函数包含两个参数,`最小值` 和 `最大值`,一般用于响应式布局,控制子元素最大宽度和最小宽度,使用方法参考上图。 此函数也可以单独使用,比如: ```css grid-template-columns: minmax(20px, auto) 1fr 1fr; ``` ### 使用 fit-content() 函数 计算规则:`min(最大尺寸, max(最小尺寸, argument))` 首先用传入的 `参数` 与子元素的 `最小尺寸` 比较,取两者 `最大值`; 再用比价出的 `最大值` 与子元素的 `最大尺寸` 比较,取 `最小值`。 ```css grid-template-columns: fit-content(80px) 1fr; /* 第1列自适应但不超过80px,第2列占剩余空间 */ grid-template-columns: repeat(3, fit-content(80px)); /* 第1、2、3列自适应但不超过80px */ ``` 效果如下: ![](https://cdn.res.knowhub.vip/c/2504/17/226ac124.png?G1UAAMT0bJzoaWjVNvqh%2f4lHQjNQkUZQqWe93nv3aUTf7wzO8Zl9LD8fftHHciomMCUGF2SEkBSGAquaQ0qoKiZicU8H) ### grid-template-areas 设置网格区域 此属性的作用就是划地盘,老大(容器盒子)划分网格区域地盘命名,然后马仔(子元素)使用 `grid-area` 来插旗说某个地盘是谁的。 `grid-template-areas` 需要结合 `grid-area` 使用,使用方法如下: ```css .box { display: grid; grid-template-areas: "A A A" "B C C" "B D D"; /*区域划分为 三行 三列(A的地盘占了整个第一行,B占了第二行和第三行的第一列,C占了第二行剩余空间,D占了第三行剩余空间)*/ grid-template-columns: repeat(3, 1fr); /* 指定容器分为 3 等分 */ grid-template-rows: repeat(3, 1fr); /* 指定容器分为 3 等分 */ } .box .item { border: 2px solid rgba(0,255,0,1); } .box .item:nth-child(1) { grid-area: A; /* 第 1 个子元素说它要 A 地盘 */ } .box .item:nth-child(2) { grid-area: B; /* 第 2 个子元素说它要 B 地盘 */ } .box .item:nth-child(3) { grid-area: C; /* 第 3 个子元素说它要 C 地盘 */ } .box .item:nth-child(4) { grid-area: D; /* 第 4 个子元素说它要 D 地盘 */ } ``` 如果这时候再来个马仔 E 说它也要 A 地盘怎么办?嘿...老大就会说那你也去 A 地盘站着吧~~,然后 A 和 E 就叠加在一起了,如下图二: ```css .box .item:nth-child(5) { /* 第 1 、5 子元素同时要 A 地盘 */ grid-area: A; padding-left: 30px; } ``` 效果: ![](https://cdn.res.knowhub.vip/c/2504/17/2b198a88.png?G1QAAMTydJz46%2fHku406fJsoEpoBiSqCSj3r9Z6z9i3y%2fU4wx2e0Pn1%2f%2bEPr00WtwKoQVGQEf1UYFElTDaaZxlQY13A%3d) 可使用 `.` 来标记未命名区域,表示这地方是无主的,谁都不能占用,比如: ```css .box { grid-template-areas: "a a ." "a a ." ". b c"; } ``` 以上代码 第一行 、 第二行 最后一列 及 第三行 第一列 都是未命名区域, ### grid-template 简写属性 使用关键字 `none`: ```css grid-template: none; ``` 同时设置行/列,需注意必须同时设置两个值,指定一个值是无效的。 ```css grid-template: 100px 1fr / 50px 1fr; /* 等价于 */ grid-template-rows: 100px 1fr; grid-template-columns: 50px 1fr; ``` 使用 `grid-template` 划分地盘: ```css grid-template: "a a a" 20% "b b b" auto; /* 等价于 */ grid-template-rows: 20% auto; grid-template-columns: none; grid-template-areas: "a a a" "b b b"; ``` 使用 `grid-template` 设置所有属性: ```css grid-template: "A A A" 1fr "B C C" 1fr "B D D" 1fr / 1fr 1fr 1fr; /* 等价于 */ grid-template-rows: 1fr 1fr 1fr; grid-template-columns: 1fr 1fr 1fr; grid-template-areas: "A A A" "B C C" "B D D"; ``` 还可定义 `行线命名`,具体使用方法需结合子元素 `grid-row` 来使用,后文再看,使用方法如下: ```css grid-template: [header-left] "head head" 30px [header-right] [main-left] "nav main" 1fr [main-right] [footer-left] "nav foot" 30px [footer-right] / 120px 1fr; ``` ### 定义行列间距 使用 `column-gap` 定义列间距,使用 `row-gap` 定义行间距,让子元素别离太近,有点边界感: 它俩都可食用所有 CSS 支持的单位~ ```css .box { column-gap: 30px; row-gap: 20px; } ``` 效果: ![](https://cdn.res.knowhub.vip/c/2504/17/3888bde3.png?G1MAAETn9LyUSmDIvtMdbIlTE20GJKoIKvWs13vO2jfR9weDJT%2bj9Rn7wx9an0HqF9yIwQpB0sXgEJViSO7qqKh5jQA%3d) 使用 `gap` 属性合并行列间距,以下代码与上面等效: ```css .box { gap: 20px 30px; } ``` `gap: 20px` 只有一个值时,表示行列间距都为 20px。 ### 设置隐式行列大小 什么是隐式行列大小: `grid-template-columns` 声明的是显示的列大小,`grid-auto-columns` 声明的是隐式行列大小。 所谓显示就是明确看得到的列结构,而隐式就是没有明确声明的列大小。 比如: ```css .box { display: grid; grid-template-areas: "A A A A"; grid-template-columns: 40px 1fr 50px; /* 显式 3 列 */ grid-auto-columns: 100px; /* 隐式列宽 100px */ } ``` 表格声明了 4 列,但只显式声明了前 3 列宽度,第 4 列隐式声明了宽度为 100px。 看下图左右两个容器的最后一个子元素 D 区别: ![](https://cdn.res.knowhub.vip/c/2504/17/ba6408ca.png?G1UAAETn9LyUyhDCvtMdbIlTE20GKtIIKvWs13vO2jfR9weDJT%2bj9Rn7wy9an0HVFW7E4ApBCsXgEDG1khhFXHGx5jUC) `grid-auto-rows` 用法与 `grid-auto-columns` 一致,都是用于隐式声明。 可使用关键字或函数设置隐式声明: ```css grid-auto-rows: minmax(100px, auto); grid-auto-rows: fit-content(20%); grid-auto-rows: min-content max-content auto; ``` 其关含义可参考上文~~ ### 设置子元素的流向 网格布局默认按行排列子元素,可通过 `grid-auto-flow` 控制自动放置子元素的流向,其值有三个关键字,用法如下: ```css .box { display: grid; gap: 10px; grid-template-columns: repeat(3, 1fr); grid-template-rows: repeat(5, minmax(40px, auto)); } .box:nth-child(1) { grid-auto-flow: row;/* 默认行为 */ } .box:nth-child(2) { grid-auto-flow: column;/* 按列排列子元素 */ } .box:nth-child(3) { grid-auto-flow: dense row;/* 启用“密集填充”模式,尝试填充网格中的空隙 */ /* grid-auto-flow: dense; 与 grid-auto-flow: dense row; 相同 */ } .box:nth-child(4) { grid-auto-flow: dense column;/* 启用“密集填充”模式,尝试填充网格中的空隙 */ } .box .item:nth-child(1), .box .item:nth-child(2) { /* 控制第一个和第二个子元素宽高都占用 2 行 2 列 */ grid-column: auto / span 2; grid-row: auto / span 2; } ``` `dense` 密集模式就是尝试填充网格中的空隙,只要子元素能放得下,就往空隙中塞,比如: ![](https://cdn.res.knowhub.vip/c/2504/17/a47c3d97.png?G1QAAMTW3DgpD0Fk22gDdWfqnTYDElUElXrW6917rpvo%2b0Mgmp9e24j14Q%2b1jSArJ4qTQAyK5NlRoApjT3bxAXZInj0A) ### 简写属性 grid 用于组合 `grid-template-rows`、`grid-template-columns`、`grid-template-areas`、`grid-auto-rows`、`grid-auto-columns` 和 `grid-auto-flow`。 **grid 简写最多覆盖三个属性,无法同时覆盖六个属性!!!** grid 属性值语法规则: ```css /* <'grid-template'> values */ /* <'grid-template-rows'> / [ auto-flow && dense? ] <'grid-auto-columns'>? values */ /* [ auto-flow && dense? ] <'grid-auto-rows'>? / <'grid-template-columns'> values */ ``` 看以下各种简写: ```css grid: none; /* 不设置任何属性 */ ``` * * * ```css grid: "a" 100px "b" 1fr; /* 等价于 */ grid-template-rows: 100px 1fr; grid-template-areas: "a" "b"; ``` * * * ```css grid: [line-name1] "a" 100px [line-name2]; /* 等价于 */ grid-template-rows: [line-name1] 100px [line-name2]; grid-template-areas: "a"; ``` * * * ```css grid: "a" 200px "b" min-content; /* 等价于 */ grid-template-rows: 200px min-content; grid-template-areas: "a" "b"; ``` * * * ```css grid: 100px / 200px; /* 等价于 */ grid-template-rows: 100px; grid-template-columns: 200px; ``` * * * ```css grid: 200px / auto-flow; /* 等价于 */ grid-template-rows: 200px; grid-auto-flow: column; ``` * * * ```css grid: 30% / auto-flow dense; /* 等价于 */ grid-template-rows: 30%; grid-auto-flow: column dense; ``` * * * ```css grid: repeat(3, [line1 line2 line3] 200px) / auto-flow 300px; /* 等价于 */ grid-template-rows: repeat(3, [line1 line2 line3] 200px); grid-auto-flow: column; grid-auto-columns: 300px; ``` * * * ```css grid: auto-flow / 200px; /* 等价于 */ grid-auto-flow: row; grid-template-columns: 200px; ``` * * * ```css grid: auto-flow dense / 30%; /* 等价于 */ grid-auto-flow: dense; /* 等同于 grid-auto-flow: dense row; */ grid-template-columns: 30%; ``` * * * ```css grid: auto-flow dense 40% / [line1] minmax(20em, max-content); /* 等价于 */ grid-template-columns: [line1] minmax(20em, max-content); grid-auto-flow: dense; grid-auto-rows: 40%; ``` ### 控制子元素对齐 几个控制对齐的属性与 flex 类似,这里就不多赘述了,可参考前一篇文章 `Web前端入门第 35 问:CSS 细说 flex 弹性盒子布局(多图)`。 `justify-items` 控制所有子元素在 **行方向** 的对齐方式(默认 `stretch`)。 `align-items` 控制所有子元素在 **列方向** 的对齐方式(默认 `stretch`)。 `justify-content` 当网格总宽度小于容器时(子元素没撑满时),控制整体水平对齐。 `align-content` 当网格总高度小于容器时(子元素没撑满时),控制整体垂直对齐。 本例中容器及子元素样式代码: ```css .box { display: grid; gap: 10px; } .box:nth-child(2n+1) { grid-template-columns: repeat(3, 1fr); grid-template-rows: repeat(3, 1fr); } .box .item { border: 2px solid rgba(0,255,0,1); width: 40px; height: 40px; } ``` 显示效果: ![](https://cdn.res.knowhub.vip/c/2504/17/e59150c0.png?G1UAAMTydJz4c334bqMO2kSR0AxUpBFU6lmv95y1b5HvbwTVP6P22faHX9Q%2bm0RLsCwEIxQuhAyDMhWDY2AuCBfVr9EA) ## 总结 父元素容器相关属性相关的 CSS 本文介绍完毕,作者也跟着学了一遍网格布局,以前似懂非懂的属性,现在嘛多少略知一二了,子元素相关的属性还有一大波,请看下回分解... grid 布局的规范浏览器基本都是在 2017 年之后才开始支持,所以在使用网格布局时候,如果还要兼容 2017 年之前的浏览器版本,那么网格布局可以放弃了... 参考资料:https://developer.mozilla.org/en-US/docs/Web/CSS/grid