css样式选择器
一、 CSS 选择符
类型选择符用于选择特定类型的元素,比如段落(见下面的例子)或标题元素,只要写出想要添加样式的元素名即可。类型选择符有时候也被称为元素选择符。
p {
color:black;
}
1
2
3
后代选择符用于选择某个或某组元素的后代。后代选择符的写法是在两个选择符之间添加空格。在下面的例子中,只有作为块引用后代的段落元素会被选中,从而缩进,其他段落都不会缩进。
blockquote p{
padding-left:2em;
}
1
2
3
类型选择符与后代选择符非常适合全面应用基础样式。
要想更精确地选择目标元素,可以使用ID选择符和类选择符。顾名思义,这两个选择符通过对应ID和class属性的值来选择元素。ID选择符由井号(#)开头,类选择符由句点(.)开头。下面例子中的第一条规则会把介绍性段落中的文字变成粗体,而第二条规则会把日期变成灰色。
#intro{
font-weight:bold;
}
.date-posted{
color:#ccc;
}
1
2
3
4
5
6
<p id="intro">Happy Birthday,Andy</p>
<p class="date-posted">20/1/2013</p>
1
2
1. 子选择符与同辈选择符
除了基本选择符,CSS也提供了高级选择符。第一个高级选择符叫子选择符。与后代选择符会选择一个元素的所有后代不同,子选择符只选择一个元素的直接后代,也就是子元素。在下面的例子中,外部列表中的列表项前面会出现自定义的图标,而嵌套列表中的列表项则不会受影响。
#nav > li{
background:url(folder.png)no-repeat left top;
padding-left:20px;
}
1
2
3
4
<ul id="nav">
<li><a href="/home/">Home</a></li>
<li><a href="/services/">Services</a>
<u1>
<li><a href="/services/design/">Design</a></li>
<li><a href="/services/development/">Development</a></li>
<li><a href="/services/consultancy/">Consultancy</a></li>
</u1>
</1i>
<li><a href="/contact/">Contact Us</a></li>
</u1>
1
2
3
4
5
6
7
8
9
10
11
有时候可能需要为与某个元素相邻的元素添加样式。使用相邻同辈选择符,就可以选择位于某个元素后面,并与该元素拥有共同父元素的元素。例如:
h2 + p{
font-size: 1.4em;
font-weight: bold;
co1or: #777;
}
1
2
3
4
5
<div>
<h2>
Peru Celebrates Guinea Pig festival
</h2>
<p>
The guinea pig festival in Peru is a one day event to celebrate these cute local animals.The festivalincluded a fashon show where animals are dressed up in various amusing costumes.
</p>
<p>
Guinea pigs can be fried,roasted or served in a casserole.Around 65 million guinea pigs are eaten in Perueach year.
</p>
</div>
1
2
3
4
5
6
7
8
9
10
11
> 和 + 在这里被称为组合子(combinator),因为它们描述了自身两侧的选择符组合的方式。在前面的例子中,我们看到了 > 子组合子和 + 相邻同辈组合子。实际上还有一个类似的组合子,那就是一般同辈组合子:~。仍以上面的例子来说明,使用一般同辈组合子可以选择h2元素后面的所有段落。
h2 ~ p{
font-size:1.4em;
font-weight:bold;
co1or:#777;
}
1
2
3
4
5
注意:
可能有人已经发现了,相邻同辈选择符和一般同辈选择符都不会选择前面的同辈元素具体来说,在前面的例子中,h2前面的段落都不会被选中。浏览器之所以不支持向前选择同辈元素,主要跟网页渲染性能有关。
通常情况下,浏览器会按照元素在页面中出现的先后次序给它们应用样式。在给h2前面的段落应用样式时,h2应该还不存在。这种情况下,如果有向前同辈组合子,浏览器就必须先记住相应的选择符,然后对文档进行多轮处理才能彻底应用样式。
已经有人提出了向前同辈选择符的建议,而且该建议正在被考虑采纳为标准。不过,目前的意见倾向于将其限制为CSS选择符的特殊用途,比如在JavaScript中求值。因此,即使浏览器支持了这种选择符,它也不一定是你想要的那样。
2. 通用选择符
通用选择符可以匹配任何元素。与其他语言中的通配符类似,通用选择符也使用星号(*)表示。也就是说,只用一个星号,就可以匹配页面中的所有元素。那么是否可以使用通用选择符来删除所有元素默认的内外边距:
* {
padding: 0;
margin: 0;
}
1
2
3
4
当然,通用选择符不仅限于给文档中的所有元素设置属性。你还可以把它与组合子结合使用,选择某个特定的嵌套层次,此时重要的是层次而不是元素类型。看下面这个例子:
.product-section > * {
/*·,·*/
}
1
2
3
这个组合选择符会选择带有类名product-section的元素的直接后代,不管它是什么元素,有什么属性。如果你想选择这些元素,同时又不想增加选择符的特殊性,这样就很好。后面会讲到选择符的特殊性。
3. 属性选择符
顾名思义,属性选择符基于元素是否有某个属性或者属性是否有某个值来选择元素。有了这种选择符,可以实现很多更有意思、更深人的选择。
比如,鼠标指针悬停在某个带有title属性的元素上时,多数浏览器都会显示一个提示条。利用这种行为,可以借助元素对某些缩写词给出详尽的解释:
<p>
The term
<abbr title="self-contained underwater breathing apparatus">
SCUBA
</abbr>
is an acronym rather than an abbreviation as it is pronounced as a word.
</p>
1
2
3
4
5
6
7
可是,如果不把鼠标放在这个元素上,谁也不知道它还会显示缩写词的解释。为此,可以使用属性选择符给带有title属性的abbr元素添加不同的样式,比如在缩写词下面加一条点划线。然后把悬停状态的鼠标指针改成问号,可以提供更多的上下文信息,让人注意到它的与众不同。
abbr[title]{
border-bottom: 1px dotted #999;
}
abbr[title]:hover{
cursor: help;
}
1
2
3
4
5
6
除了可以根据是否存在某个属性来选择元素,还可以根据特定的属性值来应用样式。比如:
让所有type属性值为submit的input元素在鼠标指针悬停时,都会显示一个手状光标。
input[type="submit"] {
cursor: pointer;
}
1
2
3
有时候,我们关心的是属性值是否匹配某个模式,而非某个特定值。这时候,通过给属性选择符中的等号前面加上特殊字符,就可以表达出想要匹配的值的形式了。
要匹配以某些字符开头的属性值,在等号前面加上插入符(^):
a[href^="http:"] {}
1
要匹配以某些字符结尾的属性值,在等号前面加上美元符号($):
img[src$=".jpg"] {}
1
要匹配包含某些字符的属性值,在等号前面加上星号(*):
a[href*="/about/"] {}
1
要匹配以空格分隔的字符串中的属性值(比如rel属性的值),在等号前面加上波浪号(~):
a[rel~=next] {}
1
还有一个属性选择符,可以选择开头是指定值或指定值后连着一个短划线的情况。要匹配这种情况,在等号前面加上竖线(|):
a[lang|=en] {}
1
这条规则可以匹配属性值en和en-us,暗示这个选择符很适合选择属性值中的语言代码,因为语言代码都是以短划线分隔的。理论上可以对一个class属性使用这个选择符,比如用来匹配message和message-error。但实际上这种用法不够灵活,万一以后message类前面又添加了别的类名,比如class=“box message”,这个选择符就会失效。
4. 伪元素
有时候我们想选择的页面区域不是通过元素来表示的,而我们也不想为此给页面添加额外的标记。CSS为这种情况提供了一些特殊选择符,叫作伪元素。
首先,可以使用 ::first-letter 伪元素来选择一段文本的第一个字符。若要选择一段文本的第一行,可以使用 ::first-line。
此外,还有伪元素对应着内容开头和末尾处假想的元素,分别是 ::before和 ::after。这两个伪元素非常适合用来插入小图标及版面装饰符号。怎么插人呢?就是通过content属性以文本形式插入。插入内容后,给伪元素添加样式就跟给其他元素添加一样,比如背景、边框等,都没问题。
<h1>A Study In Scarlet</h1>
<section class="chapter">
<p>
In the year 1878 I took my degree of Doctor of Medicine of the University of London, and proceeded to Netley to go through the course prescribed for surgeons in the army.Having completed my studies there,I was duly attached to the Fifth Northumberland Fusiliers as Assistant Surgeon.
</p>
</section>
1
2
3
4
5
6
.chapter::before{
content: '"'
font-size: 15em;
}
.chapter p::first-letter{
float: left;
font-size: 3em;
font-family: Georgia,Times,"Times New Roman",serif;
}
.chapter p::first-line{
font-family: Georgia,Times,"Times New Roman",serif;
text-transform: uppercase;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
注意单标签添加伪元素将无效,因为单标签无法容纳子元素。
5. 伪类
有时候,我们想基于文档结构以外的情形来为页面添加样式,比如基于超链接或表单元素的状态。这时候就可以使用伪类选择符。伪类选择符的语法是以一个冒号开头,用于选择元素的特定状态或关系。
一些最常见的用于超链接的伪类列举如下。
/*未访问过的链接为蓝色*/
a:link{
color:blue;
}
/*访问过的链接为绿色*/
a:visited{
color:green;
}
/*链接在鼠标悬停及获取键盘焦点时为红色*/
a:hover,
a:focus{
color:red;
}
/*活动状态时为紫色*/
a:active{
color:purple;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
以上伪类的先后次序很重要。:link和:visited应该排在前面,然后才是与用户交互相关的那些。这样一来,当用户鼠标悬停在链接上,或者链接获得键盘焦点时,:hover和:focus规则会覆盖:link和:hover规则。最后,当鼠标点击或键盘回车选择链接时,应用:active规则。链接作为交互元素,默认可以获得焦点以及被激活。除链接之外,表单字段和按钮也是交互元素,因此这些伪类也适用于它们。还可以使用JavaScript把其他元素变成交互元素。
最后,其实很多元素都可以使用:hover。但要注意的是,在触摸屏和键盘等输入方式下不一定真的有悬停状态。因此,不要在重要的交互功能中使用:hover。
另一个有用的伪类是:target,它匹配的元素有一个ID属性,而且该属性的值出现在当前页面URL末尾的井号(#)后边。如果我们打开链接http://example…com/blog1/#comment-3,找到该页面中标记为<article class="comment"id=“comment-3”>…</article>的评论,那么可以通过以下规则高亮该条评论:
.comment:target{
background-color:#fffec4;
}
1
2
3
现在,假设我想高亮一条评论,而该评论不是因投票否决而被隐藏的。好,也有一个选择符专门用于排除某些选择符:它就是反选(negation)伪类,或者:not()选择符。如果被标记为“投票否决”(downvoted)的评论都有一个特殊的类名,那么就可以像下面这样来改写规则:
.comment:target:not(.comment-downvoted){
background-color:#fffec4;
}
1
2
3
反选伪类可以配合各种放到括号中的选择符使用,不过伪元素和它自身除外。
6. 结构化伪类
CSS3新增了一大批与文档结构有关的新伪类。其中最常用的是nth-child选择符,可以用来交替地为表格行应用样式:
/*将表格奇数行背景设为黄色*/
tr:nth-child(odd){
background:yellow;
}
1
2
3
4
它可以接受odd(奇数)和even(偶数)作为参数。这个参数还可以是数值,表示目标元素的序数位置,比如下面这个例子会将所有表格的第3行设置为粗体:
tr:nth-child(3){
font-weight:bold;
}
1
2
3
如果这个参数是数值表达式,情况就会复杂一点。比如:
/*n从0开始,直到不再有元素匹配为止*/
tr:nth-child(3n+4){
background:#ddd;
}
1
2
3
4
还有一个伪类选择符也支持这种表达式,比如:
:nth-last-child(N) {}
1
:nth-last-child选择符与:nth-child选择符类似,只不过是从最后一个元素倒序计算(而不是从第一个元素正序计算)。
CSS2.1中有一个选择第一个子元素的伪元素,叫:first-child,相当于直观版的:nth-child(1)。CSS3选择符规范又添加了一个选择最后一个子元素的伪元素,没错,叫:last-child,对应于:nth-last-child(1)。
此外,还有:only-child和:only-of-type。其中,:only-of-type会选择特定类型的唯一子元素。使用下列伪类选择符,则可以实现更高级的选择:
:nth-of-type(N)
:nth-last-of-type(N)
1
2
这两个伪类选择符与:nth-child选择符相似,只不过会忽略非指定类型的元素。有了这些伪类选择符,我们可以创造性地运用很多高效模式,而不必让选择符与标记过于紧密地耦合。
7. 表单伪类
还有很多伪类专门用于选择表单元素。这些伪类根据用户与表单控件交互的方式,来反映表单控件的某种状态。
如果想输入框表示必填,可以使用:require伪类:
<label for="field-name">Name:</label>
<input type="text" name="field-name" id="field-name" required>
1
2
input:required{
outline:2px solid #000;
}
1
2
3
类似地,可以像下面这样使用:optional伪类,为没有添加required属性的控件添加样式:
input:optional{
border-color:#ccc;
}
1
2
3
此外,还有针对有效和无效控件的伪类。为满足某个输人框要求填写特定类型内容(如电子邮件地址)的需求,HTML5也为type属性新增了不少输人值,比如email:
<input type="email" />
1
然后,可以根据输入框中当前内容的有效性,应用不同的样式:
/*如果输入框中色含有效的电子邮件地址*/
input[type="email"]:valid{
border-color:green;
}
/*如果输入框中的内容不是有效的电子邮件地址*/
input[type="email"]:invalid{
border-color:red;
}
1
2
3
4
5
6
7
8
除此之外,还有针对type值为number的:in-range、:out-of-range伪类,针对readonly属性的:read-only伪类,以及针对没有readonly属性的:read-write伪类。
二、层叠
稍微复杂的样式表中都可能存在两条甚至多条规则同时选择一个元素的情况。CSS通过一种叫作层叠(cascade)的机制来处理这种冲突。从CSS这个名字就可知这种机制有多重要,因为其中的C就是cascade(SS是style sheet,.即样式表)。层叠机制的原理是为规则赋予不同的重要程度。最重要的是作者样式表,即由网站开发者所写的样式。其次是用户样式表,用户可以通过浏览器的设置选项,为网页应用自己的样式。排在最后的是浏览器(或用户代码)的默认样式表,它们一般都会被作者样式表覆盖掉。为了给用户更高的优先权,CSS允许用户使用!important覆盖任何规则,包括网站作者使用!important标注的规则。!important标注要放在属性声明的后面:
p{
font-size: 1.5em !important;
color: #666 !important;
}
1
2
3
4
允许用户使用!important标注来覆盖规则,主要是出于无障碍交互的需要。比如,允许诵读困难的用户使用高对比度的用户样式表。归纳起来,层叠机制的重要性级别从高到底如下所示:
标注为!important的用户样式:
标注为!important的作者样式;
作者样式:
用户样式:
浏览器(或用户代码)的默认样式。
在此基础上,规则再按选择符的特殊性排序。特殊性高的选择符会覆盖特殊性低的选择符。如果两条规则的特殊性相等,则后定义的规则优先。
三、特殊性
为了量化规则的特殊性,每种选择符都对应着一个数值。这样,一条规则的特殊性就表示为其每个选择符的累加数值。但这里的累加计算使用的并非我们熟悉的十进制加法,而是基于位置累加,以保证10个类选择符(或者40个,甚至更多的类选择符)累加的特殊性不会大于等于1个ID选择符的特殊性。
任何选择符的特殊性都对应于如下4个级别,即a、b、c、d:
行内样式,a为1;
b等于ID选择符的数目;
c等于类(class)选择符、伪类选择符及属性选择符的数目;
d等于类型(type)选择符和伪元素选择符的数目。
根据以上规则,可以计算出任意CSS选择符的特殊性。下表给出了一些选择符,以及它们所对应的特殊性级别。
选择符 特殊性 十进制特殊性
style=" " 1,0,0,0 1000
#wrapper #content {} 0,2,0,0 200
#content .datePosted {} 0,1,1,0 110
div #content {} 0,1,0,1 101
#content {} 0,1,0,0 100
p .comment .datePosted {} 0,0,2,1 21
p .comment {} 0,0,1,1 11
div p {} 0,0,0,2 2
p {} 0,0,0,1 1
* {} 0,0,0,0 0
如果样式表写在了元素的style属性里,那么这些样式的特殊性就最高。然后,通过ID属性应用的规则,其特殊性高于未通过ID属性应用的规则。同理,通过类选择符应用的规则,其特殊性高于只通过类型选择符应用的规则。最后,如果两条规则拥有相等的特殊性,则优先应用后定义的规则,也就是层叠机制。
1. 利用层叠次序
如果两条规则特殊性相等,则优先应用后定义的规则,这一点非常重要。这意味着我们在写样式的时候,必须考虑规则在样式中的位置,以及选择符的次序。
前面介绍的对链接元素使用伪类的例子,就是一个利用层叠次序的典型。如果每个选择符的特殊性都一样,那么它们的次序就很重要了。要是把a:visited选择符放在a:hover选择符后面,那么在访问过链接之后,悬停样式将不会起作用,因为已经被a:visited样式给覆盖了。如果没有真正理解特殊性和层叠机制,可能就无法理解以上问题。关于链接伪类的次序,只要记住这句英文,“Lord Vader Hates Furry Animals”。这样,你就会记住正确的顺序一:link、:visited、:hover、:focus和:active。
四、继承
有些属性,像颜色或字体大小,会被应用它们的元素的后代所继承。比如,我把body元素的文本颜色设置为黑色,那么body所有后代元素的文本颜色都会继承这个黑色。字号也一样。任何直接应用给元素的样式都会覆盖继承的样式,因为继承的样式没有任何特殊性。
继承是很有用的机制,有了它就可以避免给一个元素的所有后代重复应用相同的样式。如果你要设置的属性是一个可继承属性,那么应该考虑是否直接设置到父元素上。毕竞,如果你这么写就行:
body {color: black;}
1
那为什么还要写成下面这样呢?
p,div,hi,h2,h3,ul,ol,dl,li {color: black;}
1
继承的属性值没有任何特殊性,连0都说不上。这意味着使用特殊性为0的通用选择符设置的样式都可以覆盖继承的样式。为此我们可能会遇到“意料之外”的情况,表面上看em会继承h2的红色,但通用选择符给所有元素设置的黑色会覆盖它所继承的红色:
*{
color:black;
}
h2{
color:red;
}
1
2
3
4
5
6
<h2>The emphasized text will be <em>black</em></h2>
1
五、为文档应用样式
1. link 与 style 元素
首先,可以把样式放在style元素中,直接放在文档的head部分:
<style>
body{
font-family:Avenir Next,SegoeUI,sans-serif;
color:greyi
}
</style>
1
2
3
4
5
6
如果样式不多,你又希望立刻应用它们,并且不愿意因为浏览器额外下载文件而耽误时间,那么可以使用这种方法。不过,为了让样式表能在多个页面中重用,通常最好把它保存到一个外部文件中。
如果样式在外部样式表中,那么有两种方式把它们挂接到网页上。最常用的方式是使用link元素:
<link href="/c/base.css" rel="stylesheet"/>
1
这行代码告诉浏览器把base.css文件下载下来,然后把其中的样式应用到网页上。同样的代码可以把这个样式表应用到任意多个网页上,因此这是一种跨网页甚至跨网站重用样式的推荐方式。
除了link元素,还可以使用@import指令加载外部CSS文件:
<style>
@import url("/c/modules.css");
</style>
1
2
3
可以在HTML文档的head部分把@import指令放在style中,也可以在外部样式表中使用它。后一种用法意味着,如果网页加载外部样式表,那么浏览器后续可能还需要下载更多CSS文件。
向页面中添加样式表的时候,别忘了层叠机制的原理是次序决定优先级:如果为某个元素应用样式时,有两个或更多特殊性相等的规则互相竞争,则后声明的样式胜出。使用link或style在HTML中添加多个样式表或样式块时,它们声明的次序就是它们在HTML源代码中出现的次序。
2. 性能
选择以什么方式把CSS加载到页面中,决定了浏览器显示页面的速度(假设加载HTML页面本身很快)
度量Web性能的一个重要指标就是网页内容实际显示在屏幕上需要多久。这个指标有时候也叫“渲染时间”或“上屏时间”。
现代浏览器在屏幕上渲染内容之前,至少需要两样东西:HTML和CSS。这意味着让浏览器尽快下载HTML和全部CSS极其重要。不要把CSS放到body里或者放到页面底部,搞什么“延迟加载”。浏览器只有掌握了布局页面的全部CSS信息,才能给出最佳响应。因为只有这样,它们才知道应该把页面谊染成什么样,从而一次性地把页面绘制到屏幕上,而非一边加载新样式一边重新调整页面。
(1) 减少HTTP请求
在链接外部样式表时,保证链接的文件数量最少至关重要,因为每个文件都需要单独发送次HTTP请求。相应地,每次从服务器请求文件,浏览器都需要花一定的时间下载,然后还要花时间应用其中的样式。
线上网页最好把需要加载的CSS文件数量控制在1或2个。只用一个link元索加载CSS文件,然后在其中使用@1m即ort,并不能把请求控制为1个,因为这意味着先需要1个请求下载链接的文件,此外还要发送额外的请求取得所有导人的文件。因此,在线上网页中尽量不要使用@import
(2) 压缩和缓存内容
使用GZIP压缩线上资源也非常重要。CSS压缩的比率很高,因为它的很多属性和值都是重复的。一般来说,CSS文件压缩后会减少70%~80%。这样显然可以减少带宽占用,从而为用户节省时间。多数Wb服务器都会在浏览器支持的情况下启用自动压缩线上资源。
类似地,让Web服务器帮你设置一定的CSS文件缓存时间也很重要。理想情况下,浏览器应该只下载一次CSS文件,除非线上文件有变化。方法就是通过HTTP首部告诉浏览器,把文件缓存较长的一段时间。
(3) 不要让浏览器渲染阻塞 JavaScript
如果你在HTML文档的<head>元素中加入了<script>元素,浏览器必须先把它链接的脚本下载下来,然后再向用户显示网页内容。换句话说,这种情况下的HTML和CSS解析完全被下载以及执行脚本阻断了,也就是所谓的“渲染阻塞”。渲染阻塞会明显拖慢网站加载速度。为此,主流的做法是在HTML页面底部的结束标签</body>之前加载JavaScript:
<body>
<!--最后加载JavaScr1pt-->
<script src="/scripts/core.js"></script>
</body>
1
2
3
4
比较现代的做法是在<head>中使用<script>标签,但添加async和defer属性。给<script> 标签加上asyc属性,会异步加载脚本,不阻塞HTML解析,但会在脚本加载完毕后立即执行,阻断 HTML解析。给<script>标签加上defer属性,同样会异步加载脚本,不同的是会在HTML解析完毕后再执行加载的脚本。这两个属性该用哪一个,还要看脚本本身的具体内容。
<head>
<!--异步加载,但下载后立即执行-->
<script src="/scripts/core.js"async></script>
<!--异步加载,但在HTML解析后执行-->
<script src="/scripts/deferred.js"defer></script>
</head>
————————————————
版权声明:本文为CSDN博主「想睡觉的小郑」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_36973122/article/details/126335137