关于css布局的问题,由于我css运用不太熟练,在遇到稍微复杂的情况时只能各种百度,也从未总结过,希望通过这个学习,能熟练运用到项目当中。
参考: 阮一峰Grid布局教程
一、 概述
Grid,顾名思义,就是网格布局。分成的一个个小小的网格自由组合,通过使用者的运用能力,来突破以往传统布局的局限。由Grid可以想到flex布局。
关于两者的区别:flex是轴线布局,所有的布局方式是针对轴线展开,可以看做是一维布局。而Grid可以看成是行与列的布局,即二维布局。功能当然比一维布局强大。
二、概念
2.1 容器与项目
采用Grid布局的区域,称之为容器-container, 容器里采用网格的子元素,称之为项目-item。
<div class="father">
<div><p>1</p></div>
<div><p>2</p></div>
<div><p>3</p></div>
</div>复制代码
.father是container,里面的div是item。
注意: item只能是container的子元素,而不是孙子元素之类的。。上面例子的p标签就不是item。
2.2 行与列
容器里水平方向为行-row, 竖直方向为列-column.
2.3 单元格
行与列交叉的区域叫做单元格-cell
m行n列产生m*n个单元格。
2.4 网格线
分网格的线 就叫网格线-grid line。正常情况下,n行有n+1根网格线。
三、 容器属性
容器属性是指container上的属性。
3.1 display
display: grid; // 指定一个元素为容器复制代码
如下例子:
div {
display: grid;
}
p {
border: 1px solid #000000;
}复制代码
<body>
<div>
<p>1</p>
<p>2</p>
<p>3</p>
<p>4</p>
</div>
</body>复制代码
默认情况下,container是块级元素,也可以设置成行内块级元素。
display: inline-grid;复制代码
如下例子:
<style>
div {
display: inline-grid;
}
p {
border: 1px solid #000000;
}
</style>复制代码
<body>
<div>
<p>1</p>
<p>2</p>
<p>3</p>
<p>4</p>
</div>
</body>复制代码
选中元素可以看到
注意: 容器设置为grid、inline-grid之后,容器上的float,display: inline-block,display: table-cell、vertical-align、column-*都会失效。(这一项:在阮一峰老师教程中出现,但是我在上面的例子中给容器div加上float:left,并给容器再加一个兄弟div ,float还是起做的用。。不知道这个解释是在什么情况下)
3.2 grid-template-columns grid-template-rows
grid-template-columns定义每一列的列宽, grid-template-rows定义每一行的行高。
如下面的列子
<style>
div {
display: grid;
grid-template-columns: 100px 100px 100px;
grid-template-rows: 100px 100px 100px;
}
p {
border: 1px solid #000000;
}
</style>复制代码
<body>
<div>
<p>1</p>
<p>2</p>
<p>3</p>
<p>4</p>
</div>
<div>222</div>
</body>复制代码
效果如下
也可以使用百分比
<style>
div {
display: grid;
grid-template-columns: 33.33% 33.33% 33.33%;
grid-template-rows: 100px 100px 100px;
}
p {
border: 1px solid #000000;
}
</style>复制代码
<body>
<div>
<p>1</p>
<p>2</p>
<p>3</p>
<p>4</p>
</div>
<div>222</div>
</body>复制代码
3.2.1 repeat
上面的写法可以看到,如果有很多均等的行与列,这样写很费劲,可以用repeat函数
<style>
div {
display: grid;
grid-template-columns: repeat(3, 33.33%);
grid-template-rows: 100px 100px 100px;
}
p {
border: 1px solid #000000;
}
</style>复制代码
repeat有俩参数,重复次数,重复的大小。
repeater还能重复某种模式
<style>
div {
display: grid;
grid-template-columns: repeat(2, 33.33% 10%);
grid-template-rows: 100px 100px 100px;
}
p {
border: 1px solid #000000;
}
</style>复制代码
3.2.2 auto-fill关键词
使用情况: 容器大小不确定+单元格大小确定+希望每行/每列能容纳尽可能多的单元格。
auto-fill是自动填充的意思。
<style>
div {
display: grid;
grid-template-columns: repeat(auto-fill, 30%);
grid-template-rows: 100px 100px 100px;
}
p {
border: 1px solid #000000;
}
</style>复制代码
3.2.3 fr关键字
fraction的缩写-片段的I意思。是为了表示比列关系。如果两行,一个1fr,一个2fr,后者是前者行高的两倍。
<style>
div {
display: grid;
grid-template-columns: repeat(auto-fill, 30%);
grid-template-rows: 2fr 1fr 100px;
}
p {
border: 1px solid #000000;
}
</style>复制代码
3.2.4 minmax()函数
它表示一个长度范围,接受俩参数,第一个-最小值,第二个-最大值。
<style>
div {
display: grid;
grid-template-columns: 1fr 2fr minmax(100px, 1fr);
grid-template-rows: 2fr 1fr 100px;
}
p {
border: 1px solid #000000;
}
</style>复制代码
3.2.5 auto关键字
表示浏览器自己决定
<style>
div {
display: grid;
grid-template-columns: 200px 20px auto;
grid-template-rows: 2fr 1fr 100px;
}
p {
border: 1px solid #000000;
}
</style>复制代码
3.2.6 网格线的名称
每一行与每一列 都可以使用方括号来指定此网格线的名称,以便于之后引用。
grid-template-columns: [x1] 200px [x2] 20px [x3] auto [x4];复制代码
网格线允许一根线有多个名字,比如: [x-1 22 min]
3.3 grid-gap/grid-row-gap/grid-column-gap
看字面就能明白,表示的是间距。
grid-gap是行间距与列间距的简写。
如果grid-gap只写一个值,表示行间距与列间距相等。
grid-gap: <grid-row-gap> <grid-column-gap>;复制代码
<style>
div {
display: grid;
grid-template-columns: [x1] 200px [x2] 20px [x3] auto [x4];
grid-template-rows: 2fr 1fr 100px;
grid-row-gap: 20px;
grid-column-gap: 20px;
/* grid-gap: 20px 20px; */
}
p {
border: 1px solid #000000;
}
</style>复制代码
3.4 grid-template-areas属性
网格布局允许指定区域,此属性用于定义区域,一个区域可以由一个或者多个单元格组成。
<style>
div {
display: grid;
grid-template-columns: [x1] 200px [x2] 20px [x3] auto [x4];
grid-template-rows: 2fr 1fr 100px;
grid-row-gap: 20px;
grid-column-gap: 20px;
grid-template-areas: 'a b c''d e f''g h i';
/* grid-gap: 20px 20px; */
}
p {
border: 1px solid #000000;
}
</style>复制代码
这表示定义了9个区域。
多个单元格合并成一个区域的简写:
grid-template-areas: 'a a a' 'b b b' 'c c c';复制代码
这表示就三个区域。
如果某些区域不需要利用,就用.表示
grid-template-areas: 'a . c'
'd . f'
'g . i';复制代码
注意: 区域的命名会影响网格线。每个区域的起始网格线,会自动命名为区域名-start,区域名-end。
3.5 grid-auto-flow属性
划分网格之后,容器的item会按照顺序自动排列到网格中。默认的放置顺序是“先行后列”。这个顺序由grid-auto-flow决定,更改grid-auto-flow的值就能更改放置顺序。
grid-auto-flow: column;复制代码
它的值除了row/column,还有row dense和column dense。这两个值主要用来指导某些item指定位置之后,剩下的item怎么放置。
如图,如果1和2各占两个单元格,在默认row的值下,第一行空出一个单元格。但是在row-dense值下,效果如下图
grid-auto-flow: row dense;复制代码
3.6 justify-items、align-items、place-items
justify-items设置单元格的水平位置(左中右),align-items设置单元格的垂直位置(上中下)。
这两个属性的值相同
<style>
div {
display: grid;
grid-template-columns: [x1] 200px [x2] 20px [x3] auto [x4];
grid-template-rows: 2fr 1fr 100px;
grid-row-gap: 20px;
grid-column-gap: 20px;
justify-items: end;
}
p {
border: 1px solid #000000;
}
</style>复制代码
上面的例子,将justify-items的值设置为stretch,效果如下
place-items是align-items与justify-items的简写。
place-items: <align-items> <justify-items>;复制代码
如果省略一个值 则表示两个值相等。
3.7 justify-content、align-content、place-content
justify-content表示整个内容区域在整个容器内的水平位置(左中右),align-content表示整个内容区域在整个容器内的垂直位置(上中下)。
start- 对齐容器的起始边框
end-对齐容器的结束边框
center-容器内部居中
stretch-容器大小没指定时 网格将容器占满
space-around-每个item两侧间距相等,所以项目之间的间距比项目与容器的间距大一倍
space-between-项目与项目间距相等,项目与容器之间没有间距。
<style>
div {
display: grid;
grid-template-columns: [x1] 200px [x2] 20px [x3] auto [x4];
grid-template-rows: 2fr 1fr 100px;
grid-row-gap: 20px;
grid-column-gap: 20px;
justify-items: stretch;
justify-content: space-between;
}
p {
border: 1px solid #000000;
}
</style>复制代码
space-evenly - 项目与项目、项目与容器的间距都相等。
place-content是justify-content和align-content的简写。
place-content: <align-content> <justify-content>复制代码
3.8 grid-auto-columns、grid-auto-rows
有时候某些item会需要出现在现有的网格之外,比如有3行,但是item要出现弟5行,就会自动生成剩下两行。
grid-auto-columns、grid-auto-rows的写法与grid-template-columns、grid-template-rows的写法完全一致。如果不指定这两个值的大小,那么浏览器会根据单元格内容的大小来决定新增单元格的行高与列宽。
比如下面的例子:2*2的单元格,新的第6项指定在第4行第3列。
<style>
#container {
display: grid;
grid-template-columns: 100px 100px;
grid-template-rows: 100px 100px;
grid-auto-rows: 50px;
}
.item {
font-size: 2em;
text-align: center;
border: 1px solid #e5e4e9;
}
.item-1 {
background-color: #ef342a;
}
.item-2 {
background-color: #f68f26;
}
.item-3 {
background-color: #4ba946;
}
.item-4 {
background-color: #0376c2;
}
.item-5 {
background-color: #c077af;
grid-row-start: 4;
grid-column-start: 3;
}
</style>复制代码
<body>
<div id="container">
<div class="item item-1">1</div>
<div class="item item-2">2</div>
<div class="item item-3">3</div>
<div class="item item-4">4</div>
<div class="item item-5">5</div>
</div>
</body>复制代码
3.9 grid-template属性与grid属性
grid-template是grid-template-columns和grid-template-rows、grid-template-areas的简写。
grid是grid-template-columns、grid-template-rows、grid-template-areas、grid-auto-flow、grid-auto-columns、grid-auto-rows的缩写。
虽然简写写的东西少,但是不易读。
四、项目属性
4.1 grid-column-start、grid-column-end、grid-row-start、grid-row-end
项目的位置是可以指定的。方法是指定项目的四个边框分别定位在哪根网格线。
下面的例子:
<style>
.item-1 {
background-color: #ef342a;
grid-column-start: 2;
/*左边框所在的垂直网格线 */
grid-column-end: 4;
/*右边框所在的垂直网格线*/
}
</style>复制代码
1号: 左侧是第2根 右侧是第四根
这时候除了1号,5号 ,其他都没指定位置,其他的都是按照grid-auto-flow来布局的。这个属性默认的是row。
这四个属性的值,还可以设置为网格线的名称。还可以用span关键字,表示“跨域”。即左右边框(上下边框)跨越了多少个单元格。
<style>
#container {
display: grid;
grid-template-columns: [x1] 100px [x2] 100px [x3];
grid-template-rows: [y1] 100px [y2] 100px [y3];
}
.item {
font-size: 2em;
text-align: center;
border: 1px solid #e5e4e9;
}
.item-1 {
background-color: #ef342a;
grid-column-start: x2;
/*左边框所在的垂直网格线 */
grid-column-end: x3;
/*右边框所在的垂直网格线*/
}
.item-2 {
background-color: #f68f26;
}
.item-3 {
background-color: #4ba946;
}
.item-4 {
background-color: #0376c2;
}
</style>复制代码
<body>
<div id="container">
<div class="item item-1">1</div>
<div class="item item-2">2</div>
<div class="item item-3">3</div>
<div class="item item-4">4</div>
</div>
</body>复制代码
<style>
.item-1 {
background-color: #ef342a;
grid-column-start: span 2;
}
</style>复制代码
使用这四个属性,如果发生了项目重叠 ,就要用z-index来指定重叠的层级。
4.2 grid-column、grid-row
根据上面的规律不难判断,grid-column是grid-column-start和grid-column-end的缩写,而grid-row是grid-row-start和grid-row-end的缩写。
4.3 grid-area
grid-area指定项目放在哪一个区域
<style>
#container {
display: grid;
grid-template-columns: [x1] 50% [x2] 50% [x3];
grid-template-rows: [y1] 50% [y2] 50% [y3];
grid-template-areas: 'a b''a b';
}
.item {
font-size: 2em;
text-align: center;
border: 1px solid #e5e4e9;
}
.item-1 {
background-color: #ef342a;
/* grid-column-start: span 2; */
grid-area: a;
}
.item-2 {
background-color: #f68f26;
}
.item-3 {
background-color: #4ba946;
}
.item-4 {
background-color: #0376c2;
}
</style>复制代码
他还可以当做grid-row-start、grid-row-end、grid-column-start、grid-column-end的简写。
.item {
grid-area: <row-start> / <column-start> / <row-end> / <column-end>;
}复制代码
4.4 justify-self、align-self、place-self属性
justify-self设置单元格内容的水平位置(左中右),值与justify-items一致,但是只用于单个项目。align-self设置单元格内容的垂直位置(上中下),与align-items的值一致,但是也只用于单个项目。place-self是二者的简写。
.item {
justify-self: start | end | center | stretch;
align-self: start | end | center | stretch;
}复制代码
start:对齐单元格的起始边缘。end:对齐单元格的结束边缘。center:单元格内部居中。stretch:拉伸,占满单元格的整个宽度(默认值)。复制代码
<style>
#container {
display: grid;
grid-template-columns: [x1] 50% [x2] 50% [x3];
grid-template-rows: [y1] 50% [y2] 50% [y3];
grid-template-areas: 'a b''a b';
}
.item {
font-size: 2em;
text-align: center;
border: 1px solid #e5e4e9;
}
.item-1 {
background-color: #ef342a;
justify-self: start;
grid-area: a;
}
.item-2 {
background-color: #f68f26;
}
.item-3 {
background-color: #4ba946;
}
.item-4 {
background-color: #0376c2;
}
</style>复制代码
<body>
<div id="container">
<div class="item item-1">1</div>
<div class="item item-2">2</div>
<div class="item item-3">3</div>
<div class="item item-4">4</div>
</div>
</body>复制代码