【前端面试知识点】使用CSS Grid实现一个圣杯布局(头部、底部、三列自适应)

0 阅读6分钟

CSS Grid(网格布局)是CSS中一个强大的二维布局系统,它可以让你同时处理行和列,从而轻松创建复杂的网页布局。简单来说,Grid把页面划分成一个个网格,你可以将任意元素放入这些网格中,精确控制它们的位置、大小和对齐方式。

核心概念

  • 网格容器(Grid Container) :通过 display: grid 或 display: inline-grid 定义一个元素为网格容器。
  • 网格项(Grid Items) :网格容器的直接子元素自动成为网格项。
  • 行和列:使用 grid-template-rows 和 grid-template-columns 定义网格的结构。
  • 网格线(Grid Lines) :构成网格的分界线,用于定位网格项。
  • 网格区域(Grid Area) :由一组网格线围成的矩形区域,可以用 grid-area 给网格项命名或指定位置。

一个形象比喻

把CSS Grid想象成一个写字楼的工位布局,就很容易理解这些概念了:

  • 网格容器:就是整个办公区域,比如一整层楼。
  • 网格项:是摆放在每个工位上的办公桌(或其他家具)。注意,只有直接放在这层楼地面上的才算,放在桌子上的小物件不算。
  • 行和列:相当于把办公区域划分成的一排排和一列列,比如5排、4列。
  • 网格线:是每排之间、每列之间的过道。虽然我们看不到物理的线,但工人(浏览器)会根据过道的位置来定位每个工位。
  • 网格区域:可以是单个工位(比如某一张桌子),也可以是几个相邻工位合并成的一个大办公区(比如经理带几个员工一起办公)。你可以给这个区域起个名字,比如“销售部”,然后直接说“把销售部放在左上角那一片”。

这个比喻里,你可以自由地安排桌子(网格项)到不同的工位(网格单元格),甚至让一张桌子横跨两个工位(跨行/跨列),或者让几个桌子拼成一个区域(网格区域)。就像在写字楼里灵活调整工位一样,CSS Grid 让你能轻松实现各种网页布局。

CSS Grid 可以用来做什么?

  • 实现经典布局:如圣杯布局(头部、底部、三列自适应)、双飞翼布局等。
  • 响应式设计:结合媒体查询,轻松调整网格结构以适应不同屏幕尺寸。
  • 杂志/卡片式布局:创建复杂的图文混排、产品展示等。
  • 对齐控制:使用 justify-itemsalign-items 等属性精确控制网格项在单元格内的对齐。
  • 重叠效果:通过让多个网格项占据同一个网格区域,实现元素重叠。

简单示例

css

.container {
  display: grid;
  grid-template-columns: 200px 1fr 200px; /* 左中右:左200px,中间自适应,右200px */
  grid-template-rows: auto 1fr auto;      /* 上中下:头部和底部自动高度,中间占满剩余 */
  gap: 10px;                               /* 网格间隙 */
}

Grid vs Flexbox

  • Grid 是二维的,适合整体页面布局,同时管理行和列。
  • Flexbox 是一维的,适合组件内部的排列(如导航栏、卡片内容)。

Grid 和 Flexbox 常常结合使用:用 Grid 做页面宏观布局,用 Flexbox 处理局部细节。

使用CSS Grid实现一个圣杯布局(头部、底部、三列自适应)

效果:

image.png

以下是使用CSS Grid实现的圣杯布局HTML代码。它包含固定高度的头部和底部,左右两列宽度固定,中间列自适应,并配有简单的响应式设计(小屏幕时三列堆叠)。

