最近在重新学习CSS相关的知识,在这里进行一下归纳总结吧
1.基础选择器
·元素选择器
元素选择器能够根据标签名来选择指定的元素,基本语法像下面这样:
标签名 {样式}
举个例子:
<div>这是div</div>
<p>这是p标签 </p>
div {
background-color: #bfa;
}
p {
background-color: yellow;
}
这样我们就能为所有使用该标签的元素指定样式,但同样缺点也相当明显,当对同一类标签想要设定差异化的样式时,光靠元素选择器就做不到了
·类选择器和id选择器
这两类选择器的作用相似,都是用于给具有特殊标识(id或class属性)的标签绑定样式,不同的是id一般具有唯一性,而class能够绑定给一类具有相似属性的标签
id选择器: #id {样式}
类选择器: .className {样式}
一个标签可以绑定多个class属性,每个属性用空格隔开,而同一个class也可以绑定给多个标签,如下面的例子:
<div id="id_demo" class="class_demo1 class_demo2">这是div1</div>
<div class="class_demo2">这是div2</div>
#id_demo {
background-color: #bfa;
height: 100px;
}
.class_demo1 {
color: red;
}
.class_demo2 {
background-color: yellow;
height: 100px;
}
这类选择器让我们能够方便的为特定的标签绑定特定的样式,同样也有利于样式的复用
·通配选择器
在一些情况下我们需要给整个页面设置一些通用的样式,通配选择器能帮我们实现这样的需求,它能选中页面中所有类型的标签
*{样式}
下面的例子中通过通配选择器将页面所有标签的字体颜色改为skyblue
<div >这是div1</div>
<div>这是div2
<span>这是div2中嵌套的span</span>
</div>
<p>这是p标签</p>
* {
color: skyblue;
font-size: 30px;
}
2.复合选择器
在实际的应用场景中,往往我们会将多个选择器组合使用,这就需要使用到复合选择器
·交集选择器
这类选择器选择的是同时符合多个选择器条件的元素,类似于逻辑与&&,语法如下
选择器1选择器2选择器3选择器n {样式}
·并集选择器
相对于交集选择器,类似于逻辑或||,当只需满足多个条件中的一个就被选中时,我们可以使用并集选择器,也可以称它为选择器分组
选择器1,选择器2,选择器3,选择器n {样式}
同样来看下面的例子:
<div class="demo1">这是div1</div>
<div>这是div2
<span class="demo2">这是div2中嵌套的span</span>
</div>
<p class="demo1">这是p标签</p>
div.demo1 {
color: red;
}
p,.demo2 {
color: skyblue;
}
只有符合交集选择器的所有判定条件的元素才会被选中,例子中的p标签因为没有满足div的条件没有被选中,而满足并集选择器任意条件的元素都会被选中
3.关系选择器
在实际场景中,html标签往往会出现嵌套的情况,这种嵌套形成了父元素与子元素,祖先元素与后代元素等等特殊的关系,而关系选择器正是利用了这种特殊的关系来为我们的编码提供便利
·子元素选择器
这类选择器能够选中指定父元素的指定子元素,语法如下:
父元素 > 子元素 {样式}
例如如下的页面结构:
<div>这是div
<span>这是div中嵌套的span</span>
</div>
<span>这是span</span>
我们要为div的子元素span设置一个字体颜色红色,通过子元素选择器的实现十分方便:
div > span {
color: red;
}
·后代选择器
除了父与子之外,祖先与后代的关系也是常见的,后代选择器正是基于这一关系,它能够选中选中指定元素内的指定后代元素,语法如下:
祖先 后代 {样式}
同样来举个例子,对于如下结构:
<div id="demo">
<div>
<span>这是div中嵌套的span</span>
</div>
</div>
需求同样是将span中的字体颜色设置为红色,span与外层div间不存在父子关系,子元素选择器不再适用,这里可以使用后代选择器来实现:
#demo span {
color: red;
}
·兄弟选择器
嵌套的标签之中还有如下的结构:
<div>
<span id="first">这是div中嵌套的span1</span>
<span id="second">这是div中嵌套的span2</span>
<span>这是div中嵌套的span3</span>
<span>这是div中嵌套的span4</span>
</div>
这里的4个span标签同为外部div的子元素,我们称它们为兄弟元素,通过兄弟选择器能方便的选中兄弟元素,语法如下:
选择下一个兄弟:前一个 + 下一个 {样式}
选择下边所有的兄弟: 兄 ~ 弟 {样式}
下面的例子我们实现这样一种效果,将第二个span的字体设置为红色,将后两个span的字体设置为绿色
#first + span {
color: red;
}
#second ~ span {
color: green;
}
通过两种兄弟选择器来进行实现非常方便
4.属性选择器
html的标签能够绑定一些额外的属性,如title属性,属性选择器能够通过这些属性来选中元素,语法如下:
[属性名] 选择含有指定属性的元素
[属性名=属性值] 选择含有指定属性和属性值的元素
[属性名^=属性值] 选择属性值以指定值开头的元素
[属性名$=属性值] 选择属性值以指定值结尾的元素
[属性名*=属性值] 选择属性值中含有某值的元素的元素
同样来举个例子:
<p title="abcdef">杨花落尽子规啼</p>
<p title="fedabc">闻道龙标过五溪</p>
<p title="adssbfc">我寄愁心与明月</p>
<p>随风直到夜郎西</p>
/*改变title属性值为abcdef的标签的字体大小 */
p[title="abcdef"] {
font-size: 20px;
}
/*含有title属性的标签字体加粗 */
p[title] {
font-weight: bold;
}
/*title属性以abc开头的标签字体设置为红色 */
p[title^="abc"] {
color: red;
}
/*title属性以abc结尾的标签字体设置为绿色 */
p[title$="abc"] {
color: green;
}
/*title属性中含有ss的标签字体设置为天蓝 */
p[title*="ss"] {
color: skyblue;
}
5.伪类选择器
伪类是一种我们为方便描述元素的某些特殊状态而虚构出来的类,它并不作为真正的类而存在,这些特殊状态可以是第一个子元素、被点击的元素、鼠标移入的元素等,伪类通常以:开头,这里列举一些常用的伪类,更详细的情况可参考官方文档
下面这一组伪类用于选中指定父元素的所有子元素中的某些元素
:first-child 第一个子元素
:last-child 最后一个子元素
:nth-child(n) 选中第n个子元素
参数的特殊值:
n 第n个 n的范围0到正无穷
2n 或 even 表示选中偶数位的元素
2n+1 或 odd 表示选中奇数位的元素
还有一组功能相似的伪类,它们用来选中指定父元素的指定类型子元素中的某些元素
:first-of-type
:last-of-type
:nth-of-type(n)
例如下面这个例子:
<ul>
<span>我是一个span</span>
<li>第零个</li>
<li>第一个</li>
<li>第二个</li>
<li>第三个</li>
<li>第四个</li>
<li>第五个</li>
</ul>
分别使用上述两种伪类
ul > li:first-child {
color: red;
}
这里样式没有生效是因为:first-child对所有子元素排序,而第一个子元素并非是li
ul > li:first-of-type {
color: red;
}
这里:first-of-type只对li元素进行排序,所以第一个li元素样式生效
还有一种特殊的伪类称为否定伪类:
:not() 这是否定伪类,它的作用是将符合条件的元素从选择器中去除,括号内传入选择器
同样是上面的例子,我们来体验一下否定伪类
/*将除第一个外的所有排列在奇数位置的li的字体设置为红色*/
ul > li:nth-of-type(2n+1):not(li:first-of-type) {
color: red;
}
还有一些和a标签相关的伪类,在CSS1的老版本中这些伪类只能用于a标签,但CSS2后允许对任意元素使用这些伪类,但通常a标签用得较多
:link //选择未访问的元素
:visited//选择访问过的元素,由于隐私问题该伪类只能修改color属性,其他样式的修改不生效
:hover//选择鼠标悬浮的元素
:active//选择鼠标正在点击的元素
6.伪元素选择器
类似于伪类,伪元素并不是页面中真实存在的元素,而是代表一些特殊位置的元素,常以::开头,常用伪元素选择器如下:
::first-letter //表示第一个字母
::first-line //表示第一行
::selection //表示选中的内容
::before //元素的开始
::after //元素的最后
其中::before和::after必须结合content属性使用,如下面这个例子:
<ul>
<li>第零个</li>
<li>第一个</li>
<li>第二个</li>
<li>第三个</li>
<li>第四个</li>
<li>第五个</li>
</ul>
/*在每个li前添加'我是'*/
li::before {
content: "我是";
}
7.选择器权重
当我们通过不同的选择器对选中同一元素指定样式时,会发生样式的冲突问题,当冲突发生时到底应用哪个选择器指定的样式由选择器的权重来决定
通常来说我们按照如下的权重来排列:
内联样式 > id选择器 > 类和伪类选择器 > 元素和伪元素选择器 > 通配选择器 > 继承的样式
但这样的划分并不细致,当选择器叠加时,权重的计算方法也并不明确,这里介绍一下权重的具体计算方法
首先我们用(a,b,c,d)这样的格式来表示选择器的权重,4个字母分别代表了4种权重的数量级,其中a的值表示内联样式的数量,即每有一个内联样式则a的值加1,同理b的值表示id选择器的个数,c的值代表类和伪类选择器的数量,d的值代表元素和伪元素选择器的数量,通配选择器权重为0,继承的样式不存在优先级,也不会参与权重的计算
在明确权重分配后,我们再来看权重的叠加,首先明确一点,权重的叠加只存在于交集的情况中(并集选择器中的每个选择器单独计算其权重),在计算时需要将所有选择器的权重相加,权重大的选择器优先级更高,但是选择器的累加不会突破其所在的数量级,即id选择器的数量再多,权重中b的值再大也不能超过内联样式的权重值,内联样式的优先级依然更高。
举个例子,有如下两个选择器指向同一个元素,且该元素还设有一个内联样式:
1. div > #id_demo > ul > li:first-child > a
2. div > div > .list > li > .title > .link
此时选择器1中无内联样式,所以a的值为0,id选择器一个,所以b=1,伪类选择器一个有c=1,元素选择器4个即d=4,所以该选择器的权重为(0,1,1,4)
同理选择器2的权重计算可得为(0,0,3,3),比较两个选择器的权重,虽然选择器2的c=3比选择器1的c值更大,但因权重累加不会突破数量级,而选择器1的b值更大,所以选择器1的优先级更高,但该元素还设有一个内联样式,其权重值为(1,0,0,0),大于选择器1的权重值,所以最后生效的是内联样式
所以我们可以总结出权重值的比较规则:根据权重值从左往右依次进行比较 ,值较大者权高,如果相等,则继续往右移动一位进行比较
那么问题又来了若两个选择器权重值完全相等时谁生效呢?答案是两个都会生效,但是写在下面的样式会覆盖掉之前的样式
·特殊情况
经过上面的计算我们知道了内联样式具有最高的优先级,外部样式再怎么累加权重也不可能超过内联样式的优先级,那么在设置了内联样式的情况下我们就没有办法让外部样式生效了吗?
方法当然是有的,看下面这个例子:
<div style="color:red">我爱学前端</div>
在该div中设置了一个内联样式使其字体颜色为红色,我们再给它一个外部样式同样改变其字体颜色
div {
color: blue;
}
通过上面的学习我们已经知道外部样式的权重低不会生效,所以该div显示的应是红色字体
我们改变一下外部样式
div {
color: blue!important;
}
结果它就生效了,没错关键就是这个!important,它能让修饰的样式越过权重计算直接获得超越内联样式的最高优先级
所以对于!important在开发中能不用就不用,因为它打破了css框架所制定的优先级规则,使调试bug变得困难