CSS布局—网格布局Grid(一)

CSS网格可以定义由行和列组成的二维布局,然后将元素放置到网格中。有些元素可能只占据网格的一个单元,另一些元素则可能占据多行或多列。网格的大小既可以精确定义,也可以根据自身内容自动计算。你既可以将元素精确地放置到网格某个位置,也可以让其在网格内自动定位,填充划分好的区域。

在这里插入图片描述

Flexbox 类似,网格布局也是作用于两级的 DOM 结构。设置为 display: grid 的元素成为一个网格容器(grid container)。它的子元素则变成网格元素(grid items)。

基础网页布局

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        .grid{
            display: grid;
            grid-template-columns: 1fr 1fr 1fr;
            grid-template-rows: 1fr 1fr;
            grid-gap: 0.5em;
        }
        .grid > * {
            background: springgreen;
            color: white;
            padding: 2em;
            border-radius: 0.5em;
        }
    </style>
</head>
<body>
    <div class="grid">
        <div class="a">a</div>
        <div class="b">b</div>
        <div class="c">c</div>
        <div class="d">d</div>
        <div class="e">e</div>
        <div class="f">f</div>
    </div>
</body>
</html>

在这里插入图片描述

display:grid

使用 display: grid 定义一个网格容器。容器会表现得像一个块级元素,100%填充可用宽度。
也可以使用 inline-grid(尽管这段代码没写),这样元素就会在行内流动,且宽度只能够包含子元素,不过 inline-grid 的使用频率不高。

grid-template-columnsgrid-template-rows

grid-template-columns 定义列; grid-template-rows 定义行

两个属性定义了网格每行每列的大小。本例使用了一种新单位 fr,代表每一列(或每一行)的分数单位(fraction unit)。这个单位跟Flexboxflex-grow因子的表现一样。grid-template-columns:1fr 1fr 1fr 表示三列等宽。

不一定非得用分数单位,可以使用其他的单位,比如 px、em 或百分数。也可以混搭这几种单位,例如,grid-template-columns: 300px 1fr 定义了一个固定宽度为 300px 的列,后面跟着一个会填满剩余可用空间的列。2fr 的列宽是 1fr 的两倍。

其他使用方式
grid-template-rows: repeat(4, auto);定义了四个水平网格轨道,高度为auto,这等价于grid-template-rows: auto auto auto auto。轨道大小设置为auto,轨道会根据自身内容扩展。

repeat()符号还可以定义不同的重复模式,比如repeat(3, 2fr 1fr)会重复三遍这个模式,从而定义六个网格轨道,重复的结果是2fr 1fr 2fr 1fr 2fr 1fr

还可以将repeat()作为一个更长的模式的一部分。比如 grid-template-columns: 1fr repeat(3, 3fr) 1fr定义了一个1fr的列,接着是三个3fr的列,最后还有一个1fr的列(可以用1fr 3fr 3fr 3fr 1fr表示)。可以看出来因为展开的写法无法一目了然,所以才产生了repeat()这种简写方式。

grid-gap

属性定义了每个网格单元之间的间距。也可以用两个值分别指定垂直和水平方向的间距。(比如grid-gap: 0.5em 1em)。

网格剖析

基本概念

构建网格布局时会涉及这些组成部分。比如声明 grid-template-columns: 1fr 1fr 1fr 就会定义三个等宽且垂直的网格轨道,同时还定义了四条垂直的网格线:一条在网格最左边,两条在每个网格轨道之间,还有一条在最右边。
在这里插入图片描述

1、网格线

网格线(grid line)——网格线构成了网格的框架。一条网格线可以水平或垂直,也可以位于一行或一列的任意一侧。如果指定了grid-gap的话,它就位于网格线上。

2、网格轨道

网格轨道(grid track)——一个网格轨道是两条相邻网格线之间的空间。网格有水平轨道(行)和垂直轨道(列)。

3、网格单元

网格单元(grid cell)——网格上的单个空间,水平和垂直的网格轨道交叉重叠的部分。

4、网格区域

网格区域(grid area)——网格上的矩形区域,由一个到多个网格单元组成。该区域位于两条垂直网格线和两条水平网格线之间。

网格线编号

在这里插入图片描述
可以在grid-columngrid-row属性中用网格线的编号指定网格元素的位置。
如果想要一个网格元素在垂直方向上跨越1号网格线到3号网格线,就需要给元素设置grid-column: 1 / 3
或者设置grid-row: 3 / 5让元素在水平方向上跨越3号网格线到5号网格线。
这两个属性一起就能指定一个元素应该放置的网格区域。

grid-columngrid-row

grid-columngrid-column-startgrid-column-end 的简写;
grid-rowgrid-row-startgrid-row-end 的简写。
中间的斜线只在简写属性里用于区分两个值,斜线前后的空格不作要求。

