【前端(二)】CSS 知识梳理:从编写位置到选择器优先级

文章目录

  • [1. CSS编写位置](#1. CSS编写位置)
    • [1.1 行内样式](#1.1 行内样式)
    • [1.2 内部样式](#1.2 内部样式)
    • [1.3 外部样式](#1.3 外部样式)
    • [1.4 不同位置的优先级](#1.4 不同位置的优先级)
  • [2. CSS 语法规范](#2. CSS 语法规范)
  • [3. CSS 选择器](#3. CSS 选择器)
    • [3.1 基本选择器](#3.1 基本选择器)
    • [3.2 复合选择器](#3.2 复合选择器)
      • [3.2.1 交集选择器](#3.2.1 交集选择器)
      • [3.2.2 并集选择器](#3.2.2 并集选择器)
      • [3.2.3 后代选择器](#3.2.3 后代选择器)
      • [3.2.4 子元素选择器](#3.2.4 子元素选择器)
      • [3.2.5 兄弟选择器](#3.2.5 兄弟选择器)
      • [3.2.6 属性选择器](#3.2.6 属性选择器)
      • [3.2.7 伪类选择器](#3.2.7 伪类选择器)
        • [3.2.7.1 动作伪类](#3.2.7.1 动作伪类)
        • [3.2.7.2 结构伪类](#3.2.7.2 结构伪类)
        • [3.2.7.3 否定伪类](#3.2.7.3 否定伪类)
        • [3.2.7.4 UI伪类](#3.2.7.4 UI伪类)
      • [3.2.8 伪元素选择器](#3.2.8 伪元素选择器)
    • [3.3 选择器的优先级](#3.3 选择器的优先级)

1. CSS编写位置

1.1 行内样式

  • 位置:直接写在HTML标签的 style 属性中。
  • 🌰示例
html 复制代码
<h1 style="color:red;font-size:60px;">欢迎</h1>
  • 特点
    • 优点:直接、优先级最高。
    • 缺点
      1. 结构与样式未分离:HTML和CSS耦合在一起,不利于维护。
      2. 无法复用:样式只对当前这一个标签有效。
  • 使用场景:极少使用,通常仅用于临时测试或必须最高优先级的个别样式覆盖。

1.2 内部样式

  • 位置:写在HTML页面内部的 <style> 标签中。<style> 标签通常放在 <head> 标签内。
  • 🌰示例
html 复制代码
<head>
    <style>
        h1 {
            color: red;
            font-size: 40px;
        }
    </style>
</head>
  • 特点

    • 优点:实现了页面内的样式复用,便于维护一个页面的样式。
    • 缺点
      1. 结构与样式并未完全分离
      2. 样式无法在多个HTML页面之间复用。
  • 使用场景:适用于单个页面的简单网站,或作为学习、测试时的临时样式。

1.3 外部样式

  • 位置 :将CSS代码单独保存在一个 .css 文件中,然后在HTML文件中通过 <link> 标签引入。

  • 步骤

    1. 创建一个 .css 文件(例如 style.css),写入CSS代码。
    css 复制代码
    /* style.css */
    h1 {
    	color: red;
    	font-size: 40px;
    }
    1. 在HTML文件的 <head> 标签内,使用 <link> 标签引入该文件。
    html 复制代码
    <head>
    	<link rel="stylesheet" href="./style.css">
    </head>
    • rel="stylesheet":rel 是 "relation" 的缩写,指明引入文件与当前文档的关系是"样式表"。
    • href="./style.css":href 是 "hypertext reference" 的缩写,指明样式文件的路径。
  • 特点

    • 优点
      1. 实现了结构与样式的完全分离,代码结构清晰。
      2. 样式可复用 :一个 .css 文件可以被多个HTML文件引入,极大地提高了开发效率。
  • 使用场景:实际开发中的标准做法,也是最推荐的方式。

1.4 不同位置的优先级

多个样式规则作用于同一个元素样式冲突时,优先级遵循以下规则:

  1. 优先级规则:行内样式 > 内部样式/外部样式
  2. "后来者居上"规则 :对于内部样式和外部样式,它们的优先级是相同的。如果它们发生了冲突,后加载或后编写的样式会覆盖先前的样式。
    • 这意味着,如果<style>标签写在 <link> 标签之后,那么内部样式的优先级会高于外部样式;反之亦然。

当样式冲突时,先比"类型"(行内样式最高),再比"时机"(谁后写谁生效)。如果样式没有冲突,无论写在哪个位置,它们都会被应用。


2. CSS 语法规范

CSS的语法规则非常简单,由选择器声明块两部分构成。

  • 选择器:用于指定要添加样式的HTML元素。
  • 声明块 :由一对花括号 {} 包裹,里面是一个或多个具体的样式声明。
    • 声明的格式是:属性名: 属性值;

选择器与声明块之间,属性名与属性值之间,均有一个空格,理论上可以省略,但是建议书写。


书写风格

  1. 展开风格:开发时推荐,每个属性占一行,清晰易读,便于维护和调试。
css 复制代码
h1 {
    color: red;
    font-size: 40px;
}
  1. 紧凑风格:项目上线时推荐,所有代码写在一行,可以减小文件体积,提高加载速度。
css 复制代码
h1{color:red;font-size:40px;}

在项目上线时,通常会使用自动化工具自动将展开风格转换为紧凑风格。这样可以减小文件体积,节约网络流量,同时也能让用户打开网页时速度更快。
区别HTML中的标签属性 ,HTML的标签属性是键值对 形式,用空格分隔(如 <div class="box" id="main"></div>)。而CSS的声明是 属性名: 属性值; 的形式,用分号分隔。


3. CSS 选择器

选择器用于精准定位我们想要添加样式的HTML元素。

3.1 基本选择器

选择器类型 作用 语法示例 特点与注意事项
通配选择器 选中页面中所有的HTML元素 * { margin: 0; } 常用于清除浏览器默认的边距,效率较低,慎用。
元素选择器 选中页面中所有某种标签名的元素 h1 { color: red; } 会统一改变所有同名标签的样式,无法差异化选择。
类选择器 根据元素的 class 属性值选中某些元素 .title { ... } 最常用 。一个元素可以有多个类名,用空格隔开,如 <div class="title red">
ID选择器 根据元素的 id 属性值,来精准的选中某个元素 #nav { ... } 一个HTML文档中,id 属性值必须唯一,因此ID选择器只能选中一个元素。
  • 优先级 :当不同选择器选中同一个元素并发生样式冲突时,优先级为:
    ID选择器 > 类选择器 > 元素选择器 > 通配选择器。
    同类型选择器之间,遵循"后来者居上"原则。

3.2 复合选择器

复合选择器由多个基础选择器组合而成,可以实现更精准、更复杂的选择。

3.2.1 交集选择器

  • 作用:选中同时符合多个条件的元素。(缩小范围)
  • 语法:选择器1选择器2选择器3...选择器n { } (选择器之间紧挨着,无空格)
  • 示例:p.text 选中所有 class="text" 的 <p> 元素。
  • 注意
    1. id 选择器、通配选择器,理论上可以作为交集的条件,但实际应用中几乎不用,因为没有意义。
    2. 如果选择器中包含元素选择器,它必须写在最前面。

3.2.2 并集选择器

  • 作用:同时选中多个选择器对应的元素,简化代码。

  • 语法:选择器1, 选择器2, ...(选择器之间用逗号隔开)

    css 复制代码
    选择器1, 
    选择器2,
    选择器3, 
    ... 
    选择器n {
    	属性名: 属性值;
    }
  • 示例:h1, h2, .title, #main 将样式应用于所有这些元素。

  • 常用场景:通常用于集体声明,可以缩小样式表体积。如 h1, h2, h3 { font-family: "微软雅黑"; }

在学习后代选择器之前可以先查看附录:[HTML 元素之间的关系](#HTML 元素之间的关系)

3.2.3 后代选择器

  • 作用:选中某元素内部的所有符合条件的后代元素(包括子元素、孙元素等)。

  • 语法:祖先选择器 后代选择器(选择器之间用空格隔开)

    css 复制代码
    选择器1 选择器2 选择器3 ...... 选择器n {} 
  • 示例:div p 选中 <div> 内部所有的 <p> 元素。

  • 注意:后代选择器,最终选择的是后代,不选中祖先。

3.2.4 子元素选择器

  • 作用:选中某元素内部所有符合条件的直接子元素。

  • 语法 :父选择器 > 子选择器(选择器之间用 > 隔开)

    css 复制代码
    选择器1 > 选择器2 > 选择器3 > ...... 选择器n {}
  • 示例:div > p 选中所有父元素是 <div> 的 <p> 元素。

  • 对比:div p(后代选择器)会选中 <div> 下面任何层级的所有 <p>;而 div > p(子代选择器)只选中作为 <div> 直接子元素的 <p>。

  • 注意:子代选择器,最终选择的是子代,不是父级。

3.2.5 兄弟选择器

  • 相邻兄弟选择器 :选择器1 + 选择器2。选中 紧跟 在 选择器1 后面第一个 选择器2 元素。必须要是紧挨着的
  • 通用兄弟选择器 :选择器1 ~ 选择器2。选中跟在 选择器1 后面所有 选择器2 兄弟元素。

相邻兄弟选择器的关键点:

  1. 紧跟着的 2. 后面的 3. 第一个

    通用兄弟选择器的关键点:

  2. 后面的 2. 所有

3.2.6 属性选择器

  • 作用:根据元素的属性及属性值来选中元素。
  • 常见语法
    1. 属性名\] 选中具有某个属性的元素。

    2. 属性名\^="值"\] 选中包含某个属性,且属性值以指定的值开头的元素。

    3. 属性名\*="值"\] 选择包含某个属性,属性值包含指定值的元素。

伪类:假的类,像类,但不是类,是元素的一种状态。

3.2.7.1 动作伪类
  1. :link 超链接未被访问的状态。
  2. :visited 超链接访问过的状态。
  3. :hover 鼠标悬停在元素上的状态。
  4. :active 元素激活的状态。(鼠标按下未松开)
  5. :focus 获取焦点的元素。(如输入框)

注意

  1. link 和visited 只针对超链接有效,hover和active对全部元素有效,focus只针对表单类元素。
  2. LVHA顺序 :为链接设置样式时,推荐顺序为 :link -> :visited -> :hover -> :active。
    当多个规则同时生效且优先级相同时,后写的规则胜出。如果 :active 写在 :hover 之前,当鼠标点击时,同时处于悬浮和激活状态,:hover 靠后,会覆盖 :active 的样式,导致激活样式不生效。
3.2.7.2 结构伪类
  1. :first-child 选中父元素中的第一个子元素。
  2. :last-child 选中父元素中的最后一个子元素。
  3. :nth-child(n) 选中父元素中的第 n 个子元素。
  4. :first-of-type 所有同类型 兄弟元素中的第一个
  5. :last-of-type 所有同类型 兄弟元素中的最后一个
  6. :nth-of-type(n) 所有同类型 兄弟元素中的 第n个

注意

  1. :nth-child(n) 与 :nth-of-type(n) 的区别
  • :nth-child(n) 不考虑元素类型,只关心它在父元素的所有子元素中的位置。

  • :nth-of-type(n) 先筛选出同类型的元素,再在这些元素中找位置。

    🌰 示例对比

    html 复制代码
    <div>
        <p>段落1</p>
        <span>span1</span>
        <p>段落2</p>
    </div>
    • div :nth-child(2) 选中 <span>span1</span>(所有子元素中的第2个)。
    • div :nth-of-type(2) 选中 <p>段落2</p>(同类型 <p> 中的第2个)。

再看示例:

  • first-child
  • first-of-type
  1. n 可以是 an+b 形式的表达式,例如:
    • n:选择所有(从第1个开始)。
    • 2n:选择所有偶数位。
    • 2n+1:选择所有奇数位。
    • -n+3:选择前3个。
3.2.7.3 否定伪类

:not(选择器) 排除满足括号中条件的元素。

3.2.7.4 UI伪类
  1. :checked 被选中的复选框或单选按钮元素。
  2. :enable 可用的表单元素(没有 disabled 属性)。
  3. :disabled 不可用的表单元素(有 disabled 属性)。

3.2.8 伪元素选择器

伪元素:像元素,但不是元素,选中元素中一些特殊的位置。用双冒号表示。

  • 常见伪元素
  1. ::first-letter 选中元素中的第一个文字。
  2. ::first-line 选中元素中的第一行文字。
  3. ::selection 选中被鼠标选中的内容。
  4. ::placeholder 选中输入框的提示文字。
  5. ::before 在元素最开始的位置,创建一个子元素(必须用 content 属性指定内容)。
  6. ::after 在元素最后的位置,创建一个子元素(必须用 content 属性指定内容)。

3.3 选择器的优先级

当多个选择器指向同一个元素产生样式冲突 时,浏览器会根据一套权重规则来决定哪个样式生效。

  • 权重计算:每个选择器都可以计算出一个权重值,表示为 (a, b, c)。

    • a:ID选择器的个数。
    • b:类选择器伪类选择器属性选择器的个数。
    • c:元素选择器伪元素选择器的个数。
  • 比较规则:从左到右依次比较,(a, b, c) 中哪一位数字大,其优先级就高。如果完全相同,则遵循"后来者居上"原则。

选择器示例 权重 (a,b,c)
* (通配符) (0,0,0)
h1 (0,0,1)
.title (0,1,0)
#main (1,0,0)
h1.title (0,1,1)
div > p#main (1,0,2)
  • 特殊规则

    • !important 标记的样式拥有最高优先级,会覆盖任何其他样式。开发中应尽量避免滥用,因为它会破坏样式天然的层叠规则。
    • 行内样式(style 属性)的权重次之,高于任何外部/内部选择器。
  • 优先级总结

    1. !important > 行内样式 > 内部样式 = 外部样式
    2. 内部样式与外部样式优先级相同,冲突时先比较选择器权重(ID > 类 > 元素),权重相同则遵循"后来者居上"原则。

注意:再次强调!优先级仅针对冲突的样式。当一个声明块中有多个样式时,冲突的属性会按优先级覆盖,不冲突的属性则会全部保留并生效。

🌰示例分析

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>优先级</title>
    <link rel="stylesheet" href="css.css"> <!-- 外部样式: h2:first-child { color: brown; } -->
    <style>
       .id > h2 {
           background-color: blueviolet;
           color: aqua;
       }
    </style>
</head>
<body>
    <div class="id">
        <h2>这里是好h2标题</h2>
    </div>
</body>
</html>
css 复制代码
/* css.css */
h2:first-child {
    color: brown;
}
  • 结果:背景色为 blueviolet,文字颜色为 aqua。
  • 原因:h2:first-child 的权重是 (0,1,1),而 .id > h2 的权重是 (0,1,1),两者权重相同。此时,因为内部样式写在外部样式之后,所以 color: aqua 生效。背景色只定义在内部样式中,无冲突,因此被保留。

如果调换内部和外部顺序:

html 复制代码
<!-- ... -->
<head>
    <style>
       .id > h2 {
           background-color: blueviolet;
           color: aqua;
       }
    </style>
    <link rel="stylesheet" href="css.css"> <!-- 外部样式现在写在内部样式之后 -->
</head>
<!-- ... -->
  • 结果 :背景色为 blueviolet,文字颜色为 brown。
  • 原因:外部样式 h2:first-child 权重 (0,1,1) 与内部样式权重相同,但外部样式后加载,所以 color: brown 生效。

附录:HTML 元素之间的关系

在HTML中,元素之间的嵌套关系就像一棵家族树。我们可以用以下5种关系来精准描述它们:

  1. 父元素:直接包裹另一元素的元素。
  2. 子元素:被父元素直接包裹的元素。
  3. 祖先元素:父元素、父元素的父元素......一直到根元素。
  4. 后代元素:子元素、子元素的子元素......所有嵌套在内的元素。
  5. 兄弟元素:拥有同一个父元素的同级元素。

图形讲解总结

html 复制代码
<div class="grandpa">      <!-- 祖先 -->
  <div class="parent">     <!-- 父元素 / 也是祖先 -->
    <p class="child">      <!-- 子元素 / 也是后代 -->
      我是子元素
    </p>
    <p class="child2">     <!-- 兄弟元素 -->
      我是兄弟
    </p>
  </div>
</div>

两个容易被忽略的关系

  1. 子元素是特殊的后代元素

    只要是直接包在里面的,都是后代;但只有紧挨着、直接包着的那一层,才叫子元素。

  2. 父元素是特殊的祖先元素

    同理,离得最近的上一级叫父元素,往上追溯都叫祖先。


以上为个人学习总结,旨在梳理个人理解。如有疏漏或不当之处,欢迎指正与交流。

相关推荐
倾颜2 小时前
我是怎么把单 Tool Calling 升级成多 Tool Runtime 的
前端·后端·langchain
清汤饺子2 小时前
Superpowers:给 AI 编程 Agent 装上"工程化超能力"
前端·javascript·后端
踩着两条虫2 小时前
AI驱动的Vue3应用开发平台 深入探究(十三):物料系统之区块与页面模板
前端·vue.js·人工智能·架构·系统架构
weixin199701080163 小时前
《得物商品详情页前端性能优化实战》
前端·性能优化
帮我吧智能服务平台3 小时前
装备制造企业售后服务数字化:从成本中心到利润中心背景
java·前端·制造
qq_368019663 小时前
用 react 的react-syntax-highlighter 实现语法高亮、行号与多行错误行高亮
前端·react.js·前端框架
lbh3 小时前
从LLM到Agent的核心概念
前端·openai·ai编程
Irene19913 小时前
JavaScript脚本加载的两种方式:defer/async 的区别
前端·javascript·php
天若有情6733 小时前
开篇必看:零基础吃透前端,别再盲目死记硬背了
前端