CSS布局 - 网格布局 -- 笔记3

发布于:2025-09-13 ⋅ 阅读:(23) ⋅ 点赞:(0)

CSS 提供了一些控制网页布局的几个重要工具,这里介绍网格布局。

网格布局

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

基础网格

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

看个例子:

<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>

.grid {
  display: grid; # 使用display: grid定义一个网格容器。容器会表现得像一个块级元素,100%填充可用宽度
  grid-template-columns: 1fr 1fr 1fr; # 分数单位: 三列等宽
  grid-template-rows: 1fr 1fr; # 等高的两行
  grid-gap: 0.5em; # 网格单元格添加间隔
}

.grid > * {
  backgroud-color: gray;
  color: white;
  padding: 2em;
  border-radius: 0.5em;
}
  • 使用display: grid定义一个网格容器。容器会表现得像一个块级元素,100%填充可用宽度

也可以使用 inline-grid​,这样元素就会在行内流动,且宽度只能够包含子元素,不过 inline-grid的使用频率不高。

  • grid-template-columns 和 grid-template-rows: 定义了网格每行每列的大小。本例使用了一种新单位fr,代表每一列(或每一行)的分数单位(fraction unit)​。这个单位跟 Flexbox 中 flex-grow 因子的表现一样。grid-template-columns: 1fr 1fr 1fr 表示三列等宽。不一定非得用分数单位,可以使用其他的单位,比如px、em 或百分数。也可以混搭这几种单位,例如,grid-template-columns: 300px 1fr 定义了一个固定宽度为300px的列,后面跟着一个会填满剩余可用空间的列。2fr 的列宽是 1fr 的两倍

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

网格剖析

在这里插入图片描述

  • 网格线(grid line):网格线构成了网格的框架。一条网格线可以水平或垂直,也可以位于一行或一列的任意一侧。指定了grid-gap的话,它就位于网格线上。
  • 网格轨道(grid track):一个网格轨道是两条相邻网格线之间的空间。网格有水平轨道(行)和垂直轨道(列)​。
  • 网格单元(grid cell):网格上的单个空间,水平和垂直的网格轨道交叉重叠的部分。
  • 网格区域(grid area):网格上的矩形区域,由一个到多个网格单元组成。该区域位于两条垂直网格线和两条水平网格线之间。

设计不必填满每个网格单元。在想留白的地方让网格单元为空即可。
使用Flexbox布局时,需要按照一定方式嵌套元素。比如用Flexbox定义了列,然后将另一个Flexbox嵌套在里面定义行。用网格实现同样的布局需要改一下HTML结构:将嵌套的HTML拉平。放在网格里的每个元素都必须是主要网格容器的子元素。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Grid Document</title>
  <style>
    :root {
      box-sizing: border-box;
    }

    *,
    ::before,
    ::after {
      box-sizing: inherit;
    }

    body {
      background-color: #709b90;
      font-family: Arial, Helvetica, sans-serif;
    }

	/* 网格容器 */
    .container {
      display: grid;
      grid-template-columns: 2fr 1fr; /* 定义两个垂直的网格轨道 */
      grid-template-rows: repeat(4, auto); /* 定义四个水平轨道,大小为auto */
      grid-gap: 1.5em;
      max-width: 1080px;

      margin: 0 auto;
    }

	/* 下面这几个网格元素,必须是网格容器的子元素 */
    header,
    nav {
      grid-column: 1 / 3; /* 从1号垂直网格线跨越到3号垂直网格线 */
      grid-row: span  1; /* 刚好占据一条水平网格轨道 */
    }

	/* 下面也是,将其他网格元素定位到不同的网格线之间 */
    .main {
      grid-column: 1 / 2;
      grid-row: 3 / 5;
    }

    .sidebar-top {
      grid-column: 2  / 3;
      grid-row: 3 / 4;
    }

    .sidebar-bottom {
      grid-column: 2 / 3;
      grid-row: 4 / 5;
    }

    .title {
      padding: 1.5em;
      background-color: #fff;
    }

    .title > :first-child {
      margin-top: 0;
    }

    .title * + * {
      margin-top: 1.5em;
    }

    .page-heading {
      margin: 0;
    }

    .site-nav {
      display: flex;
      margin: 0;
      padding: .5em;
      background-color: #5f4b44;
      list-style-type: none;
      border-radius: .2em;
    }

    .site-nav > li {
      margin-top: 0;
    }

    .site-nav > li > a {
      display: block;
      padding: .5em 1em;
      background-color: #cc6b5a;
      color: white;
      text-decoration: none;
    }

    .site-nav > li + li {
      margin-left: 1.5em;
    }

    .site-nav > .nav-right {
      margin-left: auto;
    }

    .login-form h3 {
      margin: 0;
      font-size: .9em;
      font-weight: bold;
      text-align: right;
      text-transform: uppercase;
    }

    .login-form input:not([type=checkbox]):not([type=radio]) {
      display: block;
      width: 100%;
      margin-top: 0;
    }

    .login-form button {
      margin-top: 1em;
      border: 1px solid #cc6b5a;
      background-color: white;
      padding: .5em 1em;
      cursor: pointer;
    }

    .centered {
      text-align: center;
    }

    .centered small {
      text-transform: uppercase;
    }

    .cost {
      display: flex;
      justify-content: center;
      align-items: center;
      line-height: .7;
    }

    .cost > span {
      margin-top: 0;
    }

    .cost-currency {
      font-size: 2em;
    }

    .cost-dollars {
      font-size: 4em;
    }

    .cost-cents {
      font-size: 1,5em;
      align-self: flex-start;
    }

    .cta-button {
      display: block;
      background-color: #cc6b5a;
      color: white;
      padding: .5em 1em;
      text-decoration: none;
    }

  </style>
</head>
<body>
  <div class="container">
    <header>
      <h1 class="page-heading">Ink</h1>
    </header>

    <nav>
      <ul class="site-nav">
        <li><a href="/">Home</a></li>
        <li><a href="/features">Features</a></li>
        <li><a href="/pricing">Pricing</a></li>
        <li><a href="/support">Support</a></li>
        <li class="nav-right">
          <a href="/about">About</a>
        </li>
      </ul>
    </nav>

    <main class="main title">
      <h1>Team collaboration done right</h1>
      <p>Thousands of teams from all over this world turn to <b>Ink</b> to communicate and get things done.</p>
    </main>

    <div class="sidebar-top title">
      <form class="login-form">
        <h3>Login</h3>
        <p>
          <label for="username">Username</label>
          <input id="username" type="text" name="username">
        </p>
        <p>
          <label for="password">Password</label>
          <input id="password" type="password" name="password">
        </p>
        <button type="submit">Login</button>
      </form>
    </div>

    <div class="sidebar-bottom title centered">
      <small>Starting at</small>
      <div class="cost">
        <span class="cost-currency">$</span>
        <span class="cost-dollars">20</span>
        <span class="cost-cents">.00</span>
      </div>
      <a class="cta-button" href="/pricing">Sign up</a>
    </div>
  </div>
</body>
</html>

在这里插入图片描述