1.2 CSS 基础选择器、盒模型、flex 布局、grid 布局

我来为实习生准备一份生动细致的CSS教程。让我用代码演示的方式,把这几个核心概念讲透。


CSS 核心概念实战教程

一、基础选择器:CSS的"瞄准镜"

选择器就是告诉浏览器:我要选谁,给它穿什么样的衣服

1. 基础选择器一览

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>CSS选择器实战</title>
    <style>
        /* ========== 1. 元素选择器:选中所有同名标签 ========== */
        p {
            color: #333;
            line-height: 1.6;
        }

        /* ========== 2. 类选择器:选中特定类别的元素(最常用) ========== */
        .highlight {
            background: linear-gradient(120deg, #ffeaa7 0%, #ffeaa7 100%);
            padding: 2px 6px;
            border-radius: 4px;
        }

        .btn {
            display: inline-block;
            padding: 10px 20px;
            border-radius: 6px;
            cursor: pointer;
            transition: all 0.3s ease;
        }

        /* ========== 3. ID选择器:选中唯一元素(身份证号) ========== */
        #header {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            padding: 30px;
            text-align: center;
        }

        /* ========== 4. 后代选择器:选中"儿子、孙子、重孙..." ========== */
        .nav ul li {
            display: inline-block;
            margin: 0 15px;
        }

        /* ========== 5. 子选择器:只选直接儿子,不选孙子 ========== */
        .nav > ul > li {
            font-weight: bold;
        }

        /* ========== 6. 相邻兄弟选择器:紧挨着的下一个兄弟 ========== */
        h2 + p {
            font-size: 1.1em;
            color: #666;
            border-left: 3px solid #667eea;
            padding-left: 15px;
        }

        /* ========== 7. 通用兄弟选择器:后面所有兄弟 ========== */
        h2 ~ p {
            margin-top: 10px;
        }

        /* ========== 8. 属性选择器:按HTML属性选 ========== */
        input[type="text"] {
            border: 2px solid #ddd;
            padding: 8px 12px;
            border-radius: 4px;
        }

        input[type="text"]:focus {
            border-color: #667eea;
            outline: none;
        }

        /* 选中所有带有data-tip属性的元素 */
        [data-tip] {
            position: relative;
        }

        /* ========== 9. 伪类选择器:特殊状态 ========== */
        /* :hover - 鼠标悬停 */
        .btn:hover {
            transform: translateY(-2px);
            box-shadow: 0 10px 20px rgba(0,0,0,0.2);
        }

        /* :nth-child() - 第几个孩子 */
        .list li:nth-child(odd) {
            background: #f8f9fa;
        }

        .list li:nth-child(even) {
            background: #e9ecef;
        }

        /* :first-child, :last-child */
        .list li:first-child {
            border-top-left-radius: 8px;
            border-top-right-radius: 8px;
        }

        /* ========== 10. 伪元素:创造不存在的元素 ========== */
        /* ::before - 在元素内容前面插入 */
        .quote::before {
            content: '"';
            font-size: 3em;
            color: #667eea;
            float: left;
            margin-right: 10px;
            line-height: 0.8;
        }

        /* ::after - 在元素内容后面插入 */
        .external-link::after {
            content: ' ↗';
            font-size: 0.8em;
            opacity: 0.7;
        }

        /* 选中段落的第一行 */
        p::first-line {
            font-weight: 500;
        }
    </style>
</head>
<body>
    <header id="header">
        <h1>🎯 CSS选择器实战演练</h1>
        <p>学会"瞄准",才能精准控制样式</p>
    </header>

    <nav class="nav">
        <ul>
            <li>首页</li>
            <li>产品
                <ul>
                    <li>Web开发</li>
                    <li>移动应用</li>
                </ul>
            </li>
            <li>关于</li>
        </ul>
    </nav>

    <main style="max-width: 800px; margin: 40px auto; padding: 0 20px;">
        <h2>什么是CSS选择器?</h2>
        <p>选择器就像CSS的<span class="highlight">瞄准镜</span>,告诉浏览器:"我要选谁"。</p>
        <p>没有瞄准镜,你的样式子弹就会乱飞,打不中目标。</p>

        <h2>常用选择器对比</h2>
        <ul class="list">
            <li><strong>元素选择器</strong> - 选中所有同名标签(如所有p标签)</li>
            <li><strong>类选择器 .class</strong> - 选中特定类别的元素(最灵活)</li>
            <li><strong>ID选择器 #id</strong> - 选中唯一元素(像身份证号)</li>
            <li><strong>后代选择器 空格</strong> - 选中所有后代(儿子、孙子...)</li>
            <li><strong>子选择器 ></strong> - 只选直接儿子</li>
        </ul>

        <div class="quote">
            好的选择器命名,胜过千言万语。类名要语义化,不要用.red、.big这种表现层命名。
        </div>

        <p>
            <a href="#" class="btn external-link">查看文档</a>
            <a href="#" class="btn">了解更多</a>
        </p>

        <form style="margin-top: 30px;">
            <input type="text" placeholder="输入你的名字" data-tip="必填">
            <input type="email" placeholder="输入邮箱">
        </form>
    </main>
</body>
</html>

选择器优先级(权重)

想象一场** specificity 拳击赛**,谁权重高谁赢:

css 复制代码
/* 权重:0-0-1 (1分) */
p { color: red; }

/* 权重:0-1-0 (10分) */
.text { color: blue; }

/* 权重:1-0-0 (100分) */
#unique { color: green; }

/* 权重:1-0-1 (101分) */
#unique p { color: purple; }

