CSS基础之CSS选择器及CSS权重

前言

CSS(Cascade Style Sheet层叠样式表)是前端的一门修饰元素样式,实现外观设置的语言。它最先是由哈坤·利于1994年提出来的,当时伯特·波斯(Bert Bos)正在设计一个名为Argo的浏览器,于是他们决定一起设计CSS。1994年哈坤提出了最先的建议以后,在1995年的WWW会议上CSS又被再次提出,同年,W3C组织成立,CSS创作小组也步入正轨,随着规模的扩大,在1995年12月出版了CSS的第一份正式标准。后来经过一系列扩展和发展,现在CSS版本已经到了第三版。但是博主也是初学者,目前讨论的内容还是基于CSS2的,如有疏漏,诚望指正。

一、CSS选择器

CSS样式的设置是通过选择特定的某个或者某些甚至全局的元素,再设置元素的宽高、颜色、内外边距、位置等属性,因此要对一个元素的样式属性进行修改,首先需要对目标元素及进行定位。用于定位元素的工具称之为选择器,常见的选择器有id选择器,class选择器,标签选择器,属性选择器,伪类选择器, 伪元素选择器,通配符选择器等,这些选择器通过不同的方式或者属性来确定要选定的元素,具体选择方式和差异下面将再下文进行展开叙述。

1. 选择器介绍

(a) id选择器

id(identifier/identification)选择器是用于唯一地选定某个元素的最直接、最简单的方式。下文中第二段代码就是一个简单的id选择器的示例,id选择器通过“井号(#)+ id名”的方式来选择id名为指定值的元素。元素的样式设置代码段用一对花括号包裹起来,内含一系列“属性:值”对。

/*1. id选择器(1--1)*/
#good{
	color: red;
	font-size: 30px;
}

但说id选择器唯一确定某个元素也不太准确。对于CSS而言,若在HTML代码中为两个元素赋了相同的id,在CSS应用id选择器时,其实是可以将两个元素同时选择出来的,如下文中HTML代码所示,在body中声明了一个div和一个p标签,两者的id都设置为”good“。然后应用上文相同的CSS代码,选中id为good的元素,将其字体颜色设置为红色,字体大小设置为30px,得到的结果如图1所示。图中div和p标签的元素内容都发生了相应的变化,因此CSS其实是可以作用在相同id的多个元素上的。

<!-- 1. id选择器 -->
<div id="good">我的ID是good</div>
<p id="good">我的ID也是good</p>

 

图1 id选择器选中多个元素

 那为什么又要说id选择器是唯一确定元素的方式呢?首先identification本身就有唯一标识的意思,它就相当于是元素的身份证,身份证是一一对应的,不应该出现一对多或者多对一的情况,因此上文的写法是不可以的。现在的过程中还没有涉及到JavaScript(简称JS),在JS中有一个常见的方法就是获取文档中的某个元素,可以通过标签名或者id来获取,在这种情况下,如果存在多个相同id的元素,JS只能选择出第一个元素,其他后续的元素是选择不到的,因此在这种情况下,也是要求id要是唯一的。举个小栗子,我们在原本HTML的基础上再加一小段JS代码,改变指定id的元素的内容,得到的结构如图2所示,可以发现只有div的内容变了,p标签根本没有被选择到,所以在HTML代码的编写中,要注意避免id复用情况的发生。

<script type="text/javascript">
	var p=document.getElementById("good");
	p.innerHTML="我变了"
</script>
图2 JS选择指定id元素唯一

(b) class选择器

除了id,HTML元素还有一个常用的属性,那就是class属性,称为类,用于设置元素的类。一般而言,一个类的元素可以有多个,且不需要是同一种元素;并且同一个元素可以对应多个类,当多个类选择到了某个元素,并且都对统一样式属性进行了设置的情况下,遵循“后来者居上”的原则,后来的值覆盖之前的值。举个栗子,给定div元素并设置两个class,后一个class的字体颜色覆盖了前一个class的字体颜色,其他不交叉的样式按照给定的值进行渲染。class选择器的基本写法是“英文句号(.)+class名”,同样的,”样式属性-值“对用引号分割,用一对花括号包裹起来,如下文中CSS代码所示。