html

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>CSS Grid 圣杯布局</title>
    <style>
        /* 基础重置 */
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            font-family: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
            line-height: 1.6;
            color: #1e293b;
            background: #f1f5f9;
            min-height: 100vh;
            display: flex;
            flex-direction: column;
        }

        /* 网格容器 — 圣杯布局核心 */
        .grid-container {
            display: grid;
            grid-template-areas: 
                "header header header"
                "left main right"
                "footer footer footer";
            grid-template-columns: 200px 1fr 200px;  /* 左右固定,中间自适应 */
            grid-template-rows: auto 1fr auto;       /* 头部和底部高度由内容撑开,中间占满剩余 */
            min-height: 100vh;                        /* 容器至少占满视口高度 */
            gap: 0;                                   /* 间距根据需要调整 */
            background: white;
            max-width: 1400px;
            margin: 0 auto;                            /* 水平居中,大屏留白 */
            box-shadow: 0 4px 20px rgba(0,0,0,0.05);
        }

        /* 公共区域样式 */
        header {
            grid-area: header;
            background: #1e3a8a;
            color: white;
            padding: 1.5rem;
            text-align: center;
            font-size: 1.8rem;
            font-weight: 600;
            letter-spacing: 1px;
            box-shadow: 0 2px 5px rgba(0,0,0,0.1);
        }

        footer {
            grid-area: footer;
            background: #0f172a;
            color: white;
            padding: 1.2rem;
            text-align: center;
            font-size: 1rem;
        }

        /* 左侧边栏 */
        .left-sidebar {
            grid-area: left;
            background: #f8fafc;
            padding: 1.5rem;
            border-right: 1px solid #e2e8f0;
        }

        /* 主要内容区 */
        main {
            grid-area: main;
            background: white;
            padding: 2rem;
        }

        /* 右侧边栏 */
        .right-sidebar {
            grid-area: right;
            background: #f8fafc;
            padding: 1.5rem;
            border-left: 1px solid #e2e8f0;
        }

        /* 内部装饰,仅用于展示 */
        .sidebar-title {
            font-weight: 600;
            font-size: 1.2rem;
            margin-bottom: 1rem;
            color: #334155;
            border-bottom: 2px solid #cbd5e1;
            padding-bottom: 0.5rem;
        }

        .sidebar-content {
            color: #475569;
        }

        main h2 {
            font-size: 2rem;
            margin-bottom: 1rem;
            color: #0f172a;
        }

        main p {
            margin-bottom: 1.2rem;
            color: #334155;
        }

        /* 响应式:屏幕宽度小于 700px 时,三列堆叠 */
        @media (max-width: 700px) {
            .grid-container {
                grid-template-areas: 
                    "header"
                    "main"
                    "left"
                    "right"
                    "footer";
                grid-template-columns: 1fr;           /* 单列 */
                grid-template-rows: auto auto auto auto auto; /* 各行自动高度 */
                min-height: 100vh;
            }

            /* 移除侧边栏的边框,避免视觉错乱 */
            .left-sidebar {
                border-right: none;
                border-top: 2px solid #e2e8f0;
            }
            .right-sidebar {
                border-left: none;
                border-top: 2px solid #e2e8f0;
            }

            header {
                font-size: 1.5rem;
                padding: 1rem;
            }

            main {
                padding: 1.5rem;
            }
        }

        /* 小屏时优化内边距 */
        @media (max-width: 480px) {
            .left-sidebar, .right-sidebar, main {
                padding: 1rem;
            }
            main h2 {
                font-size: 1.6rem;
            }
        }
    </style>
</head>
<body>
    <div class="grid-container">
        <!-- 头部 -->
        <header>
            🏰 圣杯布局 · CSS Grid
        </header>

        <!-- 左侧边栏 -->
        <aside class="left-sidebar">
            <div class="sidebar-title">📌 左侧边栏</div>
            <div class="sidebar-content">
                <p>宽度固定 200px</p>
                <ul style="margin-left: 1.2rem; color: #475569;">
                    <li>导航一</li>
                    <li>导航二</li>
                    <li>导航三</li>
                    <li>导航四</li>
                </ul>
            </div>
        </aside>

        <!-- 主要内容区 -->
        <main>
            <h2>✨ 主内容区 · 自适应</h2>
            <p>这是圣杯布局的核心区域,宽度自动占满剩余空间。在 Grid 布局中,通过 <code>grid-template-columns: 200px 1fr 200px;</code> 实现左右固定、中间自适应。</p>
            <p>圣杯布局的名字来源于早期的布局技巧,现在用 CSS Grid 可以轻松实现。无论中间内容多少,头部和底部始终固定在顶部和底部(因为 <code>grid-template-rows: auto 1fr auto</code> 让中间行占据剩余高度)。</p>
            <p>当屏幕宽度小于 700px 时,三列会自动堆叠为:头部、主内容、左侧栏、右侧栏、底部,方便移动端阅读。</p>
        </main>

        <!-- 右侧边栏 -->
        <aside class="right-sidebar">
            <div class="sidebar-title">🔗 右侧边栏</div>
            <div class="sidebar-content">
                <p>宽度固定 200px</p>
                <p>可以放广告、相关链接或次要信息。</p>
                <p>Grid 让布局变得无比简单。</p>
            </div>
        </aside>

        <!-- 底部 -->
        <footer>
            © 2026  ·  经典圣杯布局  ·  使用 CSS Grid 实现
        </footer>
    </div>
</body>
</html>