概述
最近有几个bug和需求,涉及到布局和样式,在尽量不大动老代码的情况下,flex布局显得有些力不从心,flex布局是一种一维布局,一次只能处理一个维度的元素布局,一行或者一列,而grid布局是二维布局,可以同时处理行和列的布局,grid布局远比flex布局强大的多,下面简单梳理下grid布局的一些前置知识。
前置知识
容器和项目
采用网格布局的区域,称为容器(container),容器内的顶级子容器,称为项目(item)
单元格和网格线
行列交叉为单元格,n行m列会产生n*m个单元格,划分网格的线称为网格线,n行有n+1根水平网格线,m列有m+1根垂直网格线,网格线概念与项目属性grid-row-start、grid-row-end grid-column-start grid-column-end关系密切。
容器属性
display
- display:grid(声明该容器是个块级元素)
- display:inline-grid(声明该容器是行内元素)
注意,设为网格布局以后,容器子元素(项目)的float、display: inline-block、display: table-cell、vertical-align和column-*等设置都将失效
grid-template-rows、grid-template-columns和grid-auto-rows、grid-auto-columns
这两组四个属性放一块梳理,第一组显式行列(grid-template-rows、grid-template-columns),第二组隐式行列(grid-auto-rows、grid-auto-columns)
现在有个2 * 3的布局,但该容器内不止6个项目,此时浏览器会自动创建多余的网格,这种情况下,2 * 3为显示网格,多余的项目为隐式网格,通过grid-template-rows、grid-template-columns可设置显示网格的行宽,列宽,通过grid-auto-rows、grid-auto-columns可设置隐式网格的行宽、列宽
.container {
display: grid;
/* 声明了三列,宽度分别为 100px 100px 100px */
grid-template-columns: 100px 100px 100px;
/* 声明了两行,宽度分别为 100px 100px */
grid-template-rows: 100px 100px;
/* 设置隐式网格行50px */
grid-auto-rows: 50px;
}
在设置这四个属性时,有一些函数可简化操作
repeat(重复次数,重复值/重复模式)
.container {
display: grid;
grid-template-columns: repeat(3,100px);
grid-template-rows: repeat(3,100px);
}
fr关键字
场景:构建n行2列且2列等分,列宽随着容器大小自适应,可用fr关键字,fr表示比例关系,两列宽度都为1fr,表示两列列宽相等,若为1fr,2fr,表示后者是前者的两倍,fr也可与绝对长度结合使用
用大白话讲,fr代表份,nfr表示在总长度中占n份
.container {
display: grid;
/* 声明三列,第一列占一份,第二、三列均占两份 */
grid-template-columns: 1fr 2fr 2fr;
}
auto-fill关键字
auto-fill表示自动填充,让一行或者一列尽可能更多容纳更多的单元格,grid-template-columns: repeat(auto-fill, 100px) 表示列宽是 100 px,但每行列的数量随着容器宽度变化,只要容器容纳的下,就可以放置元素
.container {
width: 50vw;
display: grid;
grid-template-columns: repeat(auto-fill, 100px);
/* 声明了两行,宽度分别为 100px 100px */
grid-template-rows: 100px 100px;
/* 设置隐式网格行50px */
grid-auto-rows: 50px;
}
minmax(最小值,最大值)
minmax函数产生一个长度范围,表示网格元素长度在此范围内,grid-template-column:minmax(100px,300px) 1fr表示第一列列宽最小100px,最大300px
auto关键字
auto表示由浏览器自己决定长度,auto可轻松实现左右两列固定宽度,中间自适应布局,grid-template-columns: 100px auto 100px 表示第一第三列为 100px,中间由浏览器决定长度
row-gap、column-gap、gap
row-gap设置行间距,column-gap设置列间距
gap为合并简写形式,gap:<row-gap> <column-gap>
grid-template-areas
grid-template-areas用来定义区域,大白话讲就是给网格元素取名字,搭配项目属性grid-area一起使用的,grid-area 属性指定项目放在哪一个网格,这两个属性能轻松实现不同行不同个数项目的布局
<div class="container">
<div class="item_1">1</div>
<div class="item_2">2</div>
<div class="item_3">3</div>
</div>
.container {
width: 50vw;
display: grid;
grid-template-columns: repeat(2, 100px);
grid-auto-rows: 100px;
grid-template-areas:
"header header"
"content_1 content_2";
}
.container div {
display: grid;
place-content: center;
}
.item_1 {
background-color: aquamarine;
grid-area: header;
}
.item_2 {
background-color: brown;
grid-area: content_1;
}
.item_3 {
background-color: blueviolet;
grid-area: content_2;
}
grid-auto-flow
控制自动布局算法怎么运作,默认row(先行后列)
可取值:row(先行后列),row dense(先行后列,尽可能填满),column(先列后行),column dense(先列后行,尽可能填满)
.container {
display: grid;
grid-template-columns: repeat(3, 100px);
grid-auto-rows: 100px;
grid-auto-flow: row;
}
这种情况下出现空缺,使用
grid-auto-flow: row dense尽可能填满
.container {
display: grid;
grid-template-columns: repeat(3, 100px);
grid-auto-rows: 100px;
grid-auto-flow: row dense;
}
grid-auto-flow: column grid-auto-flow: column dense同理,就不过多赘述
justify-items、align-items、place-items和justify-content、align-content、place-content
也是两组属性,单元格位置(justify-items align-items place-items)和内容位置(justify-content align-content place-content)
place-items为justify-items和align-items合并简写形式
place-items:<justify-items> <align-items>
place-content为justify-content和align-content合并简写形式
place-content:<justify-content> <align-content>
单元格位置
justify-items align-items可取值如下,以下图以justify-item属性为例进行讲解,align-items属性同理,只是方向为垂直方向
- start:对齐单元格的起始边缘
- end:对齐单元格的结束边缘
- center:单元格内部居中
- stretch:拉伸,占满单元格的整个宽度(默认值)
内容位置
justify-content align-content可取值如下,以下图以justify-content属性为例进行讲解,align-content属性同理,只是方向为垂直方向
- start:对齐容器的起始边框
- end - 对齐容器的结束边框
- center - 容器内部居中
- stretch - 项目大小没有指定时,拉伸占据整个网格容器
- space-around - 每个项目两侧的间隔相等。所以,项目之间的间隔比项目与容器边框的间隔大一倍
- space-between - 项目与项目的间隔相等,项目与容器边框之间没有间隔
- space-evenly - 项目与项目的间隔相等,项目与容器边框之间也是同样长度的间隔
项目属性
grid-column-start、grid-column-end、grid-row-start、grid-row-end
这四个属性指定项目的边框定位在哪根网格线
- grid-column-start:左边框所在的垂直网格线
- grid-column-end:右边框所在的垂直网格线
- grid-row-start:上边框所在的水平网格线
- grid-row-end:下边框所在的水平网格线
grid-column、grid-row
grid-column是grid-column-start和grid-column-end的合并简写形式
grid-column: <start-line> / <end-line>;
grid-row是grid-row-start和grid-row-end的合并简写形式
grid-row: <start-line> / <end-line>;
上图布局观察到,1号项目左侧网格线定位在第一根网格线,右侧网格线定位在第四根网格线
.item_1 {
grid-column: 1/4;
}
可以使用span关键字,表示"跨越",即左右边框(上下边框)之间跨越多少个网格,上述代码等价于
.item_1 {
grid-column: span 3;
}
grid-area
指定项目放在哪个区域,具体使用看上述grid-template-areas描述
还可用作grid-row-start、grid-column-start、grid-row-end、grid-column-end的合并简写形式,直接指定项目的位置,如grid-area: 1 / 1 / 2 / 4,与上述grid-column: 1/4和grid-column: span 3等价
.item_1 {
grid-area: 1/1/2/4;
}
justify-self、align-self、place-self
justify-self属性设置单元格内容的水平位置(左中右),跟justify-items属性的用法完全一致,但只作用于单个项目。
align-self属性设置单元格内容的垂直位置(上中下),跟align-items属性的用法完全一致,也是只作用于单个项目
常见问题
为啥设置了1fr,宽度会超出
在使用CSS Grid布局时,设置1fr表示将可用空间平均分配给每个单元格,但是如果单元格中包含有固定宽度的内容,比如图片、文本等,那么单元格的实际宽度就会超出1fr所分配的空间。
例如,如果一个单元格设置了1fr,但是其中包含了一个宽度为100px的图片,那么该单元格的实际宽度就会是100px加上1fr分配的空间,这样就会导致单元格的宽度超出预期。
为了避免这种情况,可以考虑通过设置单元格的最大宽度来限制单元格的宽度,例如使用max-width属性或者minmax函数:
.grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}
在上述代码中,使用minmax函数设置单元格的最小宽度为200px,最大宽度为1fr,这样可以平衡单元格宽度和内容宽度之间的关系,避免单元格宽度超出预期。
结语
这是我目前所了解的grid布局,当然也有可能存在一定的误区。
希望对大家有帮助,不喜勿喷