gird 布局的详解

1,308 阅读12分钟

这是我参与11月更文挑战的第二天,活动详情请查看:2021最后一次更文挑战

前言

对上一篇发表的flex布局和grid布局详解 的继续补充。 在项目开始之前在继续说一下,容器相当于一个盒子外面的包装,项目是具体的内容,就是大箱子里面套用小箱子,大箱子就是容器,小箱子就是项目

11.jfif

基本概念

Grid 网格布局,将网页划分为一个个网格,可以任意组合不同的网格,对项目进行不同的排列顺序,flex是一维布局,只能针对项目的轴线设置项目放置的相对位置,而grid布局是将容器划分成,产生的单元格,然后指定项目所在的位置,可以把它看成是一个二维布局

<div class="container" >
    <div class="box"><p>11</p></div>
## <div class="box"><span>11</span></div>
    <div class="box"><h6>11</h6></div>
</div>

理解: 最外层的<div>元素就是容器,内层的三个<div>元素就是项目。项目只能是容器的顶层子元素,不包含项目的子元素,比如上面代码的<p><span><h6>元素就不是项目。 在开始之前,先弄明白一下含义

行和列

前面说过,grid 布局是在设置行和列来设置项目所在容器中的位置和大小。容器里面的水平区域称为"行"(row),垂直区域称为"列"(column)。

1.png

网格线

顾名思义,划分网格得线,水平网格线划分出行,垂直网格线划分出列。

2.png

容器的属性

grid-template-columns/rows:

grid-template-columns 和 grid-template-rows:分别设置属性的列宽和行高 补充:

display: grid;--声明一个容器
grid-template-columnsrepeat(auto-fill,500px); --宽度为500px,在一行内排列下的情况下,自动进行排列(尽可能多的排练)。
grid-template-columns300px 100px 200px;---设置3列,第一列列宽为300px,第二列宽为100px;第三列列宽为200px;
grid-template-columnsrepeat(3,500px) == grid-template-columns: 500px 500px 500px;
grid-template-columns300px 1fr 2fr;---设置3列,第一列的值为300px,第二列和第三列的值分别占据剩余空间的1/32/3的宽度;
grid-template-columns1fr 1fr minmax(300px,2fr)—前俩列均分,第三列的最大值300px最小值为前俩列的2倍;
grid-template-columns: 300px auto 300px;---第一列和第三列的宽为300px,中间一列的宽为更具浏览器的大小,自动取合适的大小。

例如:

  • grid-template-columns: repeat(3,200px);
<style>
    .container{
        width: 50%;
        display: grid;
        background-color: antiquewhite;
        box-shadow:  0px 2px 2px 0px rgba(9, 2, 4, 0.1);
    }
    .box{
        width: 100px;
        height: 100px;
        margin: 15px;
        background-color: coral;
    }
</style>

<!--设置一行有3列,且每个项目的宽度为200px-->
<h3>grid-template-columns: repeat(3,200px);</h3>
<div class="container" style="grid-template-columns: repeat(3,200px);">
    <div class="box">11</div>
    <div class="box">22</div>
    <div class="box">33</div>
    <div class="box">44</div>
</div>

<!--和上面的代码等价-->
<h3>grid-template-columns: 200px 200px 200px;</h3>
<div class="container" style="grid-template-columns: 200px 200px 200px;">
    <div class="box">11</div>
    <div class="box">22</div>
    <div class="box">33</div>
    <div class="box">44</div>
</div>

image.png

  • grid-template-columns: repeat(auto-fill,200px);
<!--在容器中能排列下的情况下京可能的多排列,每个项目的宽度为200px-->
<h3>grid-template-columns: repeat(auto-fill,200px);</h3>
<div class="container" style="grid-template-columns: repeat(auto-fill,200px);">
    <div class="box">11</div>
    <div class="box">22</div>
    <div class="box">33</div>
    <div class="box">44</div>
    <div class="box">55</div>
    <div class="box">66</div>
    <div class="box">77</div>
</div>

1637053754(1).png

1637053789(1).png

当屏幕为1100 * 937时这显示俩列,当为1980 * 1060 时显示4列

  • grid-template-columns: 100px 1fr 2fr
