css-选择器

CSS 基础

CSS: 层叠样式表(Cascading Style Sheets),

层叠表示先前添加的样式会被后面添加的样式覆盖(具体原则后面详述),
样式用于定义HTML元素在浏览器中的表现形式, 其通常存放在样式表中

CSS 语法

syntax

CSS 规则选择器(selector)声明块(declaration block) 两个部分组成

选择器: 用于从HTML文档中选择需要添加样式的DOM元素
声明块: 由一个或多个声明组成,各个声明之间用 ; 分隔。每个声明是一个key-value对, key为CSS属性,value为该属性的值, key和value之间用 : 分隔。

样式表 由一系列上述规则组成

CSS选择器

元素选择器

使用 html 元素名作为选择器,(所有html元素的的元素名都可以作为选择器) 例如:

1
2
body { background: gray; }
p { color: red; }

使用了 <body> 或 <p> 元素名作为选择器。他们会影响整个html文档中 <body>的背景色, 和所有<p>元素中的字体颜色

选择器分组

用于将一个 CSS 声明块影响多个不同的元素

1
p, h1 { color: red; } /*所有 <p> 和 h1 标签中的字体颜色为红色 */

在 CSS规则左侧将多个选择器用逗号( , )隔开,告诉浏览器这个两个不同的选择器。逗号不能省略, 如果省略意义就完全不同了。

声明分组

与选择器分组类似,CSS规则的声明也可以分组

1
2
p { font-size: 14px; }
p { color: blue; }

将所有p元素中的字体大小设置为 14px, 颜色为蓝色
这种声明效率底,在实际开发中不使用,会将分组声明合成一个声明

1
p { font-size: 14px; color: blue;}

类选择器和ID选择器

除了用标签名作为元素选择器外,类选择器(class selector)和ID选择器(ID selector) 也是开发过程中常用的选择器

1、类选择器: 用元素的 class 属性作为选择器, 在CSS中,用点号 + 类名 (.class-name) 表示类选择器

  • 类选择器默认作用于拥有对应 class 属性的所有元素, 如下例所示 .warn 中的规则作用于 p 和 span 两个元素, 字体颜色都为蓝色
  • 如果想要将类选择器的样式与元素关联, 可以采用元素名+.+类名的方式构成选择器, 如下例: span.warn, 其对应的规则只影响到了 span 元素, 而p 元素未受影响
  • HTML中, 元素的class 属性可以包含多个值,各个值直接用空格隔开, 假如两个或几个类选择器链接在一起,可以选择仅同时包含这些类名的元素(类名顺序不限), 如下例: .urgent.warn 对应的规则只影响了同时拥有类: urgent 和 warn 的 p 元素
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <style>
    .warn { color: blue; }
    span.warn { font-size: 20px; }
    .urgent { font-style: italic; }
    .urgent.warn { background: yellow; }
    </style>
    <p class="warn">feifeiyu p</p>
    <span class="warn">feifeiyu span</span>
    <p class="warn urgent">feifeiyu multi-class</p>
    <span class="urgent">feifeiyu single-class</span>

class-selector

2、ID选择器: 用元素的 id 属性作为选择器, 在CSS中, 用 #+id值(#id-value) 表示ID选择器,

1
2
3
4
<style>
#my-num { color: blue;}
</style>
<p id="my-num">13288888888</p>

与类选择器不同, 标签中的id属性是唯一的,且不可以有多个值, 因此ID选择器不能像类选择器一样结合使用,ID选择器理论上可以更精准的选择对应的元素

注意 浏览器通常不检查HTML标签中 id 属性的唯一性, 意味着如果一个HTML文档中假如存在多个相同的id属性值, 对应的CSS规则可能为这些id值相同的元素添加相同的样式

属性选择器

属性选择器(atrribute selector): 根据元素的属性及属性值来选择对应的元素, 类选择器和ID选择器本质上就是属性值的选择

1、简单属性选择

简单属性选择用于选择有某个属性的元素, 不论该属性是什么值。
简单属性选择器定义:标签名[属性名],如下所示:有class 属性的 h3 标签, h3[class], 或有 my-name属性的 h3 标签, h3[my-name]

1
2
3
4
5
6
<style>
h3[class] { color: green; }
h3[my-name] { font-style: italic; }
</style>
<h3 class="hoop">Hello</h3>
<h3 class="hoop" my-name="fei">Feifeiyu</h4>

