第2天:CSS 基础
学习时间:约 2 小时
目录
- [CSS 是什么](#CSS 是什么)
- [三种写 CSS 的方式](#三种写 CSS 的方式)
- 选择器
- 颜色与文字
- 盒模型(重中之重)
- 背景与边框
- [Flexbox 布局入门](#Flexbox 布局入门)
- [DevTools 调试 CSS](#DevTools 调试 CSS)
- 常见陷阱
1. CSS 是什么
CSS(Cascading Style Sheets)就是给 HTML "化妆"。
HTML 决定了页面上有什么(标题、图片、按钮),CSS 决定这些东西长什么样(什么颜色、多大、放在哪)。
html
<!-- HTML 说:"这是一个商品标题" -->
<h2>iPhone 16 Pro Max</h2>
<!-- 加上 CSS 后: -->
<style>
h2 {
color: #333;
font-size: 20px;
margin-bottom: 8px;
}
</style>
核心概念:层叠
CSS 的 C 代表 Cascading(层叠),意思是多个样式规则可以叠加到同一个元素上。如果有冲突,后面的覆盖前面的 ,更具体的覆盖更通用的。
优先级:内联样式 > ID 选择器 > class 选择器 > 标签选择器
2. 三种写 CSS 的方式
方式一:内联样式(写在标签的 style 属性里)
不推荐大量使用,但改一两个地方很方便:
html
<button style="background-color: #ff4400; color: white; border: none; padding: 10px 20px; border-radius: 4px;">
立即购买
</button>
方式二:内部样式(写在 HTML 的 <style> 标签里)
适合单个页面的样式:
html
<head>
<style>
.product-title {
font-size: 18px;
font-weight: bold;
color: #333;
}
.product-price {
color: #ff4400;
font-size: 24px;
}
</style>
</head>
<body>
<h2 class="product-title">iPhone 16 Pro Max</h2>
<p class="product-price">¥9,999</p>
</body>
</html>
方式三:外部样式表(写在单独的 .css 文件里)
正式项目的做法,和 HTML 分离:
html
<head>
<link rel="stylesheet" href="css/style.css" />
</head>
📁 project/
├── index.html
└── css/
└── style.css
3. 选择器
选择器就是选中 HTML 元素来施加样式的规则。
3.1 基础选择器
| 选择器 | 写法 | 选中什么 |
|---|---|---|
| 标签选择器 | div { } |
所有 <div> |
| class 选择器 | .card { } |
所有 class="card" 的元素 |
| ID 选择器 | #header { } |
id="header" 的那个元素 |
| 通配选择器 | * { } |
所有元素 |
css
/* 所有 div 加红色边框 */
div { border: 1px solid red; }
/* 所有 class="product-card" 的元素 */
.product-card { border-radius: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); }
/* id="main-nav" 的那个元素(唯一) */
#main-nav { background-color: #222; }
3.2 组合选择器
| 选择器 | 写法 | 选中什么 |
|---|---|---|
| 后代 | div span { } |
<div> 里面所有的 <span>(不管嵌套多深) |
| 子代 | div > p { } |
<div> 的直接子元素 <p>(只限一层) |
| 相邻 | h2 + p { } |
<h2> 后面紧挨着的 <p> |
| 交集 | div.card { } |
同时是 <div> 且 class="card" |
| 并集 | h1, h2, h3 { } |
所有 <h1>、<h2>、<h3> |
css
/* 商品列表里的所有价格 */
.product-list .price { color: #ff4400; font-weight: bold; }
/* 导航栏的直接子链接------不选中下拉菜单里的 */
.nav > a { color: white; }
/* 多个元素共享样式 */
.product-name, .product-price, .product-desc { margin-bottom: 4px; }
3.3 伪类选择器
伪类描述元素的特殊状态,比如鼠标悬停、第一个子元素等。
| 伪类 | 用途 | 示例 |
|---|---|---|
:hover |
鼠标悬停时 | .btn:hover { background: blue; } |
:first-child |
第一个子元素 | li:first-child { } |
:last-child |
最后一个子元素 | li:last-child { border: none; } |
:nth-child(n) |
第 n 个子元素 | li:nth-child(2) { } |
:disabled |
禁用状态的输入框 | input:disabled { background: gray; } |
css
/* 鼠标放上按钮时变暗 */
.buy-btn:hover { opacity: 0.8; }
/* 购物车最后一项没有下边框 */
.cart-item:last-child { border-bottom: none; }
/* 表格偶数行灰色背景 */
tr:nth-child(even) { background-color: #f8f8f8; }
3.4 优先级速记
当一个元素被多个选择器命中时,到底听谁的?
!important > 内联样式 > ID 选择器 > class 选择器 > 标签选择器
css
/* 标签选择器------权重最低 */
div { color: black; }
/* class 选择器------覆盖上面的 */
.text { color: blue; }
/* ID 选择器------覆盖上面的 */
#title { color: red; }
/* 内联样式------覆盖上面的 */
/* <div style="color: green;"> */
/* !important------核武器,尽量别用 */
div { color: purple !important; }
4. 颜色与文字
4.1 颜色写法
| 写法 | 示例 | 说明 |
|---|---|---|
| 颜色名 | red、white、black、blue |
直观但选择少 |
| 十六进制 | #ff4400、#333、#fff |
最常用 |
| rgb | rgb(255, 68, 0) |
红绿蓝数值 |
| rgba | rgba(255, 68, 0, 0.5) |
带透明度,a=0~1 |
css
.product-price { color: #ff4400; }
.discount-tag { background: rgba(255, 68, 0, 0.1); }
4.2 文字样式
css
.product-card {
font-size: 14px; /* 字号 ------ 最常用 */
font-weight: bold; /* 字重:normal(400) / bold(700) / 也可以直接写数字 */
font-family: "PingFang SC", "Microsoft YaHei", sans-serif; /* 字体 */
line-height: 1.6; /* 行高 ------ 控制文字行间距 */
text-align: center; /* 对齐:left / center / right */
color: #333; /* 文字颜色 */
text-decoration: none; /* 下划线:none(去下划线) / underline */
}
css
/* 电商常用文字样式 */
.product-name {
font-size: 14px;
color: #333;
line-height: 1.4;
}
.product-price {
font-size: 20px;
font-weight: bold;
color: #ff4400;
}
.original-price {
font-size: 12px;
color: #999;
text-decoration: line-through; /* 删除线 */
}
.shop-name {
font-size: 12px;
color: #666;
}
5. 盒模型(重中之重)
盒模型是 CSS 里最重要的概念,没有之一。不理解盒模型,写出来的页面布局就是乱的。
5.1 每个 HTML 元素都是一个"盒子"
css
盒模型从内到外:
┌─────────────────────────────────────┐
│ margin(外边距) │
│ ┌───────────────────────────────┐ │
│ │ border(边框) │ │
│ │ ┌─────────────────────────┐ │ │
│ │ │ padding(内边距) │ │ │
│ │ │ ┌───────────────────┐ │ │ │
│ │ │ │ 内容区域 │ │ │ │
│ │ │ │ (width / height) │ │ │ │
│ │ │ └───────────────────┘ │ │ │
│ │ │ │ │ │
│ │ └─────────────────────────┘ │ │
│ │ │ │
│ └───────────────────────────────┘ │
│ │
└─────────────────────────────────────┘
5.2 四个组成部分
css
.product-card {
/* 内容区域 ------ 放文字、图片 */
width: 280px;
height: 360px;
/* padding ------ 内容 与 边框 之间的距离,≈ 手机屏幕的"黑边" */
padding: 16px;
/* 简写:上 右 下 左 */
padding: 12px 16px 12px 16px;
/* 简写:上下 左右 */
padding: 12px 16px;
/* border ------ 边框 */
border: 1px solid #eee;
/* 细看:border: 粗细 样式 颜色 */
border: 2px dashed #ddd; /* 虚线边框 */
border-radius: 8px; /* 圆角 ★★★ 非常常用 */
/* margin ------ 盒子 与 其他盒子 之间的距离 */
margin-bottom: 16px;
margin: 0 auto; /* 水平居中 */
}
5.3 电商示例
css
/* 商品卡片 */
.product-card {
width: 240px;
padding: 12px;
border: 1px solid #eee;
border-radius: 8px;
margin-bottom: 16px;
}
/* 购物车商品项 */
.cart-item {
display: flex;
padding: 16px 0;
border-bottom: 1px solid #f0f0f0;
margin-bottom: 0;
}
/* 订单卡片 */
.order-card {
padding: 20px;
border: 1px solid #e8e8e8;
border-radius: 8px;
margin-bottom: 12px;
background: #fff;
}
5.4 魔鬼细节:盒子大小计算
关键问题 :width: 200px 是指内容区域 200px,还是整个盒子(含 padding + border)200px?
默认(box-sizing: content-box):
整个盒子宽度 = width + padding-left + padding-right + border-left + border-right
这意味着如果设置了 width: 200px; padding: 20px; border: 1px,整个盒子实际宽度是 242px。
实践中几乎永远用 border-box:
css
/* ★★★ 几乎所有项目都会在第一行写这个 */
* {
box-sizing: border-box;
}
border-box 的意思是:width: 200px 表示整个盒子(含 padding + border)一共 200px,内容区域自动压缩。符合直觉。
css
/* 用 border-box 后: */
.card {
width: 200px;
padding: 20px;
border: 1px solid #eee;
/* 整个盒子 = 200px,内容自动缩成 158px */
}
6. 背景与边框
6.1 背景
css
.banner {
background-color: #f5f5f5; /* 背景颜色 */
background-image: url('images/banner.jpg'); /* 背景图片 */
background-size: cover; /* 覆盖整个区域 */
background-position: center; /* 居中 */
background-repeat: no-repeat; /* 不重复 */
/* 简写 */
background: #f5f5f5 url('banner.jpg') no-repeat center/cover;
}
6.2 边框
css
/* 基础边框 */
.product-card { border: 1px solid #eee; }
/* 只加底部边框(电商列表项常用) */
.cart-item { border-bottom: 1px solid #f0f0f0; }
/* 圆角 ★★★ */
.avatar { border-radius: 50%; } /* 圆形 */
.button { border-radius: 4px; } /* 小圆角 */
.card { border-radius: 12px; } /* 大圆角 */
/* 阴影 ★★★ ------ 让元素"浮起来" */
.card {
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
/* 顺序:水平偏移 垂直偏移 模糊半径 颜色 */
}
7. Flexbox 布局入门
Flexbox 是目前最主流的 CSS 布局方式,你的项目里大量使用了(el-row / el-col 底层就是 Flexbox)。
7.1 核心概念
css
/* 容器上写 display: flex,子元素自动变成"弹性项"沿水平排列 */
.container {
display: flex; /* 开启 Flexbox */
}
开启前(块级元素默认上下排列):
┌──────┐
│ A │
├──────┤
│ B │
├──────┤
│ C │
└──────┘
开启后(变成左右排列):
┌──────┐┌──────┐┌──────┐
│ A ││ B ││ C │
└──────┘└──────┘└──────┘
7.2 容器属性
css
.nav-bar {
display: flex;
/* 主轴方向:row(默认,水平)| column(垂直) */
flex-direction: row;
/* 水平对齐 ★★★ */
justify-content: center; /* 居中 */
justify-content: space-between; /* 两端对齐(导航栏最常用) */
justify-content: flex-start; /* 左对齐(默认) */
justify-content: flex-end; /* 右对齐 */
/* 垂直对齐 ★★★ */
align-items: center; /* 垂直居中 */
align-items: stretch; /* 拉伸到一样高(默认) */
align-items: flex-start; /* 顶部对齐 */
/* 换行 */
flex-wrap: wrap; /* 放不下了自动换行 */
}
7.3 电商布局示例
css
/* 导航栏:Logo 在左,菜单在右 */
.nav-bar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 24px;
height: 60px;
background: #fff;
box-shadow: 0 1px 4px rgba(0,0,0,0.08);
}
/* 商品列表:一行四个,自动换行 */
.product-grid {
display: flex;
flex-wrap: wrap;
gap: 16px; /* ★★★ 子元素间距,不用 margin */
}
.product-grid .product-card {
width: calc(25% - 12px); /* 一行四个 */
}
/* 购物车项:图片在左,信息在右,删除按钮在右 */
.cart-item {
display: flex;
align-items: center;
padding: 16px 0;
}
.cart-item .item-info {
flex: 1; /* ★★★ 占据剩余所有空间 */
margin-left: 12px;
}
.cart-item .item-price {
width: 100px;
text-align: right;
}
/* 商品详情:标签垂直居中排列 */
.product-tags {
display: flex;
align-items: center;
gap: 8px;
}
.product-tags .tag {
padding: 2px 8px;
background: #fff0e6;
color: #ff4400;
border-radius: 4px;
font-size: 12px;
}
7.4 子元素属性
css
/* ★ flex: 1 ------ 占据剩余空间,极其常用 */
.sidebar { width: 200px; }
.main-content { flex: 1; } /* 填满右侧所有剩余空间 */
/* 其他 */
.item { flex-shrink: 0; } /* 不让它缩小 */
.item { order: -1; } /* 排到最前面 */
8. DevTools 调试 CSS
8.1 查看样式
打开 DevTools(F12)→ Elements 面板:
- 右侧 Styles 子面板:显示这个元素的所有样式(从哪来的,被谁覆盖了)
- 打勾/取消勾选样式前面的复选框 → 即时看到效果
- 双击属性值 → 修改 → 实时生效
8.2 查看盒模型
在 Elements 面板右下角找到 Box Model 区域:
┌─────────────────────────────────────┐
│ margin: 16px │
│ ┌───────────────────────────────┐ │
│ │ border: 1px │ │
│ │ ┌─────────────────────────┐ │ │
│ │ │ padding: 12px │ │ │
│ │ │ ┌───────────────────┐ │ │ │
│ │ │ │ 240 x 320 │ │ │ │
│ │ │ └───────────────────┘ │ │ │
│ │ └─────────────────────────┘ │ │
│ └───────────────────────────────┘ │
└─────────────────────────────────────┘
你可以直接在这个图上点击数字修改 margin / padding / border。
8.3 实用技巧
1. 选中元素 → 看右侧 Styles 面板 → 看是哪个属性导致的问题
2. 勾选/取消样式复选框 → 快速排查哪个样式生效了
3. 点击元素 → 看 Computed 面板 → 看最终计算值
4. 盒模型图 → 直接点数字改 padding/margin
9. 常见陷阱
陷阱 1:忘了写 box-sizing: border-box
css
/* ❌ 默认 content-box,width 不算 padding */
.card { width: 200px; padding: 20px; } /* 实际宽 240px */
/* ✅ 几乎所有项目都会在第一行加这个 */
*, *::before, *::after { box-sizing: border-box; }
陷阱 2:margin 重叠
两个盒子上下排列,上面的 margin-bottom: 20px,下面的 margin-top: 30px,它们之间的间距是 30px(取较大值),不是 50px。
css
/* 解决:只用 margin-bottom 不用 margin-top */
.card { margin-bottom: 16px; }
陷阱 3:不理解块级 vs 行内
css
/* span 是行内元素,width 和 height 不生效! */
span { width: 200px; height: 100px; } /* ❌ 没用 */
/* 改成行内块级或块级 */
span { display: inline-block; width: 200px; } /* ✅ */
span { display: block; width: 200px; } /* ✅ */
陷阱 4:选择器写得太长
css
/* ❌ 又长又脆弱 */
div.container ul li a.link { color: blue; }
/* ✅ 直接用 class */
.nav-link { color: blue; }
陷阱 5:用 px 写死一切
css
/* ❌ 固定宽度 */
.sidebar { width: 200px; }
/* ✅ 灵活方案 */
.sidebar { width: 25%; }
/* 或 */
.container { display: flex; }
.sidebar { flex: 0 0 200px; }
.content { flex: 1; }
附:CSS 属性速查
css
/* 文字 */
font-size: 14px;
font-weight: bold / 700;
font-family: "PingFang SC", sans-serif;
color: #333;
text-align: center / left / right;
text-decoration: none / underline / line-through;
line-height: 1.6;
/* 盒模型 */
width / height: 200px / 50% / auto;
padding: 12px 16px; /* 上下 左右 */
margin: 16px 0; /* 上下 左右 */
border: 1px solid #eee;
border-radius: 8px; /* 圆角 */
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
/* 背景 */
background-color: #fff;
background: #f5f5f5 url('bg.jpg') center/cover no-repeat;
/* 布局 */
display: flex / block / inline / inline-block / none;
/* Flexbox ★★★ */
display: flex;
justify-content: center / space-between / flex-start / flex-end;
align-items: center / stretch / flex-start / flex-end;
flex-wrap: wrap;
gap: 16px;
flex: 1; /* 占满剩余空间 */