<!--获取3列,项目的第一列的宽度为100px,将剩余空间分成3等分,第二列宽度为1/3的宽,第三列的宽度为2/3的宽-->
<h3>grid-template-columns: 100px 1fr 2fr</h3>
<div class="container" style="height:100px;grid-template-columns: 100px 1fr 2fr;">
    <div style="background-color: coral">11</div>
    <div style="background-color: #1b9ed9">22</div>
    <div style="background-color: #f350ff">33</div>
</div>

image.png

不管屏幕多大,第一列的宽度都为100px,后俩列的宽度分别占1/3和2/3的宽度

  • grid-template-columns: 1fr 1fr minmax(300px,2fr)
<!--将容器的宽度分为4份,第一列和第二列宽度为1/4,第三列的宽度为最小为300px,最大占2/4的宽度-->
<h3>grid-template-columns: 1fr 1fr minmax(300px,2fr)</h3>
<div class="container" style="height:100px;grid-template-columns: 1fr 1fr minmax(300px,2fr);">
    <div style="background-color: coral">11</div>
    <div style="background-color: #1b9ed9">22</div>
    <div style="background-color: #f350ff">33</div>
</div>

image.png

-grid-template-columns: 100px auto 100px

<!--获取3列,第一列和第三列的宽度为固定值100px,第二列更具屏幕的大小自动计算宽度-->
<h3>grid-template-columns: 100px auto 100px</h3>
<div class="container" style="height:100px;grid-template-columns: 100px auto 100px">
    <div style="background-color: coral">11</div>
    <div style="background-color: #1b9ed9">22</div>
    <div style="background-color: #f350ff">33</div>
</div>

1637054792(1).png

1637054838(1).png

第二部分蓝色区域,当屏幕为1980 * 1060时明显比屏幕为703 * 937 时宽了许多

grid-gap:10px

设置行间隙和列间隙;grid-gap:10px ==grid-row-gap:10px;和grid-column-gap:10px;

<p><strong>设置的间距之对于当前的行列的内部有效</strong></p>
<h3>grid-gap: 20px;</h3>
<div class="container" style="grid-gap: 20px;">
    <div class="box">11</div>
    <div class="box">22</div>
    <div class="box">33</div>
    <div class="box">44</div>
</div>
<h3>grid-column-gap: 20px;grid-row-gap: 20px;</h3>
<div class="container" style="grid-column-gap: 20px;grid-row-gap: 20px;">
    <div class="box">11</div>
    <div class="box">22</div>
    <div class="box">33</div>
    <div class="box">44</div>
</div>

image.png

grid-template-areas

定义区域,一个区域有一个或者多个单元格组成,一般和网格元素的grid-area一起配合使用;

<style>
    .container{
        width: 50%;
        display: grid;
        grid-gap: 10px;
        grid-template-columns: 120px  120px  120px;
        grid-template-areas:
                ". header  header "
                "sidebar content content"
                "footer footer footer";
        /*划分9个单元格,. (点)代表这个区域没有用到*/
        background-color: antiquewhite;
        color: #444;
    }
    .sidebar {
        grid-area: sidebar;
    }
    .footer{
        grid-area: footer;
    }
    .content {
        grid-area: content;
    }

    .header {
        grid-area: header;
    }
    .box {
        background-color: #1b9ed9;
        color: #fff;
        border-radius: 5px;
        padding: 20px;
        font-size: 150%;
    }
</style>
<div class="container">
    <div class=" box sidebar">sidebar</div>
    <div class=" box content">content</div>
    <div class=" box footer">footer</div>
    <div class=" box header">header</div>
</div>

image.png

通过grid-template-areas来指定class的样式的位置,就可以轻松的实现布局,将项目放置在那个位置

grid-auto-flow

自动布局算法,在一行内能排列下的情况下,依照先行后列(默认)的原则依次布局排列。也可以设置先列后行的写法,即:grid-auto-flow: column

  • grid-auto-flow: row
<style>
    .container{
        width: 50%;
        display: grid;
        grid-template-columns: repeat(auto-fill,150px);
        background-color: antiquewhite;
        box-shadow:  0px 2px 2px 0px rgba(9, 2, 4, 0.1);
    }
    .container1{
        width: 50%;
        display: grid;
        grid-template-columns: repeat(auto-fill,300px);
        background-color: antiquewhite;
        box-shadow:  0px 2px 2px 0px rgba(9, 2, 4, 0.1);
    }
    .box{
        width: 100px;
        height: 100px;
        margin: 15px;
        background-color: coral;
    }
</style>
<h3>grid-auto-flow: row;</h3>
<div class="container" style="grid-auto-flow: row;">
    <div class="box">11</div>
    <div class="box">22</div>
    <div class="box">33</div>
    <div class="box">44</div>
    <div class="box">55</div>
    <div class="box">66</div>
    <div class="box">77</div>
    <div class="box">88</div>
</div>

image.png

  • grid-auto-flow: row dense; 设置某些项目指定位置之后,其他项目的怎么自动放置。
<h3>grid-auto-flow: row dense;</h3>
<!--设置了grid-auto-flow: row dense; dense 这个属性值之后就会让其容器内尽可能的多排练一些内容,而不会很大的空隙-->
<div class="container1" style="grid-auto-flow: row dense;">
    <div class="box">11</div>
    <div style="height: 100px;width: 200px;margin:10px;background-color: aqua">22</div>
    <div class="box">33</div>
    <div style="height: 100px;width: 150px;margin:10px;background-color: brown">44</div>
    <div class="box">55</div>
    <div class="box">66</div>
    <div class="box">77</div>
    <div class="box">88</div>
</div>

image.png

justify-items、align-items

justify-items 设置单元格(项目)内容的水平(左中右)位置;align-items设置单元格(项目)内容的垂直(上中下)位置;place-items = align-items +justify-items 这俩个属性的写法完全相同,有4个属性值:

start:对齐单元格的起始边缘。
end:对齐单元格的结束边缘。
center:单元格内部居中。
stretch:拉伸,占满单元格的整个宽度(默认值)。
<style>
    .container{
        width: 50%;
        display: grid;
        background-color: antiquewhite;
        box-shadow:  0px 2px 2px 0px rgba(9, 2, 4, 0.1);
        grid-template-columns: repeat(auto-fill,200px);
        grid-template-rows: repeat(3,100px);
        grid-gap: 15px;
    }
    .box{
        width: 100px;
        height: 100px;
        background-color: coral;
    }
</style>
  • justify-items: start
<!--当前项目在单元格中的水平位置-->
<h3>justify-items: start</h3>
<div class="container" style="justify-items: start">
    <div class="box">11</div>
    <div class="box">22</div>
    <div class="box">33</div>
    <div class="box">44</div>
    <div class="box">55</div>
</div>

image.png

  • justify-items: center
<h3>justify-items: center</h3>
<div class="container" style="justify-items: center">
    <div class="box">11</div>
    <div class="box">22</div>
    <div class="box">33</div>
    <div class="box">44</div>
    <div class="box">55</div>
</div>

当前项目在单元格中的位置为水平居中,如下图

1637113961(1).png

  • align-items: start
<style>
    .container{
        width: 50%;
        display: grid;
        background-color: antiquewhite;
        box-shadow:  0px 2px 2px 0px rgba(9, 2, 4, 0.1);
        grid-template-columns: repeat(auto-fill,200px);
        grid-template-rows: repeat(3,150px);
        grid-gap: 15px;
    }
    .box{
        width: 100px;
        height: 100px;
        background-color: coral;
    }
</style>
<h3>align-items: start</h3>
<!--项目在单元格中的垂直位置-->
<div class="container" style="align-items: start">
    <div class="box">11</div>
    <div class="box">22</div>
    <div class="box">33</div>
    <div class="box">44</div>
    <div class="box">55</div>
</div>

image.png

  • align-items: center
<h3>align-items: center</h3>
<div class="container" style="align-items: center">
    <div class="box">11</div>
    <div class="box">22</div>
    <div class="box">33</div>
    <div class="box">44</div>
    <div class="box">55</div>
</div>

当前项目在单元格中的位置为垂直居中,如下图 1637114276(1).png

  • place-items: start end;

    place-items:<align-items> <justify-items>

<style>

    .container{
        width: 50%;
        display: grid;
        background-color: antiquewhite;
        box-shadow:  0px 2px 2px 0px rgba(9, 2, 4, 0.1);
        grid-template-columns: repeat(auto-fill,200px);
        grid-template-rows: repeat(3,200px);
        grid-gap: 15px;
    }
    .box{
        width: 100px;
        height: 100px;
        background-color: coral;
    }

</style>
<h3>place-items: start end-- 在单元格内,box的位置在右上角</h3>
<div class="container" style="place-items: start end">
    <div class="box">11</div>
    <div class="box">22</div>
    <div class="box">33</div>
    <div class="box">44</div>
    <div class="box">55</div>
</div>

1637114479(1).png

理解:(上图) 垂直对齐方式为顶端对齐,水平方式尾端对齐--所以,所有的盒子相对于单元格来说位置在右上角。

  • place-items: center center
<h3>place-items: center center-- 在单元格内,box的位置在中间(上下左右间距相等 )</h3>
<div class="container" style="place-items: center center">
    <div class="box">11</div>
    <div class="box">22</div>
    <div class="box">33</div>
    <div class="box">44</div>
    <div class="box">55</div>
</div>

1637114726(1).png

justify-content、align-content

justify-content整个内容区域在容器里面的水平位置(左中右);align-content 整个内容区域的垂直位置(上中下)。place-content = align-content +justify-content 上面俩个属性的值都可以取下面的值:

start:对齐容器的起始边框。
end:对齐容器的结束边框。
center:容器内部居中。
stretch:项目大小没有指定时,拉伸占据整个网格容器。
space-around:每个项目两侧的间隔相等。所以,项目之间的间隔比项目与容器边框的间隔大一倍
space-between:项目与项目的间隔相等,项目与容器边框之间没有间隔。
space-evenly:项目与项目的间隔相等,项目与容器边框之间也是同样长度的间隔。
<style>
    .container{
        width: 50%;
        display: grid;
        background-color: antiquewhite;
        box-shadow:  0px 2px 2px 0px rgba(9, 2, 4, 0.1);
        grid-template-columns: repeat(auto-fill,200px);
        grid-template-rows: repeat(3,150px);
        grid-gap: 10px;
    }
    .box{
        background-color: coral;
    }
    .box1{
        width: 100px;
        height: 100px;
        background-color: coral;
    }
</style>
  • justify-content: start
<h3>justify-content: start</h3>
<div class="container" style="justify-content: start">
    <div class="box">11</div>
    <div class="box">22</div>
    <div class="box">33</div>
    <div class="box">44</div>
    <div class="box">55</div>
</div>

image.png

  • justify-content: center
<h3>justify-content: center</h3>
<div class="container" style="justify-content: center">
    <div class="box">11</div>
    <div class="box">22</div>
    <div class="box">33</div>
    <div class="box">44</div>
    <div class="box">55</div>
</div>

1637115055(1).png

  • align-content: center
<style>
    .container{
        height: 500px;
        display: grid;
        background-color: antiquewhite;
        box-shadow:  0px 2px 2px 0px rgba(9, 2, 4, 0.1);
        grid-template-columns: repeat(auto-fill,200px);
        grid-gap: 10px;
    }
    .box{
        height: 100px;
        width: 100px;
        background-color: coral;
    }
</style>
<h3>align-content: center</h3>
<div class="container" style="align-content: center">
    <div class="box">11</div>
    <div class="box">22</div>
    <div class="box">33</div>
    <div class="box">44</div>
    <div class="box">55</div>
</div>

image.png

  • align-content: stretch
<h3>align-content: stretch</h3>
<div class="container" style="height:50%;display:grid;grid-column-gap: 10px;align-content: stretch">
    <div class="box">宽和高为100</div>
    <div style="background-color: coral">22</div>
    <div style="background-color: coral">33</div>
    <div style="background-color: coral">44</div>
    <div style="background-color: coral">55</div>
</div>

当项目没有指定的大小时,拉伸占据整个个项目的大小。如下图,第一个box 指定大小只显示100px,而其他的box则占满了整个单元格

image.png

-place-content: start end