/* 终极武器:!important (10000分,慎用!) */
p { color: black !important; }

记忆口诀:内联样式(1000) > ID(100) > 类/属性/伪类(10) > 元素/伪元素(1)


二、盒模型:CSS的"盒子哲学"

1. 盒模型核心概念

每个HTML元素都是一个盒子,从内到外四层:

复制代码
┌─────────────────────────────┐
│          margin(外边距)      │  ← 盒子与其他盒子的距离
│   ┌─────────────────────┐   │
│   │     border(边框)   │   │  ← 盒子的"皮肤"
│   │   ┌─────────────┐   │   │
│   │   │  padding(内边距)│   │   │  ← 内容与边框的缓冲空间
│   │   │   ┌─────┐   │   │   │
│   │   │   │content│   │   │   │  ← 真正的内容(文字、图片)
│   │   │   │(内容) │   │   │   │
│   │   │   └─────┘   │   │   │
│   │   └─────────────┘   │   │
│   └─────────────────────┘   │
└─────────────────────────────┘

2. 盒模型实战代码

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>盒模型深度解析</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box; /* 关键:边框盒模型 */
        }

        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            background: #f0f2f5;
            padding: 40px 20px;
        }

        .container {
            max-width: 1000px;
            margin: 0 auto;
        }

        h1 {
            text-align: center;
            margin-bottom: 40px;
            color: #333;
        }

        /* ========== 标准盒模型 vs 怪异盒模型 ========== */
        .box-model-demo {
            display: flex;
            gap: 40px;
            flex-wrap: wrap;
            justify-content: center;
            margin-bottom: 40px;
        }

        .box {
            width: 300px;
            height: 200px;
            padding: 30px;
            border: 5px solid #667eea;
            margin: 20px;
            background: white;
        }

        /* content-box:默认值,width只包含content */
        .content-box {
            box-sizing: content-box;
            background: #ffeaa7;
        }

        /* border-box:width包含content+padding+border(推荐!) */
        .border-box {
            box-sizing: border-box;
            background: #74b9ff;
        }

        .box-label {
            text-align: center;
            margin-top: 10px;
            font-weight: bold;
            color: #555;
        }

        /* ========== 盒模型各属性详解 ========== */
        .properties-demo {
            background: white;
            padding: 30px;
            border-radius: 12px;
            box-shadow: 0 4px 6px rgba(0,0,0,0.1);
        }

        .demo-item {
            margin-bottom: 30px;
        }

        .demo-item h3 {
            color: #667eea;
            margin-bottom: 15px;
        }

        /* margin 外边距 */
        .margin-demo {
            background: #dfe6e9;
            padding: 20px;
        }

        .margin-box {
            background: white;
            padding: 20px;
            margin: 20px; /* 四边都是20px */
            /* 或 margin: 10px 20px 30px 40px; 上右下左 */
            border: 2px solid #74b9ff;
        }

        /* margin 塌陷演示 */
        .collapse-container {
            background: #ffeaa7;
            padding: 10px;
        }

        .collapse-box {
            background: white;
            margin: 20px 0;
            padding: 10px;
            border: 1px solid #333;
        }

        /* padding 内边距 */
        .padding-demo {
            background: #74b9ff;
            padding: 30px;
        }

        .padding-content {
            background: white;
            padding: 40px; /* 内容与边框的距离 */
            text-align: center;
        }

        /* border 边框 */
        .border-demo {
            display: flex;
            gap: 20px;
            flex-wrap: wrap;
        }

        .border-item {
            padding: 20px;
            background: white;
        }

        .border-solid { border: 3px solid #e17055; }
        .border-dashed { border: 3px dashed #00b894; }
        .border-dotted { border: 3px dotted #0984e3; }
        .border-double { border: 4px double #6c5ce7; }
        .border-radius { 
            border: 3px solid #fdcb6e; 
            border-radius: 12px; /* 圆角 */
        }
        .border-circle {
            border: 3px solid #e84393;
            border-radius: 50%; /* 圆形 */
            width: 80px;
            height: 80px;
            display: flex;
            align-items: center;
            justify-content: center;
        }

        /* 实际应用:卡片设计 */
        .card {
            background: white;
            border-radius: 16px;
            padding: 24px;
            margin: 20px;
            box-shadow: 0 10px 30px rgba(0,0,0,0.1);
            border: 1px solid #e0e0e0;
            transition: transform 0.3s ease, box-shadow 0.3s ease;
        }

        .card:hover {
            transform: translateY(-5px);
            box-shadow: 0 20px 40px rgba(0,0,0,0.15);
        }

        .card h4 {
            color: #333;
            margin-bottom: 10px;
        }

        .card p {
            color: #666;
            line-height: 1.6;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>📦 CSS盒模型:一切都是盒子</h1>

        <!-- 盒模型对比 -->
        <div class="box-model-demo">
            <div>
                <div class="box content-box">
                    <strong>content-box(标准)</strong><br>
                    width: 300px<br>
                    实际占用宽度 = 300 + 30×2 + 5×2 = <span style="color:#e17055">370px</span>
                </div>
                <div class="box-label">content-box:width只包含content</div>
            </div>
            <div>
                <div class="box border-box">
                    <strong>border-box(推荐)</strong><br>
                    width: 300px<br>
                    实际占用宽度 = <span style="color:#00b894">300px</span>(已包含padding和border)
                </div>
                <div class="box-label">border-box:width包含content+padding+border</div>
            </div>
        </div>

        <!-- 各属性详解 -->
        <div class="properties-demo">
            <div class="demo-item">
                <h3>🌊 margin(外边距):盒子与盒子的距离</h3>
                <div class="margin-demo">
                    <div class="margin-box">我有20px的外边距</div>
                    <div class="margin-box">我也有20px的外边距</div>
                </div>
                <p style="margin-top:10px;color:#666;">💡 注意:垂直相邻的margin会<strong>塌陷</strong>(取最大值),水平不会。</p>
            </div>

            <div class="demo-item">
                <h3>🎨 padding(内边距):内容与边框的缓冲</h3>
                <div class="padding-demo">
                    <div class="padding-content">
                        我有40px的内边距<br>
                        文字不会贴边,呼吸感更好
                    </div>
                </div>
            </div>

            <div class="demo-item">
                <h3>🖼️ border(边框):盒子的"皮肤"</h3>
                <div class="border-demo">
                    <div class="border-item border-solid">solid<br>实线</div>
                    <div class="border-item border-dashed">dashed<br>虚线</div>
                    <div class="border-item border-dotted">dotted<br>点线</div>
                    <div class="border-item border-double">double<br>双线</div>
                    <div class="border-item border-radius">radius<br>圆角</div>
                    <div class="border-item border-circle">circle<br>圆形</div>
                </div>
            </div>
        </div>

        <!-- 实战应用 -->
        <h2 style="text-align:center;margin:40px 0 20px;">实战:用盒模型做一张卡片</h2>
        <div style="display:flex;justify-content:center;">
            <div class="card">
                <h4>🚀 产品卡片</h4>
                <p>content(内容)+ padding(内边距24px)+ border(边框1px)+ margin(外边距20px)= 完美的卡片设计</p>
            </div>
        </div>
    </div>
</body>
</html>

盒模型关键记忆点

属性 作用 常见坑
content-box 标准模式,width=content 实际宽度会超出预期(要加padding和border)
border-box 怪异模式,width=content+padding+border **强烈推荐!**设置width后不会再被padding撑大
margin 外边距 垂直方向会塌陷(取最大值)
padding 内边距 会增加元素总尺寸(除非用border-box)
border 边框 默认3D效果,建议配合border-radius美化

三、Flex布局:一维布局的"瑞士军刀"

Flex(弹性盒子)专门解决一维布局问题(单行或单列),让元素在容器内灵活排列。

1. Flex核心概念

复制代码
┌─────────────────────────────────────────┐
│              flex-container            │  ← 父容器( display: flex )
│  ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐     │
│  │item │ │item │ │item │ │item │     │  ← flex-item(子元素)
│  │  1  │ │  2  │ │  3  │ │  4  │     │
│  └─────┘ └─────┘ └─────┘ └─────┘     │
│  ←────── main axis(主轴)──────→     │
│  ↑                                    │
│  cross axis(交叉轴)                  │
└─────────────────────────────────────────┘

2. Flex实战代码

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Flex布局完全指南</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            background: #f5f6fa;
            padding: 20px;
        }

        .section {
            background: white;
            margin-bottom: 30px;
            padding: 30px;
            border-radius: 12px;
            box-shadow: 0 2px 10px rgba(0,0,0,0.08);
        }

        h2 {
            color: #2c3e50;
            margin-bottom: 20px;
            border-bottom: 3px solid #3498db;
            padding-bottom: 10px;
        }

        h3 {
            color: #34495e;
            margin: 20px 0 10px;
            font-size: 1.1em;
        }

        /* ========== Flex容器基础 ========== */
        .flex-container {
            display: flex;
            background: #ecf0f1;
            padding: 20px;
            border-radius: 8px;
            min-height: 150px;
            gap: 10px; /* 子元素间距(现代浏览器推荐) */
        }

        .flex-item {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            padding: 20px;
            border-radius: 8px;
            font-weight: bold;
            text-align: center;
            min-width: 80px;
        }

        /* ========== 1. flex-direction:主轴方向 ========== */
        .direction-row {
            flex-direction: row; /* 默认:水平从左到右 */
        }

        .direction-row-reverse {
            flex-direction: row-reverse; /* 水平从右到左 */
        }

        .direction-column {
            flex-direction: column; /* 垂直从上到下 */
            min-height: 300px;
        }

        /* ========== 2. justify-content:主轴对齐 ========== */
        .justify-start {
            justify-content: flex-start; /* 默认:左对齐 */
        }

        .justify-center {
            justify-content: center; /* 居中 */
        }

        .justify-end {
            justify-content: flex-end; /* 右对齐 */
        }

        .justify-between {
            justify-content: space-between; /* 两端对齐,中间平均分布 */
        }

        .justify-around {
            justify-content: space-around; /* 每个元素周围空间相等 */
        }

        .justify-evenly {
            justify-content: space-evenly; /* 空间完全平均分配 */
        }

        /* ========== 3. align-items:交叉轴对齐 ========== */
        .align-stretch {
            align-items: stretch; /* 默认:拉伸填满容器高度 */
        }

        .align-start {
            align-items: flex-start; /* 顶部对齐 */
        }

        .align-center {
            align-items: center; /* 垂直居中(最常用!) */
        }

        .align-end {
            align-items: flex-end; /* 底部对齐 */
        }

        /* 制造不同高度的子元素,方便看效果 */
        .align-start .flex-item:nth-child(1) { height: 60px; }
        .align-start .flex-item:nth-child(2) { height: 100px; }
        .align-start .flex-item:nth-child(3) { height: 40px; }

        /* ========== 4. flex-wrap:换行 ========== */
        .flex-wrap {
            flex-wrap: wrap; /* 允许换行 */
        }

        .flex-nowrap {
            flex-wrap: nowrap; /* 默认:不换行,可能溢出 */
        }

        .wrap-item {
            width: 150px; /* 固定宽度,测试换行 */
        }

        /* ========== 5. align-content:多行对齐(需wrap) ========== */
        .align-content-start {
            flex-wrap: wrap;
            align-content: flex-start;
            height: 300px;
        }

        .align-content-center {
            flex-wrap: wrap;
            align-content: center;
            height: 300px;
        }

        .align-content-between {
            flex-wrap: wrap;
            align-content: space-between;
            height: 300px;
        }

        /* ========== 6. flex子项属性 ========== */
        .flex-grow-demo .flex-item {
            flex-grow: 1; /* 默认0,设为1则平均分配剩余空间 */
        }

        .flex-grow-demo .flex-item:nth-child(2) {
            flex-grow: 2; /* 第二个元素占2份,其他占1份 */
        }

        /* flex-shrink:空间不足时如何收缩 */
        .flex-shrink-demo .flex-item {
            width: 300px; /* 故意设大,测试收缩 */
            flex-shrink: 1; /* 默认1,允许收缩 */
        }

        .flex-shrink-demo .flex-item:nth-child(2) {
            flex-shrink: 0; /* 不允许收缩,保持300px */
            background: #e74c3c;
        }

        /* flex-basis:定义元素在分配空间前的"理想尺寸" */
        .flex-basis-demo .flex-item {
            flex-basis: 200px; /* 基础尺寸200px,再分配剩余空间 */
        }

        /* flex简写:grow shrink basis */
        .flex-shortcut .flex-item {
            flex: 1; /* 等于 flex: 1 1 0% */
        }

        .flex-shortcut .flex-item:nth-child(2) {
            flex: 2; /* 占2份 */
        }

        /* align-self:单个子项的对齐方式 */
        .align-self-demo {
            align-items: center;
            height: 200px;
        }

        .align-self-demo .flex-item:nth-child(2) {
            align-self: flex-start; /* 单独顶部对齐 */
            background: #e74c3c;
        }

        .align-self-demo .flex-item:nth-child(4) {
            align-self: flex-end; /* 单独底部对齐 */
            background: #27ae60;
        }

        /* order:排序(默认0,越小越靠前) */
        .order-demo .flex-item:nth-child(1) { order: 3; }
        .order-demo .flex-item:nth-child(2) { order: 1; }
        .order-demo .flex-item:nth-child(3) { order: 2; }
        .order-demo .flex-item:nth-child(4) { order: 0; }

        /* ========== 实战案例 ========== */
        /* 案例1:水平垂直居中 */
        .center-box {
            display: flex;
            justify-content: center;
            align-items: center;
            height: 300px;
            background: #ecf0f1;
            border-radius: 8px;
        }

        .center-content {
            background: #3498db;
            color: white;
            padding: 40px;
            border-radius: 8px;
            font-size: 1.2em;
        }

        /* 案例2:导航栏 */
        .navbar {
            display: flex;
            justify-content: space-between;
            align-items: center;
            background: #2c3e50;
            padding: 15px 30px;
            border-radius: 8px;
            color: white;
        }

        .nav-links {
            display: flex;
            gap: 30px;
            list-style: none;
        }

        /* 案例3:卡片网格 */
        .card-grid {
            display: flex;
            flex-wrap: wrap;
            gap: 20px;
        }

        .card {
            flex: 1 1 250px; /* 可以grow,可以shrink,基础250px */
            background: white;
            padding: 20px;
            border-radius: 8px;
            box-shadow: 0 2px 8px rgba(0,0,0,0.1);
        }

        /* 案例4:底部固定 */
        .page-layout {
            display: flex;
            flex-direction: column;
            min-height: 400px;
            background: #ecf0f1;
            border-radius: 8px;
        }

        .page-header {
            background: #3498db;
            color: white;
            padding: 20px;
        }

        .page-content {
            flex: 1; /* 占据所有剩余空间 */
            padding: 20px;
        }

        .page-footer {
            background: #2c3e50;
            color: white;
            padding: 20px;
            text-align: center;
        }
    </style>
</head>
<body>
    <!-- 1. 方向 -->
    <div class="section">
        <h2>1️⃣ flex-direction:主轴方向</h2>
        <h3>row(默认):水平从左到右 →</h3>
        <div class="flex-container direction-row">
            <div class="flex-item">1</div>
            <div class="flex-item">2</div>
            <div class="flex-item">3</div>
        </div>

        <h3>row-reverse:水平从右到左 ←</h3>
        <div class="flex-container direction-row-reverse">
            <div class="flex-item">1</div>
            <div class="flex-item">2</div>
            <div class="flex-item">3</div>
        </div>

        <h3>column:垂直从上到下 ↓</h3>
        <div class="flex-container direction-column">
            <div class="flex-item">1</div>
            <div class="flex-item">2</div>
            <div class="flex-item">3</div>
        </div>
    </div>

    <!-- 2. 主轴对齐 -->
    <div class="section">
        <h2>2️⃣ justify-content:主轴对齐(水平方向)</h2>
        <h3>flex-start(默认):左对齐</h3>
        <div class="flex-container justify-start">
            <div class="flex-item">1</div>
            <div class="flex-item">2</div>
            <div class="flex-item">3</div>
        </div>

        <h3>center:居中(最常用)</h3>
        <div class="flex-container justify-center">
            <div class="flex-item">1</div>
            <div class="flex-item">2</div>
            <div class="flex-item">3</div>
        </div>

        <h3>space-between:两端对齐,中间平均</h3>
        <div class="flex-container justify-between">
            <div class="flex-item">1</div>
            <div class="flex-item">2</div>
            <div class="flex-item">3</div>
        </div>

        <h3>space-evenly:完全平均分配</h3>
        <div class="flex-container justify-evenly">
            <div class="flex-item">1</div>
            <div class="flex-item">2</div>
            <div class="flex-item">3</div>
        </div>
    </div>

    <!-- 3. 交叉轴对齐 -->
    <div class="section">
        <h2>3️⃣ align-items:交叉轴对齐(垂直方向)</h2>
        <h3>stretch(默认):拉伸填满</h3>
        <div class="flex-container align-stretch" style="height:150px;">
            <div class="flex-item">1</div>
            <div class="flex-item">2</div>
            <div class="flex-item">3</div>
        </div>

        <h3>center:垂直居中(经典!)</h3>
        <div class="flex-container align-center" style="height:150px;">
            <div class="flex-item">1</div>
            <div class="flex-item">2</div>
            <div class="flex-item">3</div>
        </div>

        <h3>不同高度的元素对齐效果</h3>
        <div class="flex-container align-start" style="height:150px;">
            <div class="flex-item">高60px</div>
            <div class="flex-item">高100px</div>
            <div class="flex-item">高40px</div>
        </div>
    </div>

    <!-- 4. 换行 -->
    <div class="section">
        <h2>4️⃣ flex-wrap:换行控制</h2>
        <h3>nowrap(默认):不换行,可能溢出</h3>
        <div class="flex-container flex-nowrap">
            <div class="flex-item wrap-item">1</div>
            <div class="flex-item wrap-item">2</div>
            <div class="flex-item wrap-item">3</div>
            <div class="flex-item wrap-item">4</div>
            <div class="flex-item wrap-item">5</div>
        </div>

        <h3>wrap:允许换行</h3>
        <div class="flex-container flex-wrap">
            <div class="flex-item wrap-item">1</div>
            <div class="flex-item wrap-item">2</div>
            <div class="flex-item wrap-item">3</div>
            <div class="flex-item wrap-item">4</div>
            <div class="flex-item wrap-item">5</div>
        </div>
    </div>

    <!-- 5. 子项属性 -->
    <div class="section">
        <h2>5️⃣ 子项属性:flex-grow(放大比例)</h2>
        <p>所有元素 flex-grow: 1,第二个元素 flex-grow: 2(占2份)</p>
        <div class="flex-container flex-grow-demo">
            <div class="flex-item">1份</div>
            <div class="flex-item">2份</div>
            <div class="flex-item">1份</div>
            <div class="flex-item">1份</div>
        </div>

        <h3>flex-shrink(收缩比例)</h3>
        <p>容器宽度不足时,第二个元素不收缩(flex-shrink: 0),其他收缩</p>
        <div class="flex-container flex-shrink-demo" style="width:400px;">
            <div class="flex-item">会收缩</div>
            <div class="flex-item">不收缩</div>
            <div class="flex-item">会收缩</div>
        </div>

        <h3>align-self(单独对齐)</h3>
        <div class="flex-container align-self-demo">
            <div class="flex-item">居中</div>
            <div class="flex-item">顶部</div>
            <div class="flex-item">居中</div>
            <div class="flex-item">底部</div>
        </div>
    </div>

    <!-- 6. 实战案例 -->
    <div class="section">
        <h2>6️⃣ 实战案例</h2>
        
        <h3>案例1:完美居中(面试必考)</h3>
        <div class="center-box">
            <div class="center-content">水平垂直居中</div>
        </div>

        <h3>案例2:导航栏</h3>
        <nav class="navbar">
            <div class="logo">🚀 Logo</div>
            <ul class="nav-links">
                <li>首页</li>
                <li>产品</li>
                <li>关于</li>
                <li>联系</li>
            </ul>
            <button style="padding:8px 16px;border-radius:4px;border:none;cursor:pointer;">登录</button>
        </nav>

        <h3>案例3:自适应卡片网格</h3>
        <div class="card-grid">
            <div class="card">
                <h4>卡片1</h4>
                <p>flex: 1 1 250px 实现自适应</p>
            </div>
            <div class="card">
                <h4>卡片2</h4>
                <p>屏幕宽时并排,窄时自动换行</p>
            </div>
            <div class="card">
                <h4>卡片3</h4>
                <p>剩余空间平均分配</p>
            </div>
        </div>

        <h3>案例4:底部固定(Sticky Footer)</h3>
        <div class="page-layout">
            <header class="page-header">头部</header>
            <main class="page-content">内容区域(自动撑开)</main>
            <footer class="page-footer">底部固定</footer>
        </div>
    </div>
</body>
</html>

Flex核心记忆口诀

复制代码
父容器六大属性:
"方(flex-direction)向(justify-content)对(align-items)齐(align-content),换(flex-wrap)不(flex-flow)换行"

子元素三大属性:
"伸(flex-grow)缩(flex-shrink)基(flex-basis)础,自(align-self)己排序(order)"

最常用组合(背下来!):

css 复制代码
.container {
    display: flex;
    justify-content: center; /* 水平居中 */
    align-items: center;     /* 垂直居中 */
    gap: 20px;               /* 子元素间距 */
}

四、Grid布局:二维布局的"终极武器"

Grid(网格布局)是CSS最强大的布局系统,专门处理二维布局(同时控制行和列),是Flex的升级版。

1. Grid核心概念

复制代码
┌─────────────────────────────────────────┐
│  grid-container(网格容器)              │
│  ┌─────────┬─────────┬─────────┐       │
│  │  cell   │  cell   │  cell   │  ← row 1 │
│  │  (1,1)  │  (1,2)  │  (1,3)  │       │
│  ├─────────┼─────────┼─────────┤       │
│  │  cell   │  cell   │  cell   │  ← row 2 │
│  │  (2,1)  │  (2,2)  │  (2,3)  │       │
│  ├─────────┼─────────┼─────────┤       │
│  │  cell   │  cell   │  cell   │  ← row 3 │
│  │  (3,1)  │  (3,2)  │  (3,3)  │       │
│  └─────────┴─────────┴─────────┘       │
│     ↑        ↑        ↑                │
│   col 1    col 2    col 3              │
│                                        │
│  grid line(网格线):分隔行列的线        │
│  grid track(轨道):行或列               │
│  grid area(区域):多个单元格组成的矩形   │
└─────────────────────────────────────────┘

2. Grid实战代码

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Grid布局完全指南</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            background: #f5f6fa;
            padding: 20px;
            line-height: 1.6;
        }

        .section {
            background: white;
            margin-bottom: 30px;
            padding: 30px;
            border-radius: 12px;
            box-shadow: 0 2px 10px rgba(0,0,0,0.08);
        }

        h2 {
            color: #2c3e50;
            margin-bottom: 20px;
            border-bottom: 3px solid #9b59b6;
            padding-bottom: 10px;
        }

        h3 {
            color: #34495e;
            margin: 20px 0 10px;
            font-size: 1.1em;
        }

        .grid-container {
            display: grid;
            background: #ecf0f1;
            padding: 20px;
            border-radius: 8px;
            gap: 10px; /* 单元格间距 */
        }

        .grid-item {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            padding: 20px;
            border-radius: 8px;
            font-weight: bold;
            text-align: center;
            display: flex;
            align-items: center;
            justify-content: center;
        }

        /* ========== 1. 定义网格列 ========== */
        /* 固定宽度 */
        .grid-fixed {
            grid-template-columns: 100px 200px 100px;
        }

        /* 百分比 */
        .grid-percent {
            grid-template-columns: 25% 50% 25%;
        }

        /* fr单位:弹性比例(推荐!) */
        .grid-fr {
            grid-template-columns: 1fr 2fr 1fr; /* 1:2:1 */
        }

        /* repeat():重复模式 */
        .grid-repeat {
            grid-template-columns: repeat(3, 1fr); /* 3列等宽 */
        }

        /* auto-fit + minmax():响应式神器 */
        .grid-responsive {
            grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
        }

        /* ========== 2. 定义网格行 ========== */
        .grid-rows {
            grid-template-columns: repeat(3, 1fr);
            grid-template-rows: 100px 200px; /* 第一行100px,第二行200px */
        }

        /* ========== 3. 网格区域命名(高级用法) ========== */
        .grid-areas {
            grid-template-columns: 200px 1fr 200px;
            grid-template-rows: 80px 1fr 80px;
            grid-template-areas:
                "header header header"
                "sidebar main aside"
                "footer footer footer";
            min-height: 400px;
        }

        .header { grid-area: header; background: #e74c3c; }
        .sidebar { grid-area: sidebar; background: #3498db; }
        .main { grid-area: main; background: #2ecc71; }
        .aside { grid-area: aside; background: #f39c12; }
        .footer { grid-area: footer; background: #9b59b6; }

        /* ========== 4. 单元格合并 ========== */
        .grid-span {
            grid-template-columns: repeat(4, 1fr);
            grid-template-rows: repeat(3, 100px);
        }

        .item-span-2 {
            grid-column: span 2; /* 跨2列 */
        }

        .item-span-3 {
            grid-column: 1 / 4; /* 从第1条线到第4条线(跨3列) */
            grid-row: 2 / 4;    /* 从第2条线到第4条线(跨2行) */
            background: #e74c3c !important;
        }

        /* ========== 5. 对齐方式 ========== */
        .grid-align {
            grid-template-columns: repeat(3, 100px);
            grid-template-rows: repeat(2, 100px);
            height: 300px;
            
            justify-content: center; /* 水平方向对齐网格 */
            align-content: center;   /* 垂直方向对齐网格 */
            /* 或:place-content: center center; */
            
            /* 单元格内对齐 */
            /* justify-items: center; */ /* 单元格内容水平居中 */
            /* align-items: center; */   /* 单元格内容垂直居中 */
        }

        /* ========== 6. 实战案例 ========== */
        /* 案例1:照片墙 */
        .photo-wall {
            grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
            grid-auto-rows: 250px;
            gap: 15px;
        }

        .photo-wall .grid-item {
            padding: 0;
            overflow: hidden;
        }

        .photo-wall .grid-item:nth-child(3n) {
            grid-row: span 2; /* 每第3个图片跨2行,形成瀑布流效果 */
        }

        /* 案例2:仪表盘 */
        .dashboard {
            grid-template-columns: repeat(4, 1fr);
            grid-template-rows: repeat(3, 150px);
            gap: 20px;
        }

        .dashboard .grid-item {
            flex-direction: column;
        }

        .dash-large {
            grid-column: span 2;
            grid-row: span 2;
        }

        .dash-wide {
            grid-column: span 2;
        }

        /* 案例3:杂志布局 */
        .magazine {
            grid-template-columns: 2fr 1fr 1fr;
            grid-template-rows: auto auto auto;
            gap: 20px;
            max-width: 1000px;
            margin: 0 auto;
        }

        .mag-cover {
            grid-column: 1 / 2;
            grid-row: 1 / 3;
            min-height: 400px;
            background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 600"><rect fill="%23667eea" width="400" height="600"/><text fill="white" x="50%" y="50%" text-anchor="middle" font-size="24">封面大图</text></svg>') center/cover;
        }

        .mag-title {
            grid-column: 2 / 4;
            font-size: 2em;
            background: #2c3e50;
        }

        .mag-article {
            background: #ecf0f1;
            color: #333;
        }

        /* 案例4:日历 */
        .calendar {
            grid-template-columns: repeat(7, 1fr);
            gap: 5px;
            max-width: 600px;
            margin: 0 auto;
        }

        .day-header {
            background: #34495e;
            padding: 10px;
            text-align: center;
            color: white;
            font-weight: bold;
        }

        .day-cell {
            aspect-ratio: 1; /* 正方形 */
            background: white;
            border: 1px solid #ddd;
            display: flex;
            align-items: center;
            justify-content: center;
            min-height: 60px;
        }

        .day-cell.weekend {
            background: #ffeaa7;
        }

        .day-cell.today {
            background: #74b9ff;
            color: white;
            font-weight: bold;
        }
    </style>
</head>
<body>
    <!-- 1. 定义网格列 -->
    <div class="section">
        <h2>1️⃣ grid-template-columns:定义列</h2>
        
        <h3>固定像素:100px 200px 100px</h3>
        <div class="grid-container grid-fixed">
            <div class="grid-item">A</div>
            <div class="grid-item">B</div>
            <div class="grid-item">C</div>
        </div>

        <h3>百分比:25% 50% 25%</h3>
        <div class="grid-container grid-percent">
            <div class="grid-item">A</div>
            <div class="grid-item">B</div>
            <div class="grid-item">C</div>
        </div>

        <h3>fr单位(弹性比例):1fr 2fr 1fr</h3>
        <p>fr = fraction(分数),剩余空间按比例分配</p>
        <div class="grid-container grid-fr">
            <div class="grid-item">1fr</div>
            <div class="grid-item">2fr</div>
            <div class="grid-item">1fr</div>
        </div>

        <h3>repeat():重复模式 repeat(3, 1fr)</h3>
        <div class="grid-container grid-repeat">
            <div class="grid-item">1</div>
            <div class="grid-item">2</div>
            <div class="grid-item">3</div>
        </div>

        <h3>🚀 响应式神器:auto-fit + minmax()</h3>
        <p>自动适应容器宽度,每列最小200px,最大1fr</p>
        <div class="grid-container grid-responsive">
            <div class="grid-item">1</div>
            <div class="grid-item">2</div>
            <div class="grid-item">3</div>
            <div class="grid-item">4</div>
            <div class="grid-item">5</div>
            <div class="grid-item">6</div>
        </div>
    </div>

    <!-- 2. 定义行 -->
    <div class="section">
        <h2>2️⃣ grid-template-rows:定义行高</h2>
        <div class="grid-container grid-rows">
            <div class="grid-item">100px</div>
            <div class="grid-item">100px</div>
            <div class="grid-item">100px</div>
            <div class="grid-item">200px</div>
            <div class="grid-item">200px</div>
            <div class="grid-item">200px</div>
        </div>
    </div>

    <!-- 3. 网格区域命名 -->
    <div class="section">
        <h2>3️⃣ grid-template-areas:命名区域布局(高级)</h2>
        <p>用直观的"地图"方式定义布局,代码可读性极高</p>
        <div class="grid-container grid-areas">
            <div class="grid-item header">🎨 Header</div>
            <div class="grid-item sidebar">📑 Sidebar</div>
            <div class="grid-item main">📄 Main Content</div>
            <div class="grid-item aside">📌 Aside</div>
            <div class="grid-item footer">🔻 Footer</div>
        </div>
    </div>

    <!-- 4. 单元格合并 -->
    <div class="section">
        <h2>4️⃣ 单元格合并:span 和 线编号</h2>
        <div class="grid-container grid-span">
            <div class="grid-item">1</div>
            <div class="grid-item item-span-2">跨2列</div>
            <div class="grid-item">3</div>
            <div class="grid-item">4</div>
            <div class="grid-item item-span-3">跨3列+2行</div>
            <div class="grid-item">6</div>
            <div class="grid-item">7</div>
            <div class="grid-item">8</div>
            <div class="grid-item">9</div>
            <div class="grid-item">10</div>
            <div class="grid-item">11</div>
        </div>
        <p style="margin-top:10px;color:#666;">
            • grid-column: span 2 → 跨2列<br>
            • grid-column: 1 / 4 → 从第1条线到第4条线(跨3列)<br>
            • grid-row: 2 / 4 → 从第2条线到第4条线(跨2行)
        </p>
    </div>

    <!-- 5. 对齐 -->
    <div class="section">
        <h2>5️⃣ 对齐方式</h2>
        <div class="grid-container grid-align">
            <div class="grid-item">1</div>
            <div class="grid-item">2</div>
            <div class="grid-item">3</div>
            <div class="grid-item">4</div>
            <div class="grid-item">5</div>
            <div class="grid-item">6</div>
        </div>
        <p style="margin-top:10px;">
            justify-content: center(水平居中网格)<br>
            align-content: center(垂直居中网格)
        </p>
    </div>

    <!-- 6. 实战案例 -->
    <div class="section">
        <h2>6️⃣ 实战案例</h2>

        <h3>案例1:响应式照片墙(瀑布流效果)</h3>
        <div class="grid-container photo-wall">
            <div class="grid-item">📷 1</div>
            <div class="grid-item">📷 2</div>
            <div class="grid-item">📷 3(跨2行)</div>
            <div class="grid-item">📷 4</div>
            <div class="grid-item">📷 5</div>
            <div class="grid-item">📷 6</div>
            <div class="grid-item">📷 7</div>
            <div class="grid-item">📷 8</div>
        </div>

        <h3>案例2:数据仪表盘</h3>
        <div class="grid-container dashboard">
            <div class="grid-item dash-large">
                <div style="font-size:2em;">📊</div>
                <div>核心指标</div>
            </div>
            <div class="grid-item">
                <div style="font-size:1.5em;">💰</div>
                <div>销售额</div>
            </div>
            <div class="grid-item">
                <div style="font-size:1.5em;">👥</div>
                <div>用户数</div>
            </div>
            <div class="grid-item dash-wide">
                <div style="font-size:1.5em;">📈</div>
                <div>趋势图表</div>
            </div>
            <div class="grid-item">
                <div style="font-size:1.5em;">⚡</div>
                <div>性能</div>
            </div>
            <div class="grid-item">
                <div style="font-size:1.5em;">🎯</div>
                <div>目标</div>
            </div>
        </div>

        <h3>案例3:杂志布局</h3>
        <div class="grid-container magazine">
            <div class="grid-item mag-cover">封面</div>
            <div class="grid-item mag-title">杂志标题</div>
            <div class="grid-item mag-article">文章1</div>
            <div class="grid-item mag-article">文章2</div>
            <div class="grid-item mag-article">文章3</div>
        </div>

        <h3>案例4:日历</h3>
        <div class="grid-container calendar">
            <div class="day-header">日</div>
            <div class="day-header">一</div>
            <div class="day-header">二</div>
            <div class="day-header">三</div>
            <div class="day-header">四</div>
            <div class="day-header">五</div>
            <div class="day-header">六</div>
            
            <div class="day-cell weekend">29</div>
            <div class="day-cell">30</div>
            <div class="day-cell">31</div>
            <div class="day-cell">1</div>
            <div class="day-cell">2</div>
            <div class="day-cell">3</div>
            <div class="day-cell weekend">4</div>
            <div class="day-cell weekend">5</div>
            <div class="day-cell">6</div>
            <div class="day-cell">7</div>
            <div class="day-cell today">8</div>
            <div class="day-cell">9</div>
            <div class="day-cell">10</div>
            <div class="day-cell weekend">11</div>
        </div>
    </div>
</body>
</html>

Grid vs Flex 选择指南

场景 推荐方案 原因
单行/单列布局 Flex 一维控制更简单
多行多列复杂布局 Grid 二维控制更强大
组件内部对齐(如按钮内文字居中) Flex 单行居中神器
整体页面布局(header/sidebar/main/footer) Grid 区域划分清晰
响应式卡片网格 Grid auto-fit + minmax() 无敌
未知数量元素均匀分布 Flex flex-wrap + flex: 1 更灵活

黄金法则

  • Grid管大局(页面整体结构)
  • Flex管细节(组件内部对齐)
  • 两者可以嵌套使用(Grid容器里放Flex容器)

五、总结:给实习生的学习路线图

学习优先级

复制代码
第1周:基础选择器 + 盒模型
        ↓
第2周:Flex布局(重点!80%的日常布局)
        ↓
第3周:Grid布局(进阶,复杂页面结构)
        ↓
第4周:实战项目(用Grid做页面框架,Flex做组件)

面试必考代码(背下来)

1. 水平垂直居中(Flex版)

css 复制代码
.center {
    display: flex;
    justify-content: center;
    align-items: center;
}

2. 水平垂直居中(Grid版)

css 复制代码
.center {
    display: grid;
    place-items: center; /* 等于 justify-items + align-items */
}

3. 三栏布局(Grid版)

css 复制代码
.layout {
    display: grid;
    grid-template-columns: 200px 1fr 200px; /* 固定-自适应-固定 */
}

4. 响应式卡片网格

css 复制代码
.cards {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
    gap: 20px;
}

推荐练习项目

  1. 用Flex做:导航栏、卡片居中、底部固定布局
  2. 用Grid做:个人主页、仪表盘、照片墙、日历
  3. 混合使用:电商首页(Grid布局框架 + Flex组件内部)

记住:多写多练,看十遍不如写一遍!

相关推荐
专吃海绵宝宝菠萝屋的派大星2 小时前
使用Dify对接自己开发的mcp
java·服务器·前端
爱分享的阿Q2 小时前
Rust加WebAssembly前端性能革命实践指南
前端·rust·wasm
蓝黑20203 小时前
Vue的 value=“1“ 和 :value=“1“ 有什么区别
前端·javascript·vue
小李子呢02113 小时前
前端八股6---v-model双向绑定
前端·javascript·算法
He少年3 小时前
【基础知识、Skill、Rules和MCP案例介绍】
java·前端·python
史迪仔01123 小时前
[QML] QML IMage图像处理
开发语言·前端·javascript·c++·qt
AwesomeCPA3 小时前
Miaoduo MCP 使用指南(VDI内网环境)
前端·ui·ai编程
前端大波3 小时前
前端面试通关包(2026版,完整版)
前端·面试·职场和发展
qq_433502183 小时前
Codex cli 飞书文档创建进阶实用命令 + Skill 创建&使用 小白完整教程
java·前端·飞书