.box {
  gird-column: 1 / 3;
  grid-row: span 1;
}

其实还可以用一个特别的关键字 span 来指定 grid-rowgrid-column 的值。这个关键字告诉浏览器元素需要占据一个网格轨道。因为这里没有指出具体是哪一行,所以会根据网格元素的布局算法(placement algorithm)自动将其放到合适的位置。布局算法会将元素放在网格上可以容纳该元素的第一处可用空间。

替代语法

布局网格元素还有另外两个替代语法:命名的网格线和命名的网格区域。至于选择哪个纯属个人偏好。

命名的网格线

有时候记录所有网格线的编号实在太麻烦了,尤其是在处理很多网格轨道时。为了能简单点,可以给网格线命名,并在布局时使用网格线的名称而不是编号。声明网格轨道时,可以在中括号内写上网格线的名称,如下代码片段所示。

grid-template-columns: [start] 2fr [center] 1fr [end]

这条声明定义了两列的网格,三条垂直的网格线分别叫作start、center和end。
在这里插入图片描述

之后定义网格元素在网格中的位置时,可以不用编号而是用这些名称来声明,如下代码所示。

grid-column: start / end ;

这条声明将网格元素放在1号网格线(start)到2号网格线(center)之间的区域。
还可以给同一个网格线提供多个名称,比如下面的声明(为了可读性,这里将代码换行了)。

grid-template-columns:  [left-start] 2fr 
						[left-end right-start] 1fr 
						[right-end]

在这条声明里,2号网格线既叫作left-end也叫作right-start,之后可以任选一个名称使用。

这里还有一个彩蛋:将网格线命名为left-startleft-end,就定义了一个叫作left的区域,这个区域覆盖两个网格线之间的区域。-start-end后缀作为关键字,定义了两者之间的区域。如果给元素设置grid-column: left,它就会跨越从left-startleft-end的区域。

命名的网格区域

另一个方式是命名网格区域。不用计算或者命名网格线,直接用命名的网格区域将元素定位到网格中。实现这一方法需要借助网格容器的grid-template属性和网格元素的grid-area属性。

grid-template-areas属性使用了一种ASCII art的语法,可以直接在CSS中画一个可视化的网格形象。该声明给出了一系列加引号字符串,每一个字符串代表网格的一行,字符串内用空格区分每一列。

grid-template-areas: "a a" "b b" "c d" "c e"

在这里插入图片描述
使用时制定区域即可,grid-area: c
警告 每个命名的网格区域必须组成一个矩形。不能创造更复杂的形状,比如L或者U型。

还可以用句点(.)作为名称,这样便能空出一个网格单元。

实现开头图片的例子

在这里插入图片描述
方法一:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        .grid{
            display: grid;
            /* grid-template-columns: 1fr 1fr 1fr 1fr 1fr; */
            grid-template-columns: repeat(5, 1fr);
            /* grid-template-rows: 1fr 1fr 1fr; */
            grid-template-rows: repeat(3, 1fr);
            grid-gap: 1em;
            margin: 3em;
            
        }
        .grid > * {
            background: rgba(0, 0, 0, 0.6);
            color: white;
            padding: 2em;
            border-radius: 0.5em;
            font-size: 2em;
        }
        .grid .d{
            grid-column: 4 / 6;
            grid-row: 1 / 3;
        }
        .grid .f {
            grid-column: 2 / 4;
            grid-row: 2 / 4;
        }
    </style>
</head>
<body>
    <div class="grid">
        <div class="a">1</div>
        <div class="b">2</div>
        <div class="c">3</div>
        <div class="d">4</div>
        <div class="e">5</div>
        <div class="f">6</div>
        <div class="g">7</div>
        <div class="h">8</div>
        <div class="i">9</div>
    </div>
</body>
</html>

方法二:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        .grid{
            display: grid;
            grid-template-areas: "a b c d d" 
                                 "e f f d d" 
                                 "g f f h i";
            grid-gap: 1em;
            margin: 3em;
            
        }
        .grid > * {
            background: rgba(0, 0, 0, 0.6);
            color: white;
            padding: 2em;
            border-radius: 0.5em;
            font-size: 2em;
        }
        .grid .d{
            grid-area: d;
        } 
        .grid .f {
            grid-area: f;
        }
    </style>
</head>
<body>
    <div class="grid">
        <div class="a">1</div>
        <div class="b">2</div>
        <div class="c">3</div>
        <div class="d">4</div>
        <div class="e">5</div>
        <div class="f">6</div>
        <div class="g">7</div>
        <div class="h">8</div>
        <div class="i">9</div>
    </div>
</body>
</html>
  • 5
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值