我来为实习生准备一份生动细致的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;
}
推荐练习项目
- 用Flex做:导航栏、卡片居中、底部固定布局
- 用Grid做:个人主页、仪表盘、照片墙、日历
- 混合使用:电商首页(Grid布局框架 + Flex组件内部)
记住:多写多练,看十遍不如写一遍!