跳转目录🚀
篇章 | 知识点 |
---|---|
CSS进阶之形变与动画 (一) | transform、垂直居中总结、transition动画、animation动画、vertical-align |
CSS进阶之预处理语言之less (二) | Easy less插件、认识less、注释、计算方式、嵌套、变量的定义导入less文件、从less导出css样式的路径 |
CSS进阶之grid网格布局 (三) | 关于grid布局、grid-container属性、grid-items属性 |
CSS进阶之移动端适配 (四) | 媒体查询、CSS常见单位、深入理解pixel、DPR、PPI、浏览器视口Viewport、移动端适配rem方案、移动端适配vw方案 |
CSS进阶之额外内容补充 (五) | HTML5新增、CSS函数补充、BFC详解 |
1. 认识 grid 网格布局
1.1 什么是 grid 网格布局
- grid网格布局: 我们把用Grid box网格盒子来进行布局的方案称为grid布局(grid layout)
- 网格容器? 将一个网格盒子划分成"行"和"列",产生了一个个的网格,我们可以将网格元素放在与这些行和列相关的位置上,然后定义这些网格的大小、位置、层次等关系,从而实现二维布局
1.2 grid布局与弹性布局的不同
- 维度上的区别
- flex布局维度: flex布局只是规定弹性项目flex item在轴线上的位置,是
一维布局
- grid布局维度 : grid布局可以把容器划分成"行"和"列",产生单元格,然后指定网格项目grid item所在的单元格,是
二维布局
。Grid 布局比 Flex 布局更强大,但是兼容性较差。
- flex布局维度: flex布局只是规定弹性项目flex item在轴线上的位置,是
- 兼容性上的区别
- flex布局的兼容性:
- grid布局的兼容性:
- flex布局的兼容性:
- 布局上的区别:
-
flex布局:
-
grid布局:
2. grid网格布局的理解
2.1 grid布局的重要概念
- 容器和项目:在进行grid布局,我们都先需要先给父级盒子(容器)设置上
display:grid
成为网格容器
,容器的所有顶层子元素称为项目
,这个概念在flex也是适用的。 - display:grid;与display:inline-grid
grid
:指明该容器本身是块级元素,块级元素独占一行。inline-grid
:指明该容器本身是一个行内元素,行内元素可以和其他行内元素共占一行。
- 注意:container是一个网格容器,item为网格元素。而grandson却不是网格元素,所以父容器只能影响儿子容器
2.2 grid布局的模型
- 网格线 grid line:
- 划分网格的线,称为"网格线。网格线会被编号帮我们定位每一个网格项目。
- 如果有m列则有m+1根垂直网格线,有n行则有n+1根水平网格线
- 编号从左到右,从上到下为1,2,3排列;也有从右到左,从下到上的-1,-2,-3排列
- 网格单位 grid cell:网格容器里面一个个网格项目元素就是网格单位,一个网格单元是在一个网格元素中最小的单位,就像表格的单元格一样。如图中的1,2,3,4,5……9的格子
- 网格轨道 grid track:
grid-template-columns
和grid-template-rows
属性就是来定义网格中的行和列。一个网格轨道就是网格中两条平行线之间的空间,就好比表格中行或列 - 网格区域 grid area:多个网格线包围的总空间。网格区域可以包含任意数量的网格单元。
2.3 开启网格布局
- 指定一个容器采用网格布局:
display: grid | inline-grid | subgrid
- grid:生成一个块级(block-level)网格容器
- ** inline-grid**:生成一个行级(inline-level)网格容器、
- subgrid:如果你的 grid container 本身就是一个 grid item(即,嵌套网格),你可以使用这个属性来表示你想从它的父节点获取它的行/列的大小,而不是指定它自己的大小。
3. grid-container属性
3.1 grid-template-columns/rows 网络轨道的宽高(列宽和行高)
grid-template-columns
:定义每一列的列宽grid-template-rows
:定义每一行的行高
-
如何定义行列:
- 直接定义行列数、列宽行高:
/* 定义了三列 每一行50px */ grid-template-columns: 50px 50px 50px; /* 定义了三行 每一行50px */ grid-template-rows: 50px 50px 50px;
- 定义网格线的名称(按需求而定):大小前面使用数组可以定义网格线的名称,可以有很多个名称,多个名称用空格隔开。
/* 定义了三列 每一行50px */ grid-template-columns: [column1] 50px [column2]50px [column3]50px [column-end]; /* 定义了三行 每一行50px */ grid-template-rows: [row1]50px [row3]50px [row3]50px [row-end];
3.1.1 取值类型拓展:百分比、fr单位、repeat()函数、auto-fill 关键字、minmax() 函数、auto 关键字
- 百分比:是比较常用的单位,参照与容器的大小
- fr单位:Grid 布局引入了一个另外的长度单位来帮助我们创建灵活的网格轨道,
fr关键字代表网格容器中可用空间的一等份
。下面例子中表示容器分成4份,第一列和第二列各占一份空间,第三列占两份空间。 - repeat()函数:该函数接收
两个参数
,第一个参数为重复次数
,第二个参数为需要重复的值
,使用repeat函数可以简化重复的值, - auto-fill 关键字:单元格大小固定但容器大小不确定时,可以使用
auto-fill关键字
进行自动填充
,让一行或者一列尽可能多的容纳单元格
,常搭配repeat()函数中使用
。 - minmax()函数:minmax()函数产生一个
长度范围
,接收两个参数
,第一个参数为最小值
,第二个为最大值
。 - auto关键字:auto关键字表示由浏览器自己决定长度,下面代码中第一列为容器的30%宽,第二列是50px,第三轮由浏览器自适应。
grid-template-columns: 25% 25% 25% 25%;
grid-template-columns: 1fr 1fr 2fr;
grid-template-columns: repeat(5, 1fr);//第一个参数可以是具体值也可以是auto-fill关键字,后面可以写绝对单位,百分比,fr,minmax()函数
grid-template-columns: repeat(auto-fill, 100px);
grid-template-columns: 200px 20% minmax(100px,1fr);
grid-template-columns: 200px auto 200px;
grid-template-columns: repeat(3, 50px [col-start]);//携带网格线名字
grid-template-columns: repeat(2, 100px 20px 80px);//重复某种模式
grid-template-columns: 30% 50px auto;
3.2 row-gap,column-gap,gap 网格间距(行间距和列间距)
注意 :根据最新标准,grid-row-gap、grid-column-gap、grid-gap三个属性名的grid-前缀已经删除,现在可以写为row-gap、column-gap、gap
- column-gap:设置网格的列间距
- row-gap:设置网格的行间距
- gap:两个属性的简写属性 当有两个值时分别表示 行间距row-gap,列间距column-gap;一个值表示同时设置行列间距
.box {
/* grid布局 */
display: grid;
/* 设置列数 */
grid-template-columns: repeat(4, 1fr);
grid-auto-rows: minmax(100px, 1fr);
/* 设置网格间距 */
/* 行间距 */
row-gap: 20px;
/* 列间距 */
column-gap: 10px;
/* 简写属性 */
gap: 30px 50px;
/* 容器 */
width: 1000px;
/* height: 500px; */
margin: 100px auto;
/* grid-gap是grid-row-gap和grid-column-gap的综合写法,但是此类设置不推荐使用 */
/* grid-row-gap: 10px;
grid-column-gap: 10px;
grid-gap: 10px; */
/* row-gap: 10px;
column-gap: 10px; */
/* gap: 行间距 列间距; 如果取值一致就设置一个值*/
}
3.3 grid-template-areas和grid-area 网格合并
- grid-template-areas:该属性一般与grid-area一起使用,
grid-template-areas
属性在容器上
制定各个区域并命名 - grid-area:
grid-area
属性指定项目
放在哪一个区域内。
.box {
/* 开启了grid布局 */
display: grid;
/* 设置列数 */
grid-template-columns: repeat(4,1fr);
/* 设置行数 */
grid-template-rows: repeat(2,1fr);
grid-template-areas:
"a1 a1 a2 a2"
"a1 a1 a3 a4"
;
gap: 10px;
width: 1008px;
height: 210px;
border: 3px solid #333;
margin: 0 auto;
}
.box div:nth-child(1) {
grid-area: a1;
background-color: #305496;
}
.box div:nth-child(2) {
grid-area: a2;
background-color: #f4b084;
}
.box div:nth-child(3) {
grid-area: a3;
background-color: #70ad47;
}
.box div:nth-child(4) {
grid-area: a4;
background-color: #ffff00;
}
3.3 grid-template 简写属性
- grid-template:grid-template-columns属性,grid-template-rows属性 和 grid-template-areas属性的简写;
.box {
width: 1000px;
margin: 0 auto;
display: grid;
/* grid-template-columns: repeat(4, 1fr);
grid-template-rows: repeat(2, 100px);
grid-template-areas:
"a1 a1 a2 a2"
"a1 a1 a3 a4"
;*/
/* 综合写法 */
grid-template:
"a1 a1 a2 a2" 100px
"a1 a1 a3 a4" 100px
/ 1fr 1fr 1fr 1fr
;
}
3.4 grid-auto-flow 网格排列顺序
- grid-auto-flow:该属性决定容器中的项目按照什么顺序排列,
默认值为row
,即先行后列
,先填满第一行,再开始放入第二行- 默认值为 row
- 值为column:
- 默认值为 row
- 当r单独设置了item后所占空间被排列到下一行或列而产生多余空间,可以使用
row dense/column dense
,表示尽可能填满表格-
以grid-auto-flow:column;为例
-
值修改为
column dense
,如果是row同理改为row dense
.box { /* grid布局 */ display: grid; /* 设置列数 */ grid-template-rows: repeat(4, minmax(100px, 1fr)); grid-auto-columns: minmax(100px, 1fr); /*网格排列顺序 */ /* 默认值 */ /* grid-auto-flow: column; */ grid-auto-flow: column dense; /* 设置网格间距 */ /* 行间距 */ row-gap: 20px; /* 列间距 */ column-gap: 10px; /* 简写属性 */ /* gap: 30px 50px; */ /* 容器 */ width: 1000px; /* height: 500px; */ margin: 100px auto; } .three { grid-row: 2/span 2; }
-
3.5 .justify-items&align-items&place-items网格内容对齐方式
3.5.1 justify-items 水平对齐
- justify-items:该属性设置单元格内容左中右的水平位置
- 取值的区别
-
stretch(默认值):拉伸,占满整个单元格的宽度
-
start: 对齐单元格的起始边缘
-
end:对齐单元格的结束边缘
-
center:单元格内部居中
-
3.5.2 align-items 垂直对齐
- align-items:该属性设置单元格内容上中下的垂直位置
- 取值的区别:align-items为垂直方向,效果同理只是改为垂直方向,此处不再赘述
.container {
justify-content: start | end | center | stretch | space-around | space-between | space-evenly;
align-content: start | end | center | stretch | space-around | space-between | space-evenly;
}
3.5.3 place-items 简写属性
- place-items:前两个属性合在一起的简写属性,当有两个值时表示分别设置 align-items 和 justify-items 属性;如果有一个值,则同时设置两个属性。
3.6 justify-content&align-content&place-content 内容区域在容器中的对齐方式
3.6.1 justify-content 水平对齐
- justify-content:该属性是整个内容区域在容器里左中右的水平位置
- 取值的区别:
-
start:对齐容器的起始边框
-
end:对齐容器的结束边框
-
center:容器的内部居中
-
space-around:每个项目的两侧间隔相等,项目之间的间隔比项目与容器边框的间隔大一倍
-
space-between:项目之间的间隔相等,项目与容器边框之间没有间隔
-
space-evenly:项目与项目的间隔相等,项目与容器边框之间也是同样长度的间隔
-
3.6.2 align-content 垂直对齐
- align-content:该属性是整个内容区域在容器里上中下的垂直位置位置
- 取值的区别: align-content为垂直方向,效果同理只是改为垂直方向,此处不再赘述
3.6.3 place-content 简写属性
- place-content:前两个属性合在一起的简写属性,当有两个值时表示分别设置 align-content和 justify-content属性;如果有一个值,则同时设置两个属性。
3.7 grid-auto-columns&grid-auto-rows 隐式网格轨道的宽高(列宽和行高)
注意:在讲 grid-auto-columns 属性和 grid-auto-rows 属性之前,先来看看隐式和显示
网格的概念
- 显示网格:
- 显式网格就是你在
grid-template-columns 和 grid-template-rows 属性中定义的行和列。
显式网格的行高和列宽
可以根据grid-template-columns 和 grid-template-rows属性设置
- 显式网格就是你在
- 隐式网格:
- 如果你在网格定义之外又放了一些东西,或者因为
内容的数量而需要的更多网格轨道
的时候,网格将会在隐式网格中创建行和列
. 隐式网格的行高和列宽
可以根据 grid-auto-columns 属性和 grid-auto-rows 属性设置。- 如果
不指定这两个属性
,浏览器完全根据单元格内容的大小
,决定新增网格的列宽和行高
- 如果你在网格定义之外又放了一些东西,或者因为
- grid-auto-columns&grid-auto-rows的取值:具体值或minmax()函数等
.wrapper {
display: grid;
grid-template-columns: 200px 100px;
grid-template-rows: 100px 100px;
grid-gap: 10px 20px;
grid-auto-rows: 50px;
}
-
小米案例Grid布局练习
* { margin: 0; padding: 0; } a { text-decoration: none; } ul, li { list-style: none; } .w { width: 1226px; margin: 0 auto; } .banner { height: 460px; background: url(./uploads/banner01.webp) no-repeat center center; background-size: 1226px 460px; margin-top: 100px; } .banner .prolist { position: relative; box-sizing: border-box; width: 234px; height: 100%; padding: 20px 0; background-color: #9b9997; } /* .banner .prolist li {} */ .banner .prolist li .proitem { padding-left: 30px; display: grid; grid-auto-flow: column; grid-template-columns: 1fr auto; box-sizing: border-box; height: 42px; line-height: 42px; color: #fff; font-size: 14px; } .banner .prolist li a i { padding-right: 20px; } .banner .prolist li .proitem:hover { background-color: #ff6700; } /* 细节展示 */ .banner .prolist li .detail { display: none; position: absolute; top: 0; left: 234px; /* width: 100px; */ height: 460px; background-color: skyblue; border: 1px solid #e0e0e0; box-shadow: 0 8px 16px rgba(0, 0, 0, .18); } .banner .prolist li .detail ul { display: inline-grid; /* 给定列数行数,默认先行后列 */ /* grid-template-columns: repeat(3, 1fr); */ grid-template-rows: repeat(6, 1fr); /* 我们不知道有多少item需要设置另外属性 */ grid-auto-columns: 265px; /* 改变展示的方向 colum先列后行 */ grid-auto-flow: column; /* width: 1000px; */ background-color: rgb(255, 255, 255); padding-top: 4px; } .banner .prolist li .detail ul li a { display: grid; width: 265px; height: 76px; grid-template-columns: 40px 1fr; grid-template-rows: 1fr; align-items: center; justify-items: start; column-gap: 12px; color: #333; font-size: 14px; padding-left: 20px; /* background-color: aquamarine; */ } .banner .prolist li .detail ul li .propic { width: 40px; height: 40px; } .banner .prolist li .detail ul li .propic img { height: 100%; } .banner .prolist li .detail ul li .protitle:hover { color: #ff6700; } /* 鼠标悬浮出现效果 */ .banner .prolist li:nth-child(1):hover .detail { display: block; } .banner .prolist li:nth-child(2):hover .detail { display: block; }
<div class="w banner"> <!-- 商品分类列表 --> <ul class="prolist"> <!-- 手机 --> <li> <a class="proitem" href="#"> 手机 <i class="iconfont icon-arrow-right-bold"></i> </a> <!-- 展示列 --> <div class="detail"> <ul> <li> <a class="goodsitem" href="#"> <div class="propic"> <img src="./uploads/p1.webp" alt=""> </div> <p class="protitle"> Xiaomi MIX系列 </p> </a> </li> <li> <a class="goodsitem" href="#"> <div class="propic"> <img src="./uploads/p2.webp" alt=""> </div> <p class="protitle"> Xiaomi 数字系列 </p> </a> </li> <li> <a class="goodsitem" href="#"> <div class="propic"> <img src="./uploads/p3.webp" alt=""> </div> <p class="protitle"> Xiaomi Civi系列 </p> </a> </li> <li> <a class="goodsitem" href="#"> <div class="propic"> <img src="./uploads/p4.webp" alt=""> </div> <p class="protitle"> Xiaomi 青春系列 </p> </a> </li> <li> <a class="goodsitem" href="#"> <div class="propic"> <img src="./uploads/p5.webp" alt=""> </div> <p class="protitle"> Xiaomi K系列 </p> </a> </li> <li> <a class="goodsitem" href="#"> <div class="propic"> <img src="./uploads/p6.webp" alt=""> </div> <p class="protitle"> Xiaomi Note系列 </p> </a> </li> <li> <a class="goodsitem" href="#"> <div class="propic"> <img src="./uploads/p7.webp" alt=""> </div> <p class="protitle"> Redmi 数字系列 </p> </a> </li> </ul> </div> </li> <!-- 电视 --> <li> <a class="proitem" href="#"> 电视 <i class="iconfont icon-arrow-right-bold"></i> </a> <div class="detail "> <ul> <li> <a class="goodsitem" href="#"> <div class="propic"> <img src="./uploads/t1.webp" alt=""> </div> <p class="protitle"> 小米电视6 55" OLED </p> </a> </li> <li> <a class="goodsitem" href="#"> <div class="propic"> <img src="./uploads/t2.webp" alt=""> </div> <p class="protitle"> Redmi X65 </p> </a> </li> <li> <a class="goodsitem" href="#"> <div class="propic"> <img src="./uploads/t3.webp" alt=""> </div> <p class="protitle"> Redmi X55 </p> </a> </li> <li> <a class="goodsitem" href="#"> <div class="propic"> <img src="./uploads/t4.webp" alt=""> </div> <p class="protitle"> 小米电视6 65" OLED </p> </a> </li> <li> <a class="goodsitem" href="#"> <div class="propic"> <img src="./uploads/t5.webp" alt=""> </div> <p class="protitle"> 小米电视 大师 77" OLED </p> </a> </li> <li> <a class="goodsitem" href="#"> <div class="propic"> <img src="./uploads/t6.webp" alt=""> </div> <p class="protitle"> 小米电视6 至尊版 55英寸 </p> </a> </li> <li> <a class="goodsitem" href="#"> <div class="propic"> <img src="./uploads/t7.webp" alt=""> </div> <p class="protitle"> 小米电视6 至尊版 65英寸 </p> </a> </li> <li> <a class="goodsitem" href="#"> <div class="propic"> <img src="./uploads/t8.webp" alt=""> </div> <p class="protitle"> 小米电视 ES43 </p> </a> </li> <li> <a class="goodsitem" href="#"> <div class="propic"> <img src="./uploads/t9.webp" alt=""> </div> <p class="protitle"> 小米电视 ES55 </p> </a> </li> <li> <a class="goodsitem" href="#"> <div class="propic"> <img src="./uploads/t10.webp" alt=""> </div> <p class="protitle"> 小米电视 ES65 </p> </a> </li> <li> <a class="goodsitem" href="#"> <div class="propic"> <img src="./uploads/t11.webp" alt=""> </div> <p class="protitle"> 小米电视 ES75 </p> </a> </li> <li> <a class="goodsitem" href="#"> <div class="propic"> <img src="./uploads/t12.webp" alt=""> </div> <p class="protitle"> 大师电视 65英寸 OLED </p> </a> </li> <li> <a class="goodsitem" href="#"> <div class="propic"> <img src="./uploads/t13.webp" alt=""> </div> <p class="protitle"> Redmi 智能电视 MAX 98" </p> </a> </li> <li> <a class="goodsitem" href="#"> <div class="propic"> <img src="./uploads/t8.webp" alt=""> </div> <p class="protitle"> 小米电视大师86英寸Mini LED </p> </a> </li> </ul> </div> </li> <!-- 家电 --> <li> <a class="proitem" href="#"> 家电 <i class="iconfont icon-arrow-right-bold"></i> </a> </li> <!-- 笔记本 平板 --> <li> <a class="proitem" href="#"> 笔记本 平板 <i class="iconfont icon-arrow-right-bold"></i> </a> </li> <!-- 出行 穿戴 --> <li> <a class="proitem" href="#"> 出行 穿戴 <i class="iconfont icon-arrow-right-bold"></i> </a> </li> <!-- 耳机 音箱 --> <li> <a class="proitem" href="#"> 耳机 音箱 <i class="iconfont icon-arrow-right-bold"></i> </a> </li> <!-- 健康 儿童 --> <li> <a class="proitem" href="#"> 健康 儿童 <i class="iconfont icon-arrow-right-bold"></i> </a> </li> <!-- 生活 箱包 --> <li> <a class="proitem" href="#"> 生活 箱包 <i class="iconfont icon-arrow-right-bold"></i> </a> </li> <!-- 智能 路由器 --> <li> <a class="proitem" href="#"> 智能 路由器 <i class="iconfont icon-arrow-right-bold"></i> </a> </li> <!-- 电源 配件 --> <li> <a class="proitem" href="#"> 电源 配件 <i class="iconfont icon-arrow-right-bold"></i> </a> </li> </ul> </div>
4. grid-items属性
4.1 grid-row-start&grid-column-start&grid-row-end&grid-column-end 基于网格线布局
-
各属性的作用与含义
- grid-row-start:该属性表示上边框所在的水平网格线
- grid-column-start:该属性表示左边框所在的垂直网格线
- grid-row-end:该属性表示下边框所在的水平网格线
- grid-column-end:该属性表示右边框所在的垂直网格线
-
如何进行网格线布局:
- 数字写法:我们可以通过网格线的序号对网格进行布局,使用上面四个属性设置对应子项所占据区域起始和终止位置,包括水平方向(列方向)和垂直方向(行方向)
.box div:nth-child(1) { background-color: pink; /* 列方向摆放位置从第2条列线开始到第3条列线结束位置摆放 */ grid-column-start: 2; grid-column-end: 3; /* 行方向摆放位置从第2条行线开始到第3条行线结束位置摆放 */ grid-row-start: 2; grid-row-end: 3; }
- 如果只设置了grid-column-start和grid-column-end不设置grid-row-start和grid-row-end,此时默认的取值是auto,其他子项会依次让后排列;
如果都设置了,后面子项会自动补全空缺进行布局。
.box div:nth-child(1) {
background-color: pink;
/* 列方向摆放位置从第2条列线开始到第3条列线结束位置摆放 */
grid-column-start: 2;
grid-column-end: 3;
/* 行方向摆放位置从第2条行线开始到第3条行线结束位置摆放 */
/* grid-row-start: 2;
grid-row-end: 3; */
}
.box div:nth-child(2) {
background-color: red;
}
- span关键字网格跨越数量:网格项将跨越指定数量的网格轨道
.item2 {
grid-column-start: span 2;
}
注意:使用这四个属性如果产生了重叠,则可以使用z-index指定项目的重叠顺序
4.2 grid-column&grid-rows 简写属性
- grid-column:是grid-column-start和grid-column-end合并简写
- grid-rows:是grid-row-start和grid-row-end合并简写
.item2 {
grid-column-start: 2;
grid-column-end: 4;
grid-row-start:1;
grid-row-end:3;
}
等同于
.item2 {
grid-column: 2 / 4;
grid-row:1 / 3;
}
等同于
.item2 {
grid-column: 2 / span 2;
grid-row:1 / span 2;
}
4.3 grid-area 作为简写属性用法
- grid-area:
grid-area
属性是grid-row-start,grid-column-start,grid-row-end,grid-column-end的缩写,顺序不能更改;- 上本提及过的:支持grid-template-areas设置网格名称;
/*grid-area: grid-row-start / grid-column-start / grid-row-end / grid-column-end;*/
/*
grid-column-start: 2;
grid-column-end: 3;
grid-row-start: 2;
grid-row-end: 3;
*/
grid-area: 2 / 2 / 3 / 3;
4.4 justify-self&align-self( 单元格内容水平垂直对齐方式
- justify-self:该属性设置单元格内容左中右的水平位置,跟 justify-items 属性的
用法完全一致
,但只作用于单个项目
- align-self:该属性设置单元格内容上中下的垂直位置,align-items属性的
用法完全一致
,也是只作用于单个项目
justify-self:start | end | center | stretch;
align-self:start | end | center | stretch;