<!-- 2. class选择器 -->
<div class="boxes word">class选择器</div>
/*2. class选择器(m--n)*/
.boxes{
	width: 100px; 
	height: 100px;
	border-radius: 10px;
	color: black;
	border: 1px solid blue;
}

.word{
	color: red;
}
图3 class选择器示意图

 

(c) 标签选择器

标签选择器,顾名思义,根据标签名选择这个标签的所有元素,比起前面两个选择器要简单粗暴得多,选择范围也会随网页的复杂度的提高而扩大。一般标签选择器多用来去除某一类标签的默认样式,比如现在很多超链接都不会用它默认的蓝色字体下划线的样式,因此会用一个a标签对默认样式进行清除,改造成需要的方式。标签选择器的写法也比较简单,直接用标签名加英文括号包裹的样式属性设置即可。

图4 超链接默认样式
<!-- 3. 标签选择器 -->
<a href="#">超链接新样式</a>

 

/*3. 标签选择器*/
a{
	text-decoration: none;
	color: #3c3c3c;
}
图5 超链接新样式

(d) 属性选择器

属性选择器是一个很灵活的选择器,编程人员可以选择具有特定的属性的元素,它比单独的id选择器或者class选择器的范围是要更大的,以class属性为例,只要一个元素设置了class属性,那么就可以被属性选择器选择出来,id属性同理,但是现在尚不清楚属性选择器用在什么场合比较合适。另外,在使用属性选择器的时候,还可以对属性的值进行限定,下面就来举个例子。用CSS的属性选择器选择id值为“box1”的元素,并将该元素的背景颜色设置为灰色。属性选择器的写法是用一对方括号将待选属性放置其中,如果要限定属性值,将属性和属性值之间用等号连接,且属性值不需要加引号,其余的部分与前文选择器一致。

<div id="box1">id选择器</div>
/*4. 属性选择器(选出所有拥有某属性的标签,还可限定标签的值)*/
[id=box1]{
	background-color: #333333;
}

 

图6 属性选择器修改样式

(e) 通配符选择器

通配符,就是能匹配任何字符的符号,因此通配符选择器能够选中body中的所有元素,包括body本身。在默认情况下,如图7所示,body有一个外边距margin,默认设置为8px,这会使得在进行网页布局的时候,body内的元素始终无法紧贴业面边框,会有8像素的留白,这样其实是很不方便的,因此,一般都会用通配符选择器来去除元素本身的margin和padding,如果需要设置,后续用其他更具体的选择器设置即可。通配符选择器的写法也比较简单,前面用一个星号(*),后面同样跟样式设置即可,如下文中的CSS代码所示。

图7 body默认margin示意图
/*5. 通配符选择器*/
*{
	margin: 0;
	padding: 0;
}

(f) 伪类选择器

这个后面来补。

(g) 伪元素选择器

这个后面来补。

(h) 父子选择器

父子选择器是用于层数大于等于2的元素选择的选择器,以下面的代码为例,HTML中有两个span,且都没有设置id和class,在这种情况下要选择出div中的span需要用到父子选择器。父子选择器不一定是严格父子关系,也可以是爷孙等表层级的关系。在下面的代码中,span是div的子元素,那么在选择span的时候就可以用“父元素选择器+空格+子元素选择器”的方式来定位span,就如下文中的CSS代码中所示。而且如CSS代码中所示的那样,父元素和子元素的选择器可以不同,只要能定位到元素就行。

<div id="father">
	<span>123</span>
</div>
<span>234</span>
#father span{
	background-color: red;
	/*font-size: 设置的是字体的高度; */
	font-size: 20px;
	font-weight: bold;
	font-style: italic;
}

(i) 直接子元素选择器

直接子元素选择器可以说是父子选择器的严格版,直接子元素选择器只能选择父元素的直接子元素,即连接的元素之间只能是父子关系,表示方式是在父子选择器的基础之上,空格部分用>符号来连接,具体示例见如下代码,HTML结构与上文父子选择器相同:

#father > span{
	background-color: red; 
}

(j) 并列选择器

并列选择器是用一个元素的多个选择器一起来定位该元素,用尽可能多的限制来达到精准定位该元素的目的。写法是“选择器1选择器2……”,选择器之间无空格。以下面的代码为例,为了定位到HTML代码中的内容为2的div元素,只用标签选择器会多选出内容为1的div,但是用类标签又会多选出p标签,因此可以用并列选择器来解决问题。

<div>1</div>
<div class="demo">2</div>
<p class="demo">3</p>

 

div.demo{
	background-color: blue; 
	/*border复合属性: border-width border-style border-color*/
	border: 1px solid green;
}

(k) 分组选择器

分组选择器是为了给几个或几组不同的元素设置相同的属性而出现的,书写方式也很简单,用逗号将几个不同的选择器连接起来,然后后续继续跟平常的CSS设置即可。选择器彼此可以不同。

div, 
.demo, 
p{
	color: black;
}

2. 不同选择器优先级对比

前面说了那么多的选择器,那么当多个选择器选中同一个元素,并且对该元素的某一样式做了不同的设置,应该以哪种选择器为准,还是按照先后顺序,亦或是其他方式来确定最终的样式呈现方式呢?一般来说,按照选择强度来确定选择器的优先级(即前面所说的以谁为准),定位元素越精准的选择器,其效力越强。因此,可以得到如下的优先级关系:

id选择器 > class选择器 = 标签选择器 > 通配符选择器

PS:  同级样式后续样式覆盖前面的样式

二、CSS的三种引入方式

CSS选择器是为了选中HTML中的某些元素,并且对元素的样式进行设置和修改。但是要使得CSS真的在元素上生效,还有重要的一环——CSS引入。CSS引入就是让CSS代码和目标元素或者目标文档之间建立起联系,使得CSS代码能在文档上生效的步骤。一般而言,CSS有行间样式、页面级CSS和外部CSS文件三种形式,分别有不同的引入方式,下面将针对性地展开介绍。

1. 三种引入方式介绍

(a) 行间样式

行间样式是指直接在元素的标签中加入style属性设置样式,例如:

<!-- 1. 行间样式 -->
<div style="width: 100px; height: 100px;background-color: gray;">
	行间样式
</div>

(b) 页面级CSS

页面级CSS是指在头标签中加入style标签对,然后将CSS代码放style标签对中,例如:

<style type="text/css">
	div{
		width: 100px; 
		height: 100px;
		background-color: green;
	}
</style>

(c) 外部CSS文件

外部CSS文件的引入是通过在头标签中用link标签引入的,具体使用方式如下,其中href是CSS文件的位置或者URL。一般而言,HTML和CSS,JavaScript都是分开开发,各自为政的,因此外部CSS文件引入是主流的CSS引入方式,其余两种方式都是补充用的更多一点。

<link rel="stylesheet" type="text/css" href="./style.css">

2. 三种CSS引入方式的优先级对比

不同引入方式的CSS也是根据CSS代码的位置来确认优先级的,一般来说距离目标元素越近的CSS代码作用效力越大,因此,三者的优先级方式为:

同一样式:行间样式>页面级CSS>外部CSS

不同样式: 谁设置了听谁的

三、CSS权重

CSS权重其实英文直译过来不是权重,它的英文名是CSS Specificity(具体性,明确性),主要是为了在针对同一元素样式的多块CSS代码中找到最具体或者权重最高的那些代码,然后执行生效。在前面两节内容中,讨论了不同的选择器以及不同的CSS引入方式下的优先级(也就是我们这里所说的权重)的问题,但其实这些讨论都可以在本节用一个数值对应表格进行统一的量化。根据渡一教育的前端基础课(非广告,是尊重)中介绍,这个权重关系表是某一位工程师花了很长时间,一个一个测出来的,在不同的情况下,对应着不同的权值,需要注意的是,不同权值之间的进制关系是256进制,不是十进制,因此在进行权重计算的时候要注意。具体的对应关系如下:

/*取值: 2556进制*/

!important:                             Infinity;
行间样式:                                1000;
id选择器:                                100;
class选择器|属性选择器|伪类选择器:          10;
标签选择器|伪元素选择器:                    1;
通配符选择器:                              0
 

1. !important

!important在前面的介绍中都没有出现过,因此在这一部分进行一个简单的介绍。!important的使用比较简单,在CSS代码的属性设置行后面添加上即可,如:

div{
	width: 100px; 
	height: 100px;
	background-color: blue !important;
}

根据上面的对应关系,可以看到 !important的权值是Infinity无穷大,因此,在其他选择器或者引入方式权重相同时,若某个CSS样式后面设置了!important,则该属性必然生效。还有一个值得注意的事情是,不同于数学中的infinity+1=infinity,在CSS权重的计算中infinity+1>infinity,即在下列的代码中,虽然通配符选择器将页面中所有元素的背景颜色都设置成了蓝色,但是因为infinity+1>infinity,所以该div的背景颜色将是黄色。

div{
	width: 100px; 
	height: 100px;
	background-color: yellow !important;
}

*{
	background-color: blue !important;
}

2. 页面级CSS

可以发现,在上述的对应关系中,除了行间样式,另外两种CSS引入方式——页面级CSS和外部CSS并没有设置CSS权值。这是因为页面级CSS和外部CSS文件内容基本是一致的,只是放置的位置不同。对于HTML文件而言,不考虑优先级的情况下,页面级CSS中的选择器那些与外部CSS文件的选择器并没有什么不同。并且一般情况下,按照行业的分离开发的规则,并不推荐页面级CSS的引入方式,因此这里基本是讨论的外部CSS文件中的选择器。但如果不可避免地出现了页面级CSS与外部CSS并存的情况,那么对于被选中的同个元素,则还是按照先计算权重,再按页面级CSS>外部CSS的关系来选取。例如,在下面的例子中,如图8所示,div中的字体颜色将会变成绿色:

<!DOCTYPE html>
<html>
    <head>
	    <meta charset="utf-8">
	    <title>XXX</title>
	    <link rel="stylesheet" type="text/css" href="compare.css">
	    <style type="text/css">
		    #good{
			    color: green;
		    }
	    </style>
    </head>
    <body>
	    <div id="good">我是div,我的ID是good</div>
    </body>
</html>
#good{
	color: red;
	font-size: 30px;
}

 

图8 页面级CSS和外部CSS

3. CSS权重的叠加

CSS权重的叠加主要是针对父子选择器而言的,由于父级元素的选择形式多样,因此在选择某一个层数较深元素时,往往有多种选择方式。那么对于不同选择方式,因为选择器的权重不同,也会具有不同的权值。以下面的代码为例,用两种不同的方式来选择div中的a标签,设置a标签的样式,由于id选择器与标签选择器的权值和大于标签选择器与class选择器的权值和,因此,a标签的字体颜色应是紫色。

<div id="good">
	<a class="ref" href="#">超链接新样式</a>
</div>

 

div .ref{
	text-decoration: none;
	color: gray;
}

#good a{
	text-decoration: none;
	color: purple;
}
图9 CSS权重叠加

 

四、浏览器中父子选择器的遍历

浏览器中父子选择器的遍历是自右向左的。从前面的介绍来看,父子选择器并不是严格的父子关系,因此当要从一棵DOM树中定位到符合父子选择器的元素,如果自左向右遍历的话是需要遍历整棵树的,因为不遍历到最后并不知道后面还有没有可能出现相应的结构。而自右向左遍历首先从终点就可以减少一部分分支的遍历,并且随着倒退的顺序可以陆续避开一些分支,比从左至右要轻松一些。

自右向左遍历示意图
图10 自右向左遍历示意图

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值