学习本文之前,建议先学习上一篇了解父元素的相关属性。
前文对 grid 网格布局中父元素容器相关的 CSS 属性做了详细介绍,本篇将继续学习子元素相关的 CSS 属性。
网格布局的一大波样式属性,父元素占据了大半江山,子元素嘛相对就少了一些~~
本文中的中的示例基础代码:
ABCD<style> .box { margin: 20px 0; width: 400px; height: 280px; border: 2px solid #ff4757; display: grid; } .box .item { border: 2px solid rgba(0,255,0,1); }</style>
子元素相关的 CSS 属性
grid-column-start
控制子元素列从哪根线开始。grid-column-end
控制子元素列在哪条网格线结束。grid-column
简写属性 grid-column-start 、 grid-column-end。grid-row-start
控制子元素行从哪根线开始。grid-row-end
控制子元素行在哪条网格线结束。grid-row
简写属性 grid-row-start 、 grid-row-end。grid-area
指定子元素属于哪个命名区域或简写位置。justify-self
覆盖容器的 justify-items,控制单个子元素的行对齐。align-self
覆盖容器的 align-items,控制单个子元素的列对齐。order
调整子元素的显示顺序(类似 Flexbox)。z-index
控制子元素的层叠顺序。
设置子元素列的开始位置和结束位置
grid-column-start
用于设置子元素列的开始位置,从哪条网格线开始grid-column-end
用于设置子元素列的结束位置,在哪条网格线结束
以 grid-column-start 为例:
grid-column-start: auto; grid-column-start: 4; grid-column-start: span 2; grid-column-start: some-grid-area; grid-column-start: span some-grid-area; grid-column-start: span some-grid-area 3;
使用数字和关键字 span 示例:
.box { grid-template-columns: repeat(5, 1fr); grid-template-rows: repeat(5, 1fr);}.box .item:nth-child(1) { grid-column-start: B;}.box .item:nth-child(2) { grid-column-start: span 2;}
注意看右侧网格线,由于第二个子元素要占用两列,网格放不下了,所以从第二行开始。显示效果:
使用命名区域设置子元素开始位置:
.box { grid-template-areas:"A1 A1 F2 G3 G3""A1 A1 F2 B4 B4""C5 C5 C5 C5 C5""D6 D6 D6 D6 D6""E7 E7 E7 E7 E7";}.box .item:nth-child(1) { grid-column-start: F2; }.box .item:nth-child(2) { grid-column-start: span G3; }.box .item:nth-child(3) { grid-column-start: span D6 4; }
重点:不知道是我姿势不对,还是 MDN 文档有问题, grid-column-start: span G3;
和grid-column-start: span D6 4;
两种写法浏览器解析了,没报无效值,但是实际没啥效果~~头大....
不过 MDN 上找到这么一个例子:
.box { grid-template-columns: repeat(6, [col1-start] 1fr [col2-start] 3fr);}.item:nth-child(1) { grid-column: col1-start / col2-start 2;}.item:nth-child(2) { grid-row: 2; grid-column: col1-start 2 / span 2 col1-start;}
实际使用是正常可以显示的,那么grid-column-start: span D6 4;
这种写法应该是用于重复的命名行线,而不是命名区域。
同时设置列起始和结束位置:
grid-column-end 与 grid-column-start 写法一样。
使用数字比较好理解:
.box { grid-template-columns: repeat(5, 1fr); grid-template-rows: repeat(5, 1fr);}.box .item:nth-child(1) { grid-column-start: 2; grid-column-end: 4;}.box .item:nth-child(2) { grid-column-start: 2; grid-column-end: span 4;}
显示效果:
使用命名区域设置时候又出幺蛾子了,感觉命名区域设置就不能带上span
关键字~~
.box { grid-template-areas:"A1 A1 F2 G3 G4""A1 A1 F2 B4 B4""C5 C5 C5 C5 C5""D6 D6 D6 D6 D6""E7 E7 E7 E7 E7";}.box .item:nth-child(1) { grid-column-start: F2; grid-column-end: G3;}.box .item:nth-child(2) { grid-column-start: F2; grid-column-end: span G3;}.box .item:nth-child(3) { grid-column-start: F2; grid-column-end: span G3 10;}
看效果:
grid-column-end: span G3 10;
这种写法你说他无效吧,它在网格后面多绘制了 10 列,你说有效吧,又没办法理解浏览器的绘制方式。
按照 MDN 的说法,还支持 grid-column-end: 10 G3 span;
这种写法,实际效果与上面一样,还是给网格多绘制了 10 列。
但如果使用grid-template-columns: repeat(5, 1fr);
控制了网格列数,那么就不会多绘制那么多列了,但也无法理解他的绘制方式。
可能跟上面一样,用于重复的命名行线,而不是命名区域。
设置子元素行的开始位置和结束位置
grid-row-start
用于设置子元素行的开始位置,从哪条网格线开始grid-row-end
用于设置子元素行的结束位置,在哪条网格线结束
设置行的两个属性与设置列的属性一样,使用命名区域
有 span 关键字时设置行起始和结束位置还是会出幺蛾子,就不再一一演示。
看能理解的示例:
.box { grid-template-areas:"A1 A1 F2 G3 G4""A1 A1 F2 B4 B4""C5 C5 C5 C5 C5""D6 D6 D6 D6 D6""E7 E7 E7 E7 E7";}.box .item:nth-child(1) { grid-column-start: 1; grid-column-end: 3; grid-row-start: 1; grid-row-end: 3;}.box .item:nth-child(2) { grid-column-start: 2; grid-column-end: span 2; grid-row-start: 2; grid-row-end: span 2;}.box .item:nth-child(3) { grid-column-start: F2; grid-column-end: G3; grid-row-start: G3; grid-row-end: B4;}
显示效果:
行列的简写属性
使用grid-column
和grid-row
可简写列和行的开始结束位置。毕竟一次写四个属性太麻烦了,只写两个就省了一半。
.box { grid-template-areas:"A1 A1 F2 G3 G4""A1 A1 F2 B4 B4""C5 C5 C5 C5 C5""D6 D6 D6 D6 D6""E7 E7 E7 E7 E7";}.box .item:nth-child(1) { grid-column: 1 / 3; grid-row: 1 / 3;}.box .item:nth-child(2) { grid-column: 2 / span 2; grid-row: 3 / span 2;}.box .item:nth-child(3) { grid-column: span 3 / 2; grid-row: 3 / span 2; }.box .item:nth-child(4) { grid-column: F2 / G3; grid-row: G3 / B4;}
显示效果:
设置位置时,可使用负数,表示倒数,比如:grid-column: -1 / span 2;
表示从倒数第一根网格线开始,跨 2 列。
使用命名行线
虽然个人觉得这种用法有点难理解,但浏览器是支持这种写法的,可以不用,但不能不会,对不~
.box { 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;}.box .item:nth-child(1) { grid-row: header-left / footer-left;}
显示效果:
使用 grid-area 插旗
前文介绍过grid-template-areas
用于划分地盘,子元素就使用grid-area
来插旗,指定子元素在哪块地盘。
看看经典的管理系统结构:
.box { grid-template-areas:"header header header""left main right""footer footer footer"; grid-template-columns: 10r 10%; grid-template-rows: 30px 1fr 40px;}.box .item:nth-child(1) { grid-area: header;}.box .item:nth-child(2) { grid-area: left;}.box .item:nth-child(3) { grid-area: main;}.box .item:nth-child(4) { grid-area: right;}.box .item:nth-child(5) { grid-area: footer;}
显示效果:
覆盖父元素的对齐方式
justify-self
和align-self
可用于覆盖父元素设置的对齐方式(justify-items / align-items)。某个子元素想要特立独行的时候,就可以派上用场了。
.box { grid-template-columns: repeat(4, 1fr); grid-template-rows: repeat(4, 1fr); align-items: center; justify-items: center;}.box .item { width: 40px; height: 40px;}.box .item:nth-child(2) { align-self: flex-start;}.box .item:nth-child(3) { justify-self: flex-end;}
显示效果:
调整子元素顺序
接上例中的代码,直接添加order
属性可调整子元素顺序。
排序规则:越小值则越靠前,默认值为 0。
.box .item:nth-child(1) { order: 3; }.box .item:nth-child(2) { order: 2; }.box .item:nth-child(3) { order: 1; }.box .item:nth-child(4) { order: 4; }.box .item:nth-child(5) { order: 5; }
显示效果:
控制子元素的层叠顺序
当网格布局中两个子元素叠在一起显示时候,这会可拿出z-index
属性控制子元素层叠顺序,想谁在上面谁就在上面。
规则:谁的 z-index 值大谁就在上面。
.box .item:nth-child(1) { grid-column: 1 / span 2; grid-row: 1 / span 2; background-color: red;}.box .item:nth-child(2) { grid-column: 2 / span 2; grid-row: 1 / span 2; background-color: yellow;}.box:nth-child(2) .item:nth-child(1) { z-index: 2;}
以上代码由于 grid-row 值相同,所以两个子元素会叠在一起,然后使用 z-index 控制了第二个盒子的第一个子元素。
显示效果:
总结
网格布局这一壶终于喝完了,它包含的内容太多太广了,要熟练使用还需要多加练习才行,后续文章还会更新弹性盒子与网格布局的对比,以及它俩的应用场景,敬请期待。
2023 版本的 CSS 规范还提出了子网格 Subgrid
概念,如需了解更多请参阅后文中的参考资料链接。
参考资料:
https://developer.mozilla.org/en-US/docs/Web/CSS/grid
https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_grid_layout/Subgrid