attr-selector

2、具体属性值选择

根据特定属性值选择元素, 定义: 标签名[属性名=”属性值”]
例如:选择链接为google.com的 a 标签 a[href=”google.com”]
注意 采用具体属性值选择时, 必须要求属性值与相应标签的属性值完全相同,否则无法生效, 例如: a[href=”baidu”]的样式就无法生效

1
2
3
4
5
6
7
8
9
10
<style>
a[href="google.com"] {
text-decoration: none; /*无下划线*/
}
a[href="baidu"] {
text-decoration: none;
}
</style>
<a href="//google.com">Google</a>
<a href="//baidu.com">Baidu</a>

attr-selector

3、根据部分属性选择
| 选择器 | 描述 | 例 |
| —- | —- | – |
| [foo~=”bar”] | 选择属性值列表里包含词 “bar” 的所有元素 | p[class~=”warn”] |
| [foo^=”bar”] | 选择属性值以 “bar” 开头的所有元素 | p[href^=”baidu”] |
| [foo$=”bar”] | 选择属性值以 “bar” 结尾的所有元素 | p[href$=”com”] |
| [foo*=”bar”] | 选择属性值中包含子串 “bar” 的所有元素 | p[href*=”du”] |

HTML文档树结构

HTML文档是一种具有层次结构的文档, 可以从 “树” 这种数据结构来形象的理解这种文档结构, 如下图所示
dom-tree
在HTML文档中, 每个元素都有自己的位置, 他要么是别的元素的子元素, 要么是别的元素的父元素, 通常两者兼有之。

1
2
3
4
5
6
7
8
9
10
11
12
<html> 
<head>
<title>page title</title>
</head>
<body>
<p>XXX我是一个段落XXX</p>
<ul>
<li>google</li>
<li>baidu</li>
</ul>
</body>
</html>

根据上例分析:
1、如果一个元素出现在另一个元素的上一层, 则 前者称为后者的父元素, 后者为前者的子元素, 他们之间为 父-子关系

head, body 为 html 元素的 子元素, html 为 head, body 的父元素; body 为 p, ul 元素的父元素, p, ul 为 body 的子元素, 以此类推

2、如果从一个元素到另一个元素需要跨越两级或多级, 他们之间为 祖先-后代 关系

例如: ul, p 为 html 元素的后代, html 为 ul,p 元素的祖先。 li 为 body 和 html 的后代元素, body, html 都为 li 的祖先元素
父子关系为 祖先-后代关系的特例

3、拥有相同父元素的元素, 他们之间为: 兄-弟关系

例如 p, ul 元素相互为兄弟关系, 两个 li 元素之间为兄弟关系, body, head 之间为兄弟关系

后代选择器

后代选择器: 在CSS 规则左边的选择器一端包含两个或多个用空额分隔的选择器, 选择器之间, 左侧的对应的元素必须是右侧的祖先元素,
选择器可以是上面介绍的每一种, 后代选择器可以影响所有后代元素, 包括子元素。
例如: p i 表示 p 元素后代中的任何 i 元素: 从结果上看这条规则可以影响到 p 元素的子元素及后代元素

1
2
3
4
5
6
7
<style>
p span {color: gray;} /*p 的子元素 span 颜色为 灰色*/
p i {color: yellowgreen;} /*p 的后代元素 i 颜色为黄绿*/
p .school { font-size: 26px; } /* 使用 元素选择器加类选择器混用模式 */
</style>
<p>feifeiyu <span>is my</span><i>nick</i></p>
<p>graduated from <span class="school">NUAA <i> with master degree</i></span></p>

child-selector

子选择器

子选择器: 用于选择一个元素的子元素, 定义:父元素选择器 > 子元素选择器 ( > 称为子结合符), > 的左右两侧可以有空格,也可以没有,随意。
例如: p > i 规则只会影响到 p 中子元素 i 的样式, 而后代元素为 i 的则无影响。

1
2
3
4
5
<style>
p > i {color: yellowgreen;}
</style>
<p>feifeiyu <span>is my</span><i>nick</i></p>
<p>graduated from <span class="school">NUAA <i> with master degree</i></span></p>

child-selector

相邻兄弟元素选择器

兄弟元素选择器: 在同一父元素下, 要选择紧接在一个元素后的兄弟元素,可以使用兄弟选择器, 定义 选择器 + 选择器( + 称为相邻兄弟结合符 ), + 左右两侧可以有无空格随意
例: .list #google + li 选择 id 属性值为 google 元素后面相邻的兄弟元素

1
2
3
4
5
6
7
8
<style>
.list #google + li {color: brown;}
</style>
<ul class="list">
<li id="google">Google</li>
<li>Baidu</li>
<li>Bing</li>
</ul>

brother-selector

伪类选择器

伪类(pseudo-class): 一般用于标识已访问和未访问的锚类型, 例如: visited, hover
伪类选择器: 为普通选择器 + 伪类结合的选择器,定义: 选择器:伪类名
例如: 1、常见用法 a:link, 2、结合伪类 a:visited:hover

1
2
3
4
5
6
7
8
<style>
a:link { color: gray; } /*未访问时状态*/
a:hover { color: pink;} /*鼠标指针停留时状态*/
a:visited { color: blue;} /*访问过后的状态*/
a:visited:hover {color: red;} /*访问过后的链接,鼠标指针停留 */
</style>
<a href="//google.com">Google</a>
<a href="//Baidu.com">Baidu</a>

pseudo-selector

伪元素选择器

伪元素(pseudo-element): 是插入文档的假想元素, 从而得到某种效果
伪元素选择器: 为普通选择器 + 伪元素结合的选择器, 定义: 与伪类选择器类似, 选择器:伪元素名 or 选择器::伪元素名
例如, :first-letter 段落的首字母, :before, :after 对应元素添加之前之后元素

1
2
3
4
5
6
7
<style>
.pse-elem:first-letter { font-size: 200%;}
.bre-aft:before { content: "(" }
.bre-aft:after { content: ")"}
</style>
<p class="pse-elem">This is a rainy day</p>
<p class="bre-aft"> pseudo element after & berfore </>

pseudo-selector

其他选择器

除以上介绍的常用的选择器, 跟多的选择器请访问: CSS 选择器参考手册

样式继承

样式继承: CSS样式不仅可以应用的到选择器指定的元素, 还会应用的他的后代元素
例如: .inherit1 选择的目标元素为 p 元素, i 作为 p 的子元素继承了 p 元素的样式
CSS 样式声明会沿着DOM树,向下传播到后代元素;但后代元素的样式声明则不能反方向向祖先元素传播

1
2
3
4
5
6
<style>
.inherit1 { color: blue; }
.inherit2 { color: yellow; }
</style>
<p class="inherit1">NUAA is short for <i> Nanjing University of Aeronautics and Astronautics</i></p>
<p>NUAA is short for <i class="inherit2"> Nanjing University of Aeronautics and Astronautics</i></p>

inherit
注意一般而言, 大多数框属性无法继承, 例如: 外边距, 内边距, 边框, 背景等。

样式层叠

如果存在两条规则,且这两条规则影响的是同一个DOM元素的同一个样式(例如: 下面的两条规则), 因此这两条规则形成了冲突, 此时那条规则具有更高的优先级,战胜另一条规则, 例如:
h1 { color: red; }
h2 { color: blue; }
此时就涉及到 CSS 中一个非常重要的概念层叠也是 CSS 命名来源之一。
CSS 层叠样式就是, 通过选择器的特殊性和继承, 让样式层叠在一起, 层叠规则如下:

1、找出声明

找出所有相关CSS声明, 这些声明都能影响到某一个DOM元素
如果两条规则影响同一个DOM元素,但声明不同,则这两条规则同时生效,

1
2
3
4
5
<style>
p { color: blue; }
p { font-size: 24px; }
</style>
<p>NUAA is short for Nanjing University of Aeronautics and Astronautics</p>

rule2
如果两条规则影响同一个DOM元素,声明相同,就需要考虑以下规则了

2、按权重和来源排序

标志 !important 的声明权重要高于没有 !important 的声明

1
2
3
4
5
<style>
p { color: blue !important; }
p { color: yellow; }
</style>
<p>NUAA is short for Nanjing University of Aeronautics and Astronautics</p>

important
不带 !important 的声明, 不管写得如何的天花乱坠, 优先级都没有带有 !important 的声明优先级高, 正因 !important 杀伤范围太大, 在开发过程中不推荐使用

CSS 样式来源一共有三种: 创作人员, 读者, 用户代理

  • 创作人员: 就是页面开发者(即前端开发)编写的样式, 称为创作人员样式
  • 读者: 浏览器用户,如果用户为网页样式添加了个性化配置,这些样式称为读者样式
  • 用户代理: 用户代理是指浏览器本身, 一般浏览器都会为一些元素提供默认样式, 这些样式称为用户代理样式

声明优先级排序
1、读者的带有 !important 的声明
2、创作人员的带有 !important 的声明
3、创作人员的正常声明
4、读者的正常声明
5、用户代理的声明

开发过程中一般需要考虑前4级, 任何声明都会胜过用户代理样式。

3、按特殊性排序

特殊性(specificity): 是指选择器的特殊性, 对于每个跪着,用户代理(浏览器)都会计算选择器的特殊性, 并将特殊性附加到CSS规则的各个声明。
按特殊性对元素给定的所有声明进行排序, 特殊性高的声明优先级高, 在声明特殊性最高的会在所有声明冲突中胜出
特殊性是页面开发中最常用的

特殊性表述

  • 使用内联样式,即在元素 style 属性中添加样式: 加 1,0,0,0
  • 使用元素 ID属性值作为选择器的: 加 0,1,0,0
  • 使用元素的 class属性值、属性(例如:title, type等)、伪类作为选择器: 加 0,0,1,0
  • 使用元素名称, 伪元素 作为选择器: 加 0,0,0,1
  • 使用通配符和结合符( * )作为选择器: 对特殊性没有任何帮助

例子:

  • p { color: red; } /specificity = 0,0,0,1 /
  • p i { color: purple; } /specificity = 0,0,0,2 /
  • .class-a { color: blue; } /specificity = 0,0,1,0 /
  • *.class-a { color: yellow; } /specificity = 0,0,1,0 /
  • p.class-a { color: maroon; } /specificity = 0,0,1,1 /
  • p.class-a i.class-b { color: block; } / specificity = 0,0,2,2 /
  • input[type=”button”] { color: pink; } / specificity = 0,0,1,0 /
  • #id-a { color: silver; } / specificity = 0,1,0,0 /
  • p.class-a i#id-b { color: blue; } / specificity = 0,1,1,2 /

特殊性比较:

先比较最高位, 如果 A 的最高为大于 B 最高为,则 A 胜出; 例如: 0,1,0,0 > 0,0,10,0; 0,1,1,0 > 0,0,0,10;
如果 A, B 的最高为相同, 就比较次高位, 次高位数值高的声明胜出, 以此类推…

1
2
3
4
5
<style>
p.class-a span.class-b { color: blue; }
#id-b { color: yellow; }
</style>
<p class="class-a">NUAA is short for <span class="class-b" id="id-b">Nanjing University of Aeronautics and Astronautics</span></p>

specificity
在规则 p.class-a span.class-b { color: blue; } 中, 声明 color 的特殊性为 0,0,2,2
在规则 #id-b { color: blue; } 中, 声明 color 的特殊性为 0,1,0,0, 特殊性高,胜出

内联样式的特殊行比其他规则的声明的特殊性都高, 所有写在 元素 style 中的样式是无法通过 CSS 去修改的 (!important 声明除外)

4、按顺序排序

如果两个规则的 权重, 来源, 特殊性完全相同, 那么在样式表中后出现的声明会胜出

1
2
3
4
<style>
p { color: blue; color: seagreen;}
</style>
<p class="class-a">NUAA is short for <span class="class-b" id="id-b">Nanjing University of Aeronautics and Astronautics</span></p>

rule4

推荐链接样式顺序 LVHA
因为伪类拥有相同的特殊性, 因此与元素匹配比较时最后一个声明会胜出
在点击链接时会同时生效伪类: :link, :hover, :active, 如果将 :active 放在最后,点击链接时可以获得期望的效果
一般在推荐的链接样式: link-visited-hover-active(LVHA)

1
2
3
4
5
6
7
<style>
a:link { color: blue; }
a:visited { color: purple;}
a:hover { color: green; }
a:active { color: orange;}
</style>
<a href="//baidu.com" target="_blank">Baidu.com</a>

END