这是一个系列的文章,你也可以查看其他文章:
0、CSS-预热篇
Grid布局又叫做网格布局。是一种强大二维布局,Flex布局是一维布局。
Grid布局和Flex布局类似,Grid布局也分容器和项目两部分。但和Flex不同的是,在容器内部,分为row和column(而不是Flex布局的轴和交叉轴),row和column交叉的部分叫cell,划分cell的线叫做gridline。
正常情况下,n(n>=1) 行和m(m>=1)列的布局产生n*m个 单元格(cell),n行(列)有n+1条girdline(网格线),例如3行和3列的布局有9个单元格,有16条网格线。
IE浏览器目前不支持grid布局,其他浏览器对于grid相关属性的详细兼容情况请查看:https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout
容器属性
- grid-template-row/grid-template-column
- grid-template-areas
- row-gap/column-gap/gap
- grid-auto-flow
- justify-items ,align-items ,place-items
- justify-content ,align-content ,place-content
- grid-auto-columns ,grid-auto-rows
- grid-template ,grid
项目属性
- grid-column-start ,grid-column-end ,grid-row-start ,grid-row-end
- grid-column ,grid-row
- grid-area
- justify-self ,align-self ,place-self
下面分别介绍:
当然首先先要设置容器属性为grid,如下所示:
div {
display: grid;
}
默认情况下,容器元素都是块级元素,但也可以设成行内元素。
div {
display: inline-grid;
}
那么grid属性有没有什么需要注意的点呢?请看下面的小实验,代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
.container{
width: 600px;
height: 500px;
border: 1px solid darkgray;
background: lightgreen;
padding: 10px;
}
.item{
height:100px;
width: 100px;
}
.item-inner{
background: darkred;
height: 20px;
width: 30px;
}
.item:nth-child(1){
/* display: grid; */
background: darkblue;
}
.item-float{
float: right;
}
.item:nth-child(2){
/* display: grid; */
background: darkmagenta;
}
.item-inline-block{
display: inline-block;
}
.item:nth-child(3){
/* display: grid; */
background: darkgoldenrod;
vertical-align:middle;
}
.item-table-cell{
display: table-cell;
}
.item:nth-child(4){
/* display: grid; */
background: lightcoral;
}
.item-vertical-align{
vertical-align:middle;
}
.item:nth-child(5){
/* display: grid; */
background: yellow;
column-count: 3;
}
</style>
</head>
<body>
<div class="container">
<div class="item">
<div class="item-inner">1-1</div>
<div class="item-inner item-float">1-2</div>
<div class="item-inner">1-3</div>
</div>
<div class="item">
<div class="item-inner">2-1</div>
<div class="item-inner item-inline-block">2-2</div>
<div class="item-inner">2-3</div>
</div>
<div class="item">
<div class="item-inner">3-1</div>
<div class="item-inner item-inline-table-cell">3-2</div>
<div class="item-inner">3-3</div>
</div>
<div class="item">
<div class="item-inner">4-1</div>
<div class="item-inner item-vertical-align">4-2</div>
<div class="item-inner">4-3</div>
</div>
<div class="item">
<div class="item-inner">5-1</div>
<div class="item-inner">5-2</div>
<div class="item-inner">5-3</div>
</div>
</div>
</body>
</html>
注释每个小容器的display:grid;时,即正常显示结果如下:
取消注释结果:
对比可以看出:设为网格布局以后,容器子元素(项目)的float
、display: inline-block
、display: table-cell
、vertical-align
和column-*
等设置都将失效。
注意,以下所有属性值除了自定义属性值外,还有四个属性值:none、inherit、initial和unset。
- none:不设置
- inherit:继承
- initial:默认
- unset:暂不支持。简单理解为不设置。其实,它是关键字
initial
和inherit
的组合。
当我们给一个 CSS 属性设置了 unset属性值
:
- 如果该属性是默认继承属性,该值等同于
inherit
- 如果该属性是非继承属性,该值等同于
initial
一、容器属性
1、grid-template-row / grid-template-column
.container {
display: grid;
grid-template-columns: <track-size> ... | <line-name> <track-size> ...;
grid-template-rows: <track-size> ... | <line-name> <track-size> ...;
}
当容器被定义为grid时,定义容器的每行和每列的大小。
- line-name即线的名称,名称可省略。
- track-size即为每列的宽度,值可以是长度单位,也可以是百分比,也可以是auto或者以下一些函数。
基本用法:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
.container {
display: grid;
margin: 10px;
height: 300px;
width: 300px;
grid-template-columns: [first] 40px [line2] 50px [line3] auto [col4-start] 50px [five] 40px [end];
grid-template-rows: [row1-start] 25% [row1-end] 100px [third-line] auto [last-line];
}
.item{
border: 1px solid lightblue;
font-size: 2em;
text-align: center;
background: lightskyblue;
}
</style>
</head>
<body>
<div class="container">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
<div class="item">7</div>
<div class="item">8</div>
<div class="item">9</div>
<div class="item">10</div>
<div class="item">11</div>
<div class="item">12</div>
<div class="item">13</div>
<div class="item">14</div>
<div class="item">15</div>
</div>
</body>
</html>
(1)repeat():可以重复一些行或者列,值可以是长度或者是auto-fill(填充尽可能多的单元格)。
假如要做一个4行4列均相等的,可以这样写:
.container {
display: grid;
grid-template-columns: repeat(4, 25%);
grid-template-rows: repeat(4, 25%);
}
等同于:
.container {
display: grid;
grid-template-columns: 25% 25% 25% 25%;
grid-template-rows: 25% 25% 25% 25%;
}
颜色值采用js实现:
<script type=text/javascript>
var colorArray = [ '#D24D57',' #26A65B','#EB7347','#2C3E50',
'#84AF9B','#FC9D99','#AEDD81','#00CCFF','#D0D0D0','#990033','#FFFF00','#FF0033','#CCFFFF','#003366','#CCCC00'];
var container = document.getElementById('grid-app-main').childNodes;
for(var i = 0, k = 0, l = container.length; i < l; i++){
if(container[i].className && container[i].className ==='item'){
container[i].style.background = colorArray[k++];
}
}
</script>
repeat()还有一种用法是
接受两个参数,第一个参数是重复的次数(上例是4),第二个参数是所要重复的值。
grid-template-columns: repeat(2, 100px 20px);
这样的结果也是4列,但1,2和3,4列宽度相同。
auto-fill:容器的大小不确定时,auto-fill
表示自动填充容器,直到容器不能放置更多的列。
.container {
display: grid;
grid-template-columns: repeat(auto-fill, 100px);
}
奇数列自动填充,偶数列固定100px
(2)fr:fraction 的缩写,意为"片段"。如果设置了fr,那么设置了fr的行/列将会按照比例分配容器剩余空间。
.container {
display: grid;
grid-template-columns: 50px 1fr 2fr;
}
上面代码表示有3列,第一列固定宽度50px,假如容器尺寸为200px,则第二列和第三列分别为50px和100px。
(3)minmax():产生一个长度范围,表示长度就在这个范围之中。它接受两个参数,分别为最小值和最大值。
.container{
display: grid;
grid-template-columns: 1fr 1fr minmax(50px, 1fr);
}
上面的代码表示第3列的宽度介于50px 和1fr。
(4)auto:auto表示由浏览器自己决定长度。
.container{
display: grid;
grid-template-columns: 100px auto 100px;
}
上面代码含义是:第二列的宽度,基本上等于该列单元格的最大宽度,除非单元格内容设置了min-width
,且这个值大于最大宽度。
(5)两栏布局左侧固定宽度,右侧自适应
.container{
display: grid;
grid-template: 100px auto;
}
左侧固定100px,右侧自适应宽度
2、grid-template-areas
属性用于定义区域。先用grid-template-row和template-template-column划分区域,然后才是分区域。
.container {
grid-template-areas:
"<grid-area-name> | . | none | ..."
"...";
}
布局实例
<div class="container">
<div class="item-a">header</div>
<div class="item-b">content</div>
<div class="item-c">sidebar</div>
<div class="item-d">footer</div>
</div>
.item-a {
grid-area: header;
}
.item-b {
grid-area: main;
}
.item-c {
grid-area: sidebar;
}
.item-d {
grid-area: footer;
}
.container {
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr;
grid-template-areas:
"header header header header"
"main main main sidebar"
"footer footer footer footer";
}
.container > div{
border:1px solid lightblue;
text-align: center;
}
3、row-gap/column-gap/gap
row-gap属性设置行与行的间隔(行间距),column-gap属性设置列与列的间隔(列间距)。
.container {
row-gap: 20px;
column-gap: 20px;
}
grid-gap
属性和flex属性类似,是grid-column-gap
和grid-row-gap
的合并简写形式。
gap: <grid-row-gap> <grid-column-gap>;
.container{
gap: 20px 20px;
}
4、grid-auto-flow
划分网格以后,容器的子元素会按照顺序,自动放置在每一个网格。默认的放置顺序是"先行后列".
grid-auto-flow默认值是row,如果设为column后
grid-auto-flow: column;
grid-auto-flow
属性还可以设成row dense
和column dense
。某些项目指定位置以后,如果容器行或者列有空余位置,dense规定剩下的项目尽可能紧凑排列,并且尽量填满空格。
5、justify-items ,align-items ,place-items
justify-items
属性设置单元格内容的水平位置(左中右),align-items
属性设置单元格内容的垂直位置(上中下)。
.container {
justify-items: start | end | center | stretch;
align-items: start | end | center | stretch;
}
justify-items和align-items
这两个属性都有如下值:
- start:对齐单元格的起始边缘。
- end:对齐单元格的结束边缘。
- center:单元格内部居中。
- stretch:拉伸,占满单元格的整个宽度(默认值)。
place-items
属性是align-items
属性和justify-items
属性的合并简写形式。
注意:justify-items和align-items默认值是stretch,当设置这两个属性值为其他时,比如start,则宽度随单元格内容变化。
例如:
.container {
display: grid;
margin: 10px;
height: 300px;
width: 300px;
grid-template-columns: 25% 25% 25% 25%;
grid-template-rows: 25% 25% 25% 25%;
justify-items: start;
align-items: start;
}
如果省略第二个值,则浏览器认为与第一个值相等。
6、justify-content ,align-content ,place-content
justify-content
属性是整个内容区域在容器里面的水平位置(左中右),align-content
属性是整个内容区域的垂直位置(上中下)。这两个值和flex中的juqstify-content和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;
}
注意:此属性仅在网格总宽度小于grid容器宽度时候有效果。意味着假如按照百分比设置行列,那么这两个属性是无效的,除非你按照固定宽度设置才会有效。
例如:
如果按照百分比设置grid-template-column和grid-template-row,
.container {
grid-template-columns: 25% 25% 25% 25%;
grid-template-rows: 25% 25% 25% 25%;
justify-content: start;
align-content: start;
border: 1px solid red;
}
.container {
grid-template-columns: 50px 50px 50px 50px;
grid-template-rows: 50px 50px 50px 50px;
justify-content: start;
align-content: start;
border: 1px solid red;
}
place-content
属性是align-content
属性和justify-content
属性的合并简写形式。
7、grid-auto-columns ,grid-auto-rows
grid-auto-columns
属性和grid-auto-rows
属性用来设置,浏览器自动创建的多余网格的列宽和行高。
如果容器指定这连个属性,并且在单元格中指定位置,那么浏览器会按照指定的位置和大小放置单元格。
.container {
display: grid;
grid-template-columns: 50px 50px 50px 50px;
grid-template-rows: 50px 50px 50px 50px;
grid-auto-rows: 40px;
}
.item:nth-child(15){
grid-row-start: 5;
grid-column-start: 3;
}
.item:nth-child(16){
grid-row-start: 6;
grid-column-start: 4;
}
如果子单元格不设定grid-column-start属性,grid-column-start默认值为1。
8、grid-template ,grid
grid-template
属性是grid-template-columns
、grid-template-rows
和grid-template-areas
这三个属性的合并简写形式。
grid
属性是grid-template-rows
、grid-template-columns
、grid-template-areas
、 grid-auto-rows
、grid-auto-columns
、grid-auto-flow
这六个属性的合并简写形式。
个人不建议使用这两个属性,会造成代码晦涩难懂。
二、项目属性
以下属性都是作用在item上
1、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-template-row和grid-template-column属性。
.container {
display: grid;
grid-template-columns: 50px 50px 50px 50px;
grid-template-rows: 50px 50px 50px 50px;
}
.item:nth-child(1){
grid-column-start: 3;
grid-column-end: 5;
grid-row-start: 3;
grid-row-end: 5;
}
上面代码表示第一个元素左边框起始于第3个列网格线,右边框结束于第5根列网格线;上边框起始于第3个列网格线,下边框结束于第5根列网格线。其他项目都没有指定位置,容器中display近似于absolute表现,由浏览器自动布局。
这四个属性值还可以指定为网格线的名称或者使用span
关键字,表示"跨越",即左右边框(上下边框)之间跨越多少个网格。
2、grid-column ,grid-row
grid-column
属性是grid-column-start
和grid-column-end
的合并简写形式,grid-row
属性是grid-row-start
属性和grid-row-end
的合并简写形式。
在此不一一举例,有兴趣的读者可以自己试试。
3、 grid-area
grid-area
属性指定项目位置.
此属性必须要和容器属性中的grid-template-areas一起使用,这很好理解,只有设定父容器区域才能指定子元素在哪个区域。
.container {
grid-template-columns: 50px 50px 50px 50px;
grid-template-rows: 50px 50px 50px 50px;
grid-template-areas: 'a b c d'
'e f g h'
'i j k l'
'm n o p';
border: 1px solid red;
}
.item:nth-child(1){
grid-area: g;
}
结果:
我们可以看到编号为1的变到了g区域。
grid-area 还可用作grid-row-start
、grid-column-start
、grid-row-end
、grid-column-end
的合并简写形式,直接指定项目的位置。
.item {
grid-area: <row-start> / <column-start> / <row-end> / <column-end>;
}
4、justify-self ,align-self ,place-self
justify-self
设置单元格内容在水平方向的位置(左中右),justify-self
和justify-items
的用法完全一致,但只作用于单个项目。
align-self
设置单元格内容的在垂直方向的位置(上中下),align-self
和align-items
的用法完全一致,也是只作用于单个项目。
.item {
justify-self: start | end | center | stretch;
align-self: start | end | center | stretch;
}
这两个属性都可以取下面四个值。
- start:对齐单元格的起始边缘。
- end:对齐单元格的结束边缘。
- center:单元格内部居中。
- stretch:拉伸,占满单元格的整个宽度(默认值)。
place-self
属性是align-self
属性和justify-self
属性的合并简写形式。如果省略第二个值,那么第二个值和第一个值相等。
三、参考资料: