CSS Grid 布局基础 及 快速使用CSS Grid布局,实现响应式设计

CSS Grid 布局是 CSS 中最强大的布局系统。与 flexbox 的一维布局系统不同,CSS Grid 布局是一个二维布局系统,也就意味着它可以同时处理列和行。通过将 CSS 规则应用于 父元素 (成为 Grid Container 网格容器)和其 子元素(成为 Grid Items 网格项),你就可以轻松使用 Grid(网格) 布局。

简介
CSS Grid(网格) 布局(又称为 “Grid(网格)” ),是一个二维的基于网格的布局系统,它的目标是完全改变我们基于网格的用户界面的布局方式。CSS 一直用来布局我们的网页,但一直以来都存在这样或那样的问题。一开始我们用表格(table),然后是浮动(float),再是定位(postion)和内嵌块(inline-block),但是所有这些方法本质上都是只是 hack 而已,并且遗漏了很多重要的功能(例如垂直居中)。Flexbox 的出现很大程度上改善了我们的布局方式,但它的目的是为了解决更简单的一维布局,而不是复杂的二维布局(实际上 Flexbox 和 Grid 能协同工作,而且配合得非常好)。Grid(网格) 布局是第一个专门为解决布局问题而创建的 CSS 模块

基础知识和浏览器支持

首先,你必须使用 display: grid 将容器元素定义为一个 grid(网格) 布局,使用 grid-template-columns 和 grid-template-rows 设置 列 和 行 的尺寸大小,然后通过 grid-column 和 grid-row 将其子元素放入这个 grid(网格) 中。与 flexbox 类似,网格项(grid items)的源(HTML结构)顺序无关紧要。你的 CSS 可以以任何顺序放置它们,这使得使用 媒体查询(media queries)重新排列网格变得非常容易。定义整个页面的布局,然后完全重新排列布局以适应不同的屏幕宽度,这些都只需要几行 CSS ,想象一下就让人兴奋。Grid(网格) 布局是有史以来最强大的 CSS 模块之一。

截至2017年3月,许多浏览器都提供了对 CSS Grid 的原生支持,而且无需加浏览器前缀:Chrome(包括 Android ),Firefox,Edge,Safari(包括iOS)和 Opera 。 另一方面,Internet Explorer 10和11支持它,但是是一个过时的语法实现。 现在是时候使用 Grid 布局网页了!

这个浏览器支持 CSS Grid 的数据,来自 Caniuse ,你可以查看更多的细节。 数字表示支持以上功能的浏览器版本号。

桌面(Desktop) 浏览器
在这里插入图片描述

手机(Mobile) / 平板(Tablet)浏览器
在这里插入图片描述

除了微软之外,浏览器厂商似乎还没有对 Grid(网格) 搞自己的一套实现(比如加前缀),直到规范完全成熟。这是一件好事,因为这意味着我们不必担心学习多个语法。

在生产中使用 Grid 只是时间问题。 但现在是学习的时候了。

重要术语
在深入了解 Grid 的概念之前,理解术语是很重要的。由于这里涉及的术语在概念上都很相似,如果不先记住 Grid 规范定义的含义,很容易混淆它们。但是别担心,术语并不多。

网格容器(Grid Container)

应用 display: grid 的元素。这是所有 网格项(grid item)的直接父级元素。在这个例子中,container 就是 网格容器(Grid Container)。

HTML 代码:

<div class="container">
        <div class="item item-1"></div>
        <div class="item item-2"></div>
        <div class="item item-3"></div>
    </div>

网格项(Grid Item)
网格容器(Grid Container)的子元素(例如直接子元素)。这里 item 元素就是网格项(Grid Item),但是 sub-item 不是。

HTML 代码:

<div class="container">
        <div class="item"></div>
        <div class="item">
            <p class="sub-item"></p>
        </div>
        <div class="item"></div>
    </div>

网格线(Grid Line)
在这里插入图片描述
网格轨道(Grid Track)
两条相邻网格线之间的空间。你可以把它们想象成网格的列或行。下图是第二条和第三条 行网格线 之间的 网格轨道(Grid Track)。

在这里插入图片描述
网格单元格(Grid Cell)
两个相邻的行和两个相邻的列网格线之间的空间。这是 Grid(网格) 系统的一个“单元”。下图是第 1 至第 2 条 行网格线 和第 2 至第 3 条 列网格线 交汇构成的 网格单元格(Grid Cell)。

在这里插入图片描述

网格区域(Grid Area)
4条网格线包围的总空间。一个 网格区域(Grid Area) 可以由任意数量的 网格单元格(Grid Cell) 组成。下图是 行网格线1和3,以及列网格线1和3 之间的网格区域。

在这里插入图片描述

Grid(网格) 属性目录
网格容器(Grid Container) 属性

display
grid-template-columns
grid-template-rows
grid-template-areas
grid-template
grid-column-gap
grid-row-gap
grid-gap
justify-items
align-items
place-items
justify-content
align-content
place-content
grid-auto-columns
grid-auto-rows
grid-auto-flow
grid

网格项(Grid Items) 属性
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 Container) 属性

display
将元素定义为网格容器,并为其内容建立新的 网格格式上下文。

值:

  • grid :生成一个块级网格
  • inline-grid :生成一个内联网格

CSS 代码:

.container {
  display: grid | inline-grid;
}

grid-template-columns / grid-template-rows
使用空格分隔的值列表,用来定义网格的列和行。这些值表示 网格轨道(Grid Track) 大小,它们之间的空格表示网格线。

值:
– track-size: 可以是长度值,百分比,或者等份网格容器中可用空间(使用 fr 单位)
– line-name:你可以选择的任意名称
CSS 代码:

.container {
  grid-template-columns: <track-size> ... | <line-name> <track-size> ...;
  grid-template-rows: <track-size> ... | <line-name> <track-size> ...;
}

示例:
当你在 网格轨道(Grid Track) 值之间留出空格时,网格线会自动分配正数和负数名称:

CSS 代码:

.container {
  grid-template-columns: 40px 50px auto 50px 40px;
  grid-template-rows: 25% 100px auto;
}

在这里插入图片描述
但是你可以明确的指定网格线(Grid Line)名称,例如 值。请注意网格线名称的括号语法:

CSS 代码:

.container {
  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];
}

在这里插入图片描述

请注意,一条网格线(Grid Line)可以有多个名称。例如,这里的第二条 行网格线(row grid lines) 将有两个名字:row1-end 和 row2-start :

CSS 代码:

.container {
  grid-template-rows: [row1-start] 25% [row1-end row2-start] 25% [row2-end];
}

如果你的定义包含多个重复值,则可以使用 repeat() 表示法来简化定义:

CSS 代码:

.container {
  grid-template-columns: repeat(3, 20px [col-start]);
}

上面的代码等价于:

CSS 代码:

.container {
  grid-template-columns: 20px [col-start] 20px [col-start] 20px [col-start];
}

如果多行共享相同的名称,则可以通过其网格线名称和计数来引用它们。

CSS 代码:

.item {
  grid-column-start: col-start 2;
}

fr 单元允许你用等分网格容器剩余可用空间来设置 网格轨道(Grid Track) 的大小 。例如,下面的代码会将每个网格项设置为网格容器宽度的三分之一:

CSS 代码:

.container {
  grid-template-columns: 1fr 1fr 1fr;
}

剩余可用空间是除去所有非灵活网格项 之后 计算得到的。在这个例子中,可用空间总量减去 50px 后,再给 fr 单元的值 3 等分:

CSS 代码:

.container {
  grid-template-columns: 1fr 50px 1fr 1fr;
}

2个例子

常用Grid布局属性介绍
下面从一个简单Grid布局例子说起。

CSS Grid 布局由两个核心组成部分是 wrapper(父元素)和 items(子元素)。 wrapper 是实际的 grid(网格),items 是 grid(网格) 内的内容。

下面是一个 wrapper 元素,内部包含6个 items :

<div class="wrapper">
        <div class="item1">1</div>
        <div class="item2">2</div>
        <div class="item3">3</div>
        <div class="item4">4</div>
        <div class="item5">5</div>
        <div class="item6">6</div>
    </div>

要把 wrapper 元素变成一个 grid(网格),只要简单地把其 display 属性设置为 grid 即可:

.item1{
            background: red;
        }
        .item2{
            background:orange;
        }
        .item3{
            background: yellow;
        }
        .item4{
            background: green;
        }
        .item5{
            background: rgb(0, 247, 255);
        }
        .item6{
            background: blue;
        }
        /* 创建一个 3x3 的grid(网格) */
        .wrapper{
            display: grid;
        }

在这里插入图片描述
Columns(列) 和 rows(行)
为了使其成为二维的网格容器,我们需要定义列和行。让我们创建3列和2行。我们将使用grid-template-row和grid-template-column属性。

   .wrapper{
            display: grid;
            grid-template-columns: 100px 100px 100px;
            grid-template-rows: 50px 50px;
        }

grid-template-columns的3个值表示三列,相应的数值表示列宽即都为100px。
grid-template-rows的2个值表示两行,相应的数值表示行高即都为50px

得到的结果如下:
在这里插入图片描述

我们可以变化一下行高跟列宽的值看下效果,代码:

  .wrapper{
            display: grid;
            grid-template-columns: 200px 50px 100px;
            grid-template-rows: 100px 30px;
        }

在这里插入图片描述
放置 items(子元素)
html

 <div class="wrapper">
        <div class="item1">1</div>
        <div class="item2">2</div>
        <div class="item3">3</div>
        <div class="item4">4</div>
        <div class="item5">5</div>
        <div class="item6">6</div>
    </div>

创建一个 3×3 的 grid(网格):

.wrapper{
            display: grid;
            grid-template-columns: 100px 100px 100px;
            grid-template-rows: 100px 100px 100px;
        }

得到如下效果:
在这里插入图片描述
我们只在页面上看到 3×2 的 grid(网格),而我们定义的是 3×3 的 grid(网格)。这是因为我们只有 6 个 items(子元素) 来填满这个网格。如果我们再加3个 items(子元素),那么最后一行也会被填满。

要定位和调整 items(子元素) 大小,我们将使用 grid-column 和 grid-row 属性来设置:

.item1{
            background: red;

            grid-column-start : 1;
            grid-column-end: 4;
            /* 或者如下写法 */
            /* grid-column: 1/4; */
        }

上面代码意思就是: item1 占据从第一条网格线开始,到第四条网格线结束。显示效果如下:
在这里插入图片描述

如果你不明白我们设置的只有 3 列,为什么有4条网格线呢?看看下面这个图像,黑色的列网格线你就明白了:
在这里插入图片描述

如果上面的看懂了,来个复杂点的巩固下。

.item1{
            background: red;

            grid-column-start : 1;
            grid-column-end: 3;
            /* 或者如下写法 */
            /* grid-column: 1/4; */
        }
        .item2{
            background:orange;
        }
        .item3{
            background: yellow;

            grid-row-start:2;
            grid-row-end: 4;
        }
        .item4{
            background: green;

            grid-column-start:2;
            grid-column-end:4;
        }
        .item5{
            background: rgb(0, 247, 255);
        }
        .item6{
            background: blue;
        }
        /* 创建一个 3x3 的grid(网格) */
        .wrapper{
            display: grid;
            grid-template-columns: 100px 100px 100px;
            grid-template-rows: 100px 100px 100px;
        }

在这里插入图片描述
响应式布局例子
实现如图效果:
在这里插入图片描述
结构布局