<h3>place-content: start end--右上角</h3>
<div class="container" style="place-content: start end">
    <div class="box">11</div>
    <div class="box">22</div>
    <div class="box">33</div>
    <div class="box">44</div>
    <div class="box">55</div>
</div>

垂直位置start在整个容器的上方,水平位置end在整个容器的末尾,所以项目的位置在容器位置的右上角的位置 image.png

<h3>place-content: end start--左下角</h3>
<div class="container" style="place-content: end start">
    <div class="box">11</div>
    <div class="box">22</div>
    <div class="box">33</div>
    <div class="box">44</div>
    <div class="box">55</div>
</div>

垂直位置end在整个容器的下方,水平位置start在整个容器的起始,所以项目的位置在容器位置的左下角的位置

image.png

grid-auto-columns 和 grid-auto-rows

grid-auto-columns 和 grid-auto-rows 定义隐式网格

  • 显式网格:就是使用grid-template-columns 和 grid-template-rows 属性中定义的行和列。
  • 隐式网格:当内容超出了设置的行和列时,网格将会在创建隐式的行和列。(如果指定增加的宽和高。浏览器会更具单元格本身的大小来确定网格的行高和列宽)
<style>
    .container{
        display: grid;
        grid-template-columns: 200px 200px;
        /*  只设置了两行,但实际的数量会超出两行,超出的行高会以 grid-auto-rows 算 */
        grid-template-rows: 100px 100px;
        grid-gap: 10px 20px;
        background: antiquewhite;
    }
    .box{
        width: 100px;
        height: 100px;
        background-color: coral;
    }
</style>

只设置了两行,但实际的数量会超出两行,超出的行高会以 grid-auto-rows 计算

<h3>显式的创建2行2列的内容</h3>
<div class="container">
    <div class="box">11</div>
    <div class="box">22</div>
    <div class="box">33</div>
    <div class="box">44</div>
    <div class="box">55--自动根据单元格宽和高创建大小</div>
</div>

image.png

<h3>显式的创建2行2列的内容,添加隐式的创建内容</h3>
<div class="container" style="grid-auto-rows: 50px">
    <div class="box">11</div>
    <div class="box">22</div>
    <div class="box">33</div>
    <div class="box">44</div>
    <div class="box">55--隐式创建行高50</div>
</div>

image.png

补充内容

  • grid-column-start 属性:左边框所在的垂直网格线
  • grid-column-end 属性:右边框所在的垂直网格线
  • grid-row-start 属性:上边框所在的水平网格线
  • grid-row-end 属性:下边框所在的水平网格线
<style>
    .container{
        display: grid;
        width: 50%;
        grid-template-columns: repeat(3, 1fr);
        grid-gap: 20px;
        grid-auto-rows: minmax(100px, 150px);
    }
    .box1{
        grid-column-start: 1;
        grid-column-end: 2;
        background: peru;
    }
    .box2{
        grid-column-start: 2;
        grid-column-end: 4;
        grid-row-start: 1;
        grid-row-end: 2;
        z-index: 1;
        background: blueviolet;
    }
    .box3 {
        grid-column-start: 3;
        grid-column-end: 4;
        grid-row-start: 1;
        grid-row-end: 4;
        background: blue;
        /*z-index:5;*/
    }
    .box4 {
        grid-column-start: 1;
        grid-column-end: 2;
        grid-row-start: 2;
        grid-row-end: 5;
        background: yellow;
    }
    .box5 {
        grid-column-start: 2;
        grid-column-end: 2;
        grid-row-start: 3;
        grid-row-end: 5;
        background: coral;
    }
</style>
<h3>通过设置网格线,来确定布局</h3>
<div class="container">
    <div class="box1">111</div>
    <div class="box2">222<p><strong>第二个盒子以第2根垂直网格线开始一直到第4根垂直网格线</strong></p></div>
    <div class="box3" style="padding-top: 80%">333<p><strong>第三个盒子以第3根垂直网格线开始一直到第4根垂直网格线</strong></p></div>
    <div class="box4">444</div>
    <div class="box5">555</div>
</div>

** 第二个box 和第三个box 有公共的部分,可以使用z-index 来设置他们的层级 **

image.png

最后

grid 布局到此为止,有不足之处,欢迎大家补充! 获取项目演示的代码