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组件内部)

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

相关推荐
weixin_3823952320 小时前
为小工厂量身打造:本地部署的物料管理系统带缺料计算
前端·制造
__zRainy__20 小时前
解决pnpm v10+不自动构建
前端·pnpm·工程化
猫猫不是喵喵.20 小时前
Vue3 Props 属性
前端·javascript·vue.js
醉城夜风~21 小时前
CSS元素显示模式(display)
前端·css
AI大模型-小华1 天前
Codex 三方充值快速入门指南
java·前端·数据库·chatgpt·ai编程·codex·chatgpt pro
做前端的娜娜子1 天前
同一链接实现 PC Web 与移动 H5 自适应
前端·掘金·金石计划
小帅不太帅1 天前
架构没变、规模没变,DeepSeek V4 Flash 正式版凭什么暴涨 47 分?
前端·aigc·deepseek
jarvisuni1 天前
DeepSeekFlash前端依旧拉垮,而且变慢了很多!
前端·javascript·算法
卷福同学1 天前
AI编程出海第二步:验证关键词能否做站
前端·人工智能·后端