.header{
            background: red;
        }
        .menu{
            background: yellow;
        }
        .content{
            background: green;
        }
        .footer{
            background: gray;
        }

        .container{
            display: grid;
            grid-template-columns: repeat(12,1fr);
            grid-template-rows:50px 350px 50px;
            grid-gap: 5px;
        }

<div class="container">
        <div class="header">HEADER</div>
        <div class="menu">MENU</div>
        <div class="content">CONTENT</div>
        <div class="footer">FOOTER</div>
    </div>

使用 grid-template-columns 属性创建一个 12 列的网格,每个列都是一个单位宽度(总宽度的 1/12 )。(愚人码头注:其中, repeat(12, 1fr) 意思是 12 个重复的 1fr 值。 fr 是网格容器剩余空间的等分单位。)

使用 grid-template-rows 属性创建 3 行,第一行高度是 50px ,第二行高度是 350px 和第三行高度是 50px。

使用 grid-gap 属性在网格中的网格项之间添加一个间隙。
在这里插入图片描述
添加 grid-template-areas
这个属性被称为网格区域,也叫模板区域,能够让我们轻松地进行布局实验。

要将它添加到网格中,我们只需给网格容器加一个 grid-template-areas 属性即可。 语法可能有点奇怪,因为它不像其他的 CSS 语法。例如:

 .container {
            display: grid;
            grid-gap: 5px;    
            grid-template-columns: repeat(12, 1fr);
            grid-template-rows: 50px 350px 50px;
            grid-template-areas:
                "h h h h h h h h h h h h"
                "m m c c c c c c c c c c"
                "f f f f f f f f f f f f";
        }

上面代码创建3行12列,上面grid-template-areas属性中的值,每行代表一行,用网格术语来说是 网格轨道(Grid Track) ,每个字符( h,m,c,f)代表一个网格单元格。愚人码头注:其实是 网格区域(Grid Area) 名称,你可以使用任意名称。

你可能已经猜到,我选择了字符 h,m,c,f,是因为他们是 header, menu, content 和 footer 的首字母。 当然,我可以把它们叫做任何想要的名称,但是使用他们所描述的东西的第一个字符更加容易让人理解。

给网格项设定网格区域名称
现在我们需要将这些字符与网格中的网格项建立对应的连接。 要做到这一点,我们将在网格项使用 grid-area 属性:

.header{
            background: red;
            grid-area:h;
        }
        .menu{
            background: yellow;
            grid-area: m;
        }
        .content{
            background: green;
            grid-area: c;
        }
        .footer{
            background: gray;
            grid-area: f;
        }

在这里插入图片描述
尝试其它布局
1.把 menu 移到右边

  .container {
            display: grid;
            grid-gap: 5px;    
            grid-template-columns: repeat(12, 1fr);
            grid-template-rows: 50px 350px 50px;
            grid-template-areas:
                "h h h h h h h h h h h h"
                "c c c c c c c c c c m m"
                "f f f f f f f f f f f f";
        }

在这里插入图片描述

2.使用点 . 来创建空白的网格单元格

 .container {
            display: grid;
            grid-gap: 5px;    
            grid-template-columns: repeat(12, 1fr);
            grid-template-rows: 50px 350px 50px;
            grid-template-areas:
                "h h h h h h h h h h h h"
                /* "m m c c c c c c c c c c" */
                "c c c c c c c c c c m m"
                ". f f f f f f f f f f .";
        }

在这里插入图片描述
3.真正的响应式布局
假设你想在移动设备上查看的是:标题旁边是菜单。那么你可以简单地这样做:

@media screen and (max-width:640px){
            .container{
                grid-template-areas:
                "m m m m m h h h h h"
                "c c c c c c c c c c"
                "f f f f f f f f f f";
            }
        }

在这里插入图片描述

注:所有这些更改都是使用纯 CSS 完成的,不需要修改 HTML 。这被称为结构和表现分离, Grid(网格) 布局真正做到了这点。

浏览器兼容

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/zjsfdx/article/details/89207161