一、CSS基本概念
CSS (Cascading Style Sheets,层叠样式表) 是一种样式表语言,用于描述HTML或XML文档的呈现方式。它由万维网联盟(W3C)在1996年首次提出,现已成为Web开发的三大核心技术之一(HTML、CSS和JavaScript)。
核心特性
1. 层叠性
层叠是CSS的核心概念,指多个样式规则可以应用于同一个元素,按照一定的优先级规则进行"层叠"。
具体机制:
- 样式表可以来自浏览器默认样式(用户代理样式表)
- 用户设置的样式
- 开发者定义的样式(内联、内部或外部样式表)
当多个规则作用于同一元素时,CSS根据以下因素决定最终应用的样式:
- 来源:开发者样式通常覆盖浏览器默认样式
- 特异性(选择器优先级)
- 顺序:相同特异性的规则,后声明的覆盖先声明的
- !important标记:可以提升规则优先级
示例:
p { color: blue; } /* 常规规则 */
#intro { color: black; } /* ID选择器优先级更高 */
p { color: red !important; } /* 使用!important提升优先级 */
2. 继承性
某些CSS属性会从父元素传递到子元素,这称为继承。
常见可继承属性:
- 文本相关:color, font-family, font-size, font-weight, text-align
- 可见性:visibility
- 列表属性:list-style
常见不可继承属性:
- 盒模型属性:width, height, padding, margin, border
- 定位属性:position, top, left
- 背景属性:background, background-color
控制继承:
/* 强制继承 */
.child {
color: inherit; /* 从父元素继承颜色 */
}
/* 阻止继承 */
.child {
color: initial; /* 使用浏览器默认值 */
}
3. 优先级
CSS规则的优先级(特异性)决定了当多个规则冲突时,哪个规则会被应用。
优先级计算:
- 内联样式:1000分
- ID选择器:100分
- 类选择器、属性选择器、伪类:10分
- 元素选择器、伪元素:1分
优先级示例:
-
h1
= 1分(一个元素选择器) -
h1.title
= 11分(一个元素选择器 + 一个类选择器) -
#header h1
= 101分(一个ID选择器 + 一个元素选择器) -
style="color:red"
= 1000分(内联样式) -
h1 { color: red !important; }
= 最高优先级
二、CSS语法结构
CSS使用简单易懂的语法结构,通过规则将样式应用到HTML元素。
基本语法
CSS规则由两个主要部分组成:
- 选择器(Selector):指定样式规则适用的HTML元素
- 声明块(Declaration Block):包含一组由属性和值组成的声明
选择器 {
属性1: 值1;
属性2: 值2;
/* 注释可以这样写 */
}
语法细节
1. 选择器
选择器可以是单个选择器或组合选择器。
/* 单个选择器 */
h1 { color: blue; }
/* 组选择器 - 同时选择多个元素 */
h1, h2, h3 { font-family: Arial; }
/* 组合选择器 - 基于元素关系选择 */
nav > ul { margin: 0; }
2. 声明
每个声明由属性名称和值组成,中间使用冒号分隔,末尾使用分号结束。
p {
color: #333; /* 颜色属性 */
font-size: 16px; /* 字体大小属性 */
line-height: 1.5; /* 行高属性 */
}
3. 注释
CSS注释使用/* */
格式,可以跨越多行。
/* 这是一个单行注释 */
/*
这是一个
多行注释
*/
4. 值的类型
CSS属性值可以有多种类型:
-
关键字:
auto
,none
,inherit
-
数字:
1
,2.5
-
长度:
10px
,2em
,50%
-
颜色:
red
,#FF0000
,rgba(255, 0, 0, 0.5)
-
URL:
url('image.jpg')
-
函数:
calc(100% - 20px)
,rgb(255, 0, 0)
-
多值:
10px 20px 30px
(用空格分隔)
5. 简写属性
许多CSS属性可以使用简写形式,将多个相关属性合并为一个。
/* 单独属性 */
margin-top: 10px;
margin-right: 20px;
margin-bottom: 10px;
margin-left: 20px;
/* 简写形式 */
margin: 10px 20px; /* 上下=10px, 左右=20px */
三、CSS引入方式
CSS可以通过多种方式应用到HTML文档,每种方式都有其特定的用途和优缺点。
1. 内联样式
内联样式直接应用于HTML元素的style
属性中。
语法:
<p style="color: blue; font-size: 16px; margin: 10px;">这是一段带有内联样式的文本。</p>
优点:
- 优先级最高(覆盖其他CSS规则)
- 样式直接与元素关联,方便查看
- 适用于需要动态生成样式的情况
缺点:
- 样式与内容混合,违背CSS的分离原则
- 难以维护,尤其是大型网站
- 无法利用缓存复用样式
- 无法使用伪类、伪元素等CSS特性
使用场景:
- 需要覆盖所有其他样式规则
- 通过JavaScript动态生成的样式
- 电子邮件HTML模板(有限的CSS支持)
- 快速原型或测试
2. 内部样式表
内部样式表通过在HTML文档头部的<style>
标签中定义CSS规则。
语法:
<!DOCTYPE html>
<html>
<head>
<style>
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 20px;
}
h1 {
color: navy;
border-bottom: 1px solid #ddd;
}
p {
line-height: 1.6;
}
</style>
</head>
<body>
<h1>内部样式表示例</h1>
<p>这个页面使用内部样式表定义样式。</p>
</body>
</html>
优点:
- 样式与HTML在同一文件,便于单文件分发
- 不需要额外的HTTP请求
- 可以使用选择器、伪类等所有CSS功能
缺点:
- 样式不能在多个页面间共享
- 增加HTML文件大小
- 样式和内容未完全分离
使用场景:
- 单页面应用或内容
- 样式仅适用于特定页面
- 简单的演示或测试
3. 外部样式表
外部样式表是将CSS代码保存在独立的.css文件中,然后通过<link>
标签或@import
规则引入HTML文档。
使用<link>
标签引入:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<h1>外部样式表示例</h1>
<p>这个页面使用外部样式表定义样式。</p>
</body>
</html>
styles.css文件内容:
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 20px;
}
h1 {
color: navy;
border-bottom: 1px solid #ddd;
}
p {
line-height: 1.6;
}
优点:
- 完全分离内容和样式
- 样式可以在多个页面间共享
- 浏览器可以缓存CSS文件,提高加载速度
- 便于维护,可由专门的CSS开发者管理
- 文件体积较小,加载更快
缺点:
- 需要额外的HTTP请求(可通过HTTP/2多路复用减轻)
- 引入额外的文件依赖
使用场景:
- 大多数生产网站和应用
- 多页面网站
- 需要良好维护性的项目
4. @import方式
@import
规则允许从一个CSS文件导入其他CSS文件的样式规则。
在HTML中使用:
<style>
@import url("typography.css");
@import url("layout.css");
/* 本地样式可以在这里定义 */
body {
background-color: #f5f5f5;
}
</style>
在CSS文件中使用:
/* main.css */
@import url("reset.css");
@import url("colors.css");
@import url("typography.css");
/* 主样式表中的规则 */
.container {
max-width: 1200px;
margin: 0 auto;
}
优点:
- 允许模块化CSS文件
- 便于组织大型项目的样式
- 可以在CSS文件中使用,无需修改HTML
缺点:
- 可能导致页面渲染延迟(串行加载)
- 增加HTTP请求数量
- 在某些情况下性能不如
<link>
标签
使用场景:
- 模块化CSS架构
- 主题切换功能
- 有条件地加载特定样式
比较不同引入方式的性能和应用场景
引入方式 | 性能 | 维护性 | 缓存 | 最佳应用场景 |
---|---|---|---|---|
内联样式 | 无额外请求,但增加HTML大小 | 差 | 不可缓存 | 关键渲染路径优化、电子邮件、小型组件 |
内部样式表 | 无额外请求,但增加HTML大小 | 中等 | 随HTML缓存 | 单页面、独立应用、快速原型 |
外部样式表(link) | 额外HTTP请求,但可并行加载 | 良好 | 单独缓存 | 大多数生产网站、多页面应用 |
@import | 串行加载,通常性能较差 | 良好 | 单独缓存 | CSS模块化、主题系统、条件加载 |
四、选择器系统
CSS选择器是样式表的基础,用于定位并选择需要应用样式的HTML元素。CSS提供了一套丰富的选择器系统,可以基于元素类型、属性、状态和位置等多种条件进行精确选择。
基础选择器
1. 元素选择器
根据标签名称选择所有匹配的HTML元素。
/* 选择所有段落元素 */
p {
line-height: 1.6;
margin-bottom: 1em;
}
/* 选择所有一级标题 */
h1 {
font-size: 2em;
font-weight: bold;
}
使用场景:
- 定义元素的基本样式
- 实现CSS重置或标准化
- 建立网站的整体排版基础
2. 类选择器
选择具有特定class属性的元素。类选择器以点(.)开头,后跟类名。
/* 选择所有带有"primary"类的元素 */
.primary {
color: blue;
font-weight: bold;
}
/* 选择所有带有"btn"类的元素 */
.btn {
display: inline-block;
padding: 8px 16px;
border-radius: 4px;
}
/* 选择同时具有多个类的元素 */
.btn.btn-primary {
background-color: blue;
color: white;
}
使用场景:
- 定义可复用的样式组件
- 创建变体样式(如按钮的不同状态)
- 实现布局系统(如网格系统)
3. ID选择器
选择具有特定id属性的元素。ID选择器以井号(#)开头,后跟ID名。每个ID在页面中应当唯一。
/* 选择ID为"header"的元素 */
#header {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 100;
}
/* 选择ID为"main-content"的元素 */
#main-content {
padding: 20px;
margin-top: 60px;
}
使用场景:
- 选择页面中唯一的元素
- 定义特定区域的布局
- JavaScript交互的钩子(虽然现代实践更推荐使用类)
4. 通用选择器
选择所有元素。通用选择器使用星号(*)表示。
/* 选择文档中的所有元素 */
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
/* 选择#container内的所有元素 */
#container * {
transition: all 0.3s ease;
}
使用场景:
- CSS重置或初始化
- 应用全局盒模型
- 调试(如添加边框或背景色)
注意:通用选择器应谨慎使用,可能影响性能,尤其是在大型文档中。
组合选择器
组合选择器根据元素之间的关系选择元素。
1. 后代选择器(空格)
选择指定元素的所有后代元素,不论层级深度。
/* 选择nav元素内的所有li元素 */
nav li {
display: inline-block;
margin-right: 10px;
}
/* 选择article元素内的所有段落 */
article p {
text-indent: 1em;
line-height: 1.8;
}
使用场景:
- 定义特定容器内元素的样式
- 创建上下文相关的样式规则
2. 直接后代选择器(>)
仅选择指定元素的直接子元素。
/* 选择nav的直接子元素ul */
nav > ul {
list-style: none;
display: flex;
}
/* 选择section直接子元素中的段落 */
section > p {
font-size: 1.1em;
margin-bottom: 1.5em;
}
使用场景:
- 避免样式泄漏到更深层级
- 精确控制元素层级关系的样式
3. 相邻兄弟选择器(+)
选择紧接在指定元素后的同级元素。
/* 选择紧接在h2后面的段落 */
h2 + p {
font-size: 1.2em;
font-weight: bold;
}
/* 选择紧接在label后面的输入框 */
label + input {
margin-left: 10px;
}
使用场景:
- 设置元素之间的间距
- 定义标题后内容的特殊样式
- 表单元素的布局
4. 通用兄弟选择器(~)
选择指定元素后的所有同级元素。
/* 选择h1后的所有段落 */
h1 ~ p {
color: #666;
}
/* 选择checkbox后的所有相关元素 */
input[type="checkbox"] ~ label {
color: gray;
}
input[type="checkbox"]:checked ~ label {
color: black;
font-weight: bold;
}
使用场景:
- 创建基于表单状态的界面反馈
- 实现无JS的交互效果
- 根据前面元素的存在控制后续元素样式
属性选择器
属性选择器基于元素的属性及其值来选择元素。
1. 基本属性选择器
选择具有指定属性的元素,不论属性值是什么。
/* 选择所有带有title属性的元素 */
[title] {
cursor: help;
}
/* 选择所有带有data-role属性的元素 */
[data-role] {
padding: 10px;
}
2. 精确匹配属性选择器
选择带有指定属性且属性值完全匹配的元素。
/* 选择type属性为"text"的输入框 */
input[type="text"] {
border: 1px solid #ccc;
padding: 5px 10px;
}
/* 选择rel属性为"external"的链接 */
a[rel="external"] {
color: orange;
}
3. 部分匹配属性选择器
-
开头匹配
[attr^="value"]
:属性值以指定值开头 -
结尾匹配
[attr$="value"]
:属性值以指定值结尾 -
包含匹配
[attr*="value"]
:属性值包含指定值 -
空格分隔匹配
[attr~="value"]
:属性值包含指定词(以空格分隔) -
连字符匹配
[attr|="value"]
:属性值等于指定值或以指定值后,接连字符开头
/* 选择所有以"https"开头的链接 */
a[href^="https"] {
color: green;
}
/* 选择所有链接到PDF文件的链接 */
a[href$=".pdf"] {
background-image: url('pdf-icon.png');
background-repeat: no-repeat;
padding-left: 20px;
}
/* 选择所有href中包含"example"的链接 */
a[href*="example"] {
text-decoration: underline dotted;
}
/* 选择class中包含单词"button"的元素 */
[class~="button"] {
border-radius: 4px;
}
/* 选择语言属性为英语及其变种的元素 */
[lang|="en"] {
font-family: 'Times New Roman', serif;
}
使用场景:
- 基于文件类型设置链接样式
- 实现图标系统
- 根据数据属性应用样式
- 选择特定类型的输入控件
4. 大小写敏感性
属性选择器默认区分大小写。使用i修饰符可以使选择器不区分大小写。
/* 大小写敏感匹配 */
[type="submit"] {
background-color: blue;
}
/* 大小写不敏感匹配 */
[type="submit" i] {
color: white;
}
伪类选择器
伪类选择器选择处于特定状态或位置的元素。伪类以冒号(:
)开头。
1. 状态伪类
选择处于特定交互状态的元素。
/* 鼠标悬停状态 */
a:hover {
text-decoration: underline;
}
/* 被激活的链接(鼠标按下时) */
a:active {
color: red;
}
/* 获得焦点的输入框 */
input:focus {
border-color: blue;
outline: none;
}
/* 已访问的链接 */
a:visited {
color: purple;
}
/* 被禁用的表单元素 */
button:disabled {
opacity: 0.5;
cursor: not-allowed;
}
/* 被选中的复选框或单选按钮 */
input:checked + label {
font-weight: bold;
}
使用场景:
- 创建交互反馈
- 提高用户界面可用性
- 增强表单元素的视觉反馈
2. 结构性伪类
基于元素在文档结构中的位置选择元素。
/* 第一个子元素 */
li:first-child {
font-weight: bold;
}
/* 最后一个子元素 */
li:last-child {
margin-bottom: 0;
}
/* 唯一的子元素 */
li:only-child {
list-style-type: none;
}
/* 特定位置的子元素 */
li:nth-child(odd) {
background-color: #f5f5f5;
}
li:nth-child(3n+1) {
color: blue;
}
/* 倒数第二个子元素 */
li:nth-last-child(2) {
text-decoration: underline;
}
/* 特定类型的第一个元素 */
p:first-of-type {
font-size: 1.2em;
}
/* 特定类型的最后一个元素 */
p:last-of-type {
margin-bottom: 2em;
}
/* 特定类型的唯一元素 */
img:only-of-type {
display: block;
margin: 0 auto;
}
/* 特定类型的第n个元素 */
h2:nth-of-type(2) {
color: navy;
}
使用场景:
- 创建交替行样式(斑马条纹)
- 特殊处理第一个或最后一个项目
- 实现网格布局或列表样式
- 精确定位无类或ID的元素
3. 特殊伪类
/* 所有未被访问的链接 */
a:link {
color: blue;
}
/* 空元素(不包含子元素或文本) */
div:empty {
display: none;
}
/* 目标元素(URL片段指向的元素) */
section:target {
background-color: #fffacd;
animation: highlight 2s ease;
}
/* 否定伪类(选择不符合选择器列表的元素) */
p:not(.special) {
color: #333;
}
/* 选择具有特定值的输入元素 */
input:valid {
border-color: green;
}
input:invalid {
border-color: red;
}
/* 选择根元素(通常是html元素) */
:root {
--main-color: blue;
font-size: 16px;
}
/* lang伪类 */
:lang(fr) {
quotes: "«" "»";
}
使用场景:
- 根据元素状态应用样式
- 创建表单验证的视觉反馈
- 根据URL片段高亮内容
- 定义全局CSS变量
伪元素选择器
伪元素选择器创建或选择元素的特定部分。伪元素使用双冒号(::
)表示。
/* 在元素内容前插入内容 */
.icon::before {
content: "";
display: inline-block;
width: 16px;
height: 16px;
background-image: url('icon.png');
margin-right: 5px;
}
/* 在元素内容后插入内容 */
a[href^="http"]::after {
content: " ↗";
font-size: 0.8em;
}
/* 选择元素的第一个字母 */
p::first-letter {
font-size: 2em;
font-weight: bold;
float: left;
margin-right: 5px;
}
/* 选择元素的第一行 */
p::first-line {
font-variant: small-caps;
}
/* 选择用户选中的文本 */
::selection {
background-color: gold;
color: black;
}
/* 选择占位符文本 */
input::placeholder {
color: #aaa;
font-style: italic;
}
使用场景:
- 添加装饰性内容(如图标)
- 创建特殊排版效果(如首字下沉)
- 自定义输入控件的外观
- 改变用户选择文本的样式
选择器组合与优化
1. 组选择器
将多个选择器组合应用同一组样式规则。
/* 多个选择器共用相同的样式规则 */
h1, h2, h3, h4, h5, h6 {
font-family: 'Georgia', serif;
line-height: 1.2;
}
button, .button, input[type="submit"] {
border-radius: 4px;
padding: 8px 16px;
cursor: pointer;
}
2. 选择器组合
可以将多种选择器组合使用,创建高度具体的选择模式。
/* 多种选择器组合 */
#sidebar ul.navigation li.active > a:hover {
color: #ff6600;
}
/* 属性选择器与伪类组合 */
input[type="checkbox"]:checked + label::before {
content: "✓";
color: green;
}
3. 选择器优化
过于复杂的选择器可能影响性能,尤其是在大型网页上。
优化建议:
- 避免过深的后代选择器(超过3-4级)
- 尽量使用类选择器,少用通用选择器
- 避免过度依赖位置选择器
- 优先使用直接子代选择器(>)而非后代选择器(空格)
/* 过于复杂的选择器 */
body div.container ul li a span { color: red; }
/* 优化后 */
.nav-link-text { color: red; }
选择器实践应用
1. BEM命名约定下的选择器
BEM(Block, Element, Modifier)是一种命名约定,有助于创建模块化、可维护的CSS。
/* 块 */
.card {
background: white;
border-radius: 4px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
/* 元素 */
.card__title {
font-size: 18px;
margin-bottom: 10px;
}
.card__image {
width: 100%;
border-radius: 4px 4px 0 0;
}
/* 修饰符 */
.card--featured {
border: 2px solid gold;
}
.card__title--large {
font-size: 24px;
}
2. 媒体元素控制
使用选择器创建响应式媒体元素。
/* 图像适应容器 */
img {
max-width: 100%;
height: auto;
}
/* 响应式视频容器 */
.video-container {
position: relative;
padding-bottom: 56.25%; /* 16:9宽高比 */
height: 0;
overflow: hidden;
}
.video-container iframe,
.video-container object,
.video-container embed {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
3. 表单样式化
使用选择器精确控制表单元素样式。
/* 所有输入控件的基本样式 */
input, select, textarea {
border: 1px solid #ddd;
border-radius: 4px;
padding: 8px 12px;
font-size: 16px;
}
/* 特定类型的输入控件 */
input[type="text"],
input[type="email"],
input[type="password"] {
width: 100%;
margin-bottom: 15px;
}
/* 表单状态和验证 */
input:focus {
border-color: #4a90e2;
box-shadow: 0 0 0 2px rgba(74, 144, 226, 0.25);
outline: none;
}
input:invalid {
border-color: #e74c3c;
}
input:valid {
border-color: #2ecc71;
}
/* 禁用状态 */
input:disabled,
select:disabled,
textarea:disabled {
background-color: #f5f5f5;
cursor: not-allowed;
opacity: 0.7;
}