CSS选择器的基础使用方法,未经作者许可

作者: 前端  发布:2019-11-09

组合选择器

你可以有一个标准的选择器比如 #nav,来选择任何带有ID为”nav”的元素,或在你可以有一个组合选择器比如#nav a,来选择任何在ID为’nav’的元素里面的链接元素

此刻,我们读这些是从左到右的方式。我们是先找到#nav,然后从它的里面找其他元素。但是浏览器解析这些不是这样的:浏览器解析选择器是从右到左的方式。

在我们看来,#nav里面带了一个a,浏览器却是看到的a在#nav里面。这些细微的差异对选择器的效率有很大的影响,同时学这些差异也是很有价值的。

如果想要知道更多浏览器这样解析的原因,请看Stack Overflow上的讨论

浏览器从最右边的元素开始(它想要渲染的元素),然后用它的方式回溯DOM树比从DOM树的最高层开始选择向下寻找,甚至可能达不到最右边的选择器—关键的选择器要高效。

这些对CSS选择器的效率有很大的影响。

这就是为什么我对选择器的性能如此感兴趣的原因了:必须在web 标准最佳实践和速度之间的保持平衡。

法二:<input type="radio"> && <label for="">

上面的方法通过添加 <a> 标签添加页面锚点的方式接收点击事件。

这里还有一种方式能够接收到点击事件,就是拥有 checked 属性的表单元素, <input type="radio"> 或者<input type="checkbox"> 。

假设有这样的结构:

XHTML

<input class="nav1" type="radio">   <ul class='nav'>     <li>列表1</li> </ul>

1
2
3
4
5
<input class="nav1" type="radio">
 
<ul class='nav'>
    <li>列表1</li>
</ul>

对于上面的结构,当我们点击 <input class="nav1" type="radio"> 单选框表单元素的时候,使用 :checked是可以捕获到点击事件的。

CSS

.nav1:checked ~ .nav li {   // 进行样式操作 }

1
2
3
.nav1:checked ~ .nav li {
  // 进行样式操作
}

同样用到了兄弟选择符 ~

这样,当接收到表单元素的点击事件时,可以通过兄弟选择符 ~ 操作它的兄弟元素的样式。

可以试着点击下面 codepen 中的单选框。

See the Pen radio box by Chokcoco (@Chokcoco) on CodePen.

但是,这里有个问题 我们的 Tab 切换,要点击的是<li>元素,而不是表单元素,所以这里很重要的一点是,使用 <label for=""> 绑定表单元素。看看如下结构:

XHTML

<input class="nav1" id="li1" type="radio">   <ul class='nav'>     <li><label for="li1">列表1</label></li> </ul>

1
2
3
4
5
<input class="nav1" id="li1" type="radio">
 
<ul class='nav'>
    <li><label for="li1">列表1</label></li>
</ul>

通过使用 <label> 包裹一个 <li> 元素,而 <label> 有一个属性 for 可以绑定一个表单元素。

上面的 <li> 中,有一层 <label for="li"> ,里面的 for="li1" 意思是绑定 id 为li1 的表单元素。

label 标签中的 for 定义:for 属性规定 label 与哪个表单元素绑定。

这样改造之后,当我们点击 <li> 元素的时候,相当于点击了 <input class="nav1" id="li1" type="radio">这个单选框表单元素,而这个表单元素被点击选中的时候,又可以被 :checked 伪类捕获到。

这个时候,我们就可以将页面上的表单元素隐藏,做到点击 <li> 相当于点击表单:

CSS

input{     display:none; }

1
2
3
input{
    display:none;
}

这样,应用到本题目,我们应该建立如下 DOM 结构:

XHTML

<div class="container">     <input class="nav1" id="li1" type="radio" name="nav">     <input class="nav2" id="li2" type="radio" name="nav">     <ul class='nav'>         <li class='active'><label for="li1">列表1</label></li>         <li><label for="li2">列表2</label></li>     </ul>     <div class="content">         <div class="content1">列表1内容:123456</div>         <div class="content1">列表2内容:abcdefgkijkl</div>     </div> </div>

1
2
3
4
5
6
7
8
9
10
11
12
<div class="container">
    <input class="nav1" id="li1" type="radio" name="nav">
    <input class="nav2" id="li2" type="radio" name="nav">
    <ul class='nav'>
        <li class='active'><label for="li1">列表1</label></li>
        <li><label for="li2">列表2</label></li>
    </ul>
    <div class="content">
        <div class="content1">列表1内容:123456</div>
        <div class="content1">列表2内容:abcdefgkijkl</div>
    </div>
</div>

使用两个单选框,分别对应两个导航选项,运用上面介绍的 label 绑定表单,:checked 接收点击事件,可以得到第二解法。

看看最后的结果:

Demo戳我:纯CSS导航切换(label 绑定 input:radio && ~)

See the Pen 纯CSS导航切换(label 绑定 input:radio && ~) by Chokcoco (@Chokcoco) on CodePen.

所有题目汇总在我的 Github ,发到博客希望得到更多的交流。

到此本文结束,如果还有什么疑问或者建议,可以多多交流,原创文章,文笔有限,才疏学浅,文中若有不正之处,万望告知。

打赏支持我写出更多好文章,谢谢!

打赏作者

伪元素选择器

选择器 描述 版本
E::first-letter 选择文本块的第一个字母 3
E::first-line 选择元素的第一行 3
E::before 在元素前面插入内容,配合”content”使用 3
E::after 在元素后面插入内容,配合”content”使用 3
E::selection 设置对象被选择时的样式 3

关键选择器

关键选择器,正如前面讨论的一样,是一个复杂的CSS选择器中最右边部分。它是浏览器最先寻找的。

现在我们回到讨论开始的地方,哪类选择器是最高效的?哪个是会影响选择器效率的关键选择器;写CSS代码的时候,关键选择器是能否高效的决定因素。 一个关键CSS选择器像这样:

CSS

#content .intro {..}

1
#content .intro {..}

是不是高效选择器比如类选择器天生就高效?浏览器会寻找.intro的实例(可能会很多),然后沿着DOM树向上查找,确定刚才找到的实例是否在一个带有ID为”content”的容器里面。

但是,下面的选择器就表现的不是那么好了:

CSS

#content * {..}

1
#content * {..}

这个选择器所做的是选择所有在页面上的单个元素(是每个单个的元素),然后去看看它们是否有一个 #content 的父元素。这是一个非常不高效选择器因为它的关键选择器执行开销太大了。

运用这些知识我们就可以在分类和选择元素的时候做出更好的选择。

假设你有一个复杂的页面,它相当巨大并且在你的一个很大很大的站点上。在那个页面上有成百上千甚至上万的 a 标签。它还有一个小的社交链接区域放在一个ID为#social的Ul里面。我们假设它们是Twitter,Facebook,Dribbble还有 Google+的链接吧。在这个页面上我们有四个社交链接和成百上千的其他链接。 下面的这个选择器就自然的不是那么高效和合理了:

CSS

#social a {…}

1
#social a {…}

这里发生的情况是浏览器会在定位到#social区域下的四个链接之前得到页面上所有成千上万的链接。我们的关键选择器匹配了太多我们不感兴趣的其他元素。

为了补救我们可以给每个在社交链接区域的 a 增加一个更特殊、明确的选择器 .social-link , 但是这好像有点违背我们的认知:当我们能用组合选择器的时候就不要放不必要的类标示在元素上。

这就是为什么我对选择器的性能如此感兴趣的原因了:必须在web 标准最佳实践和速度之间的保持平衡。

通常我们有:

CSS

<ul id="social"> <li><a href="#" class="twitter">Twitter</a></li> <li><a href="#" class="facebook">Facebook</a></li> <li><a href="#" class="dribble">Dribbble</a></li> <li><a href="#" class="gplus">Google+</a></li> </ul>

1
2
3
4
5
6
<ul id="social">
    <li><a href="#" class="twitter">Twitter</a></li>
    <li><a href="#" class="facebook">Facebook</a></li>
    <li><a href="#" class="dribble">Dribbble</a></li>
    <li><a href="#" class="gplus">Google+</a></li>
</ul>

CSS:

CSS

#social a {}

1
#social a {}

我们现在最好有:

XHTML

<ul id="social"> <li><a href="#" class="social-link twitter">Twitter</a></li> <li><a href="#" class="social-link facebook">Facebook</a></li> <li><a href="#" class="social-link dribble">Dribbble</a></li> <li><a href="#" class="social-link gplus">Google+</a></li> </ul>

1
2
3
4
5
6
<ul id="social">
    <li><a href="#" class="social-link twitter">Twitter</a></li>
    <li><a href="#" class="social-link facebook">Facebook</a></li>
    <li><a href="#" class="social-link dribble">Dribbble</a></li>
    <li><a href="#" class="social-link gplus">Google+</a></li>
</ul>

加上CSS:

CSS

#social .social-link {}

1
#social .social-link {}

这个新的关键选择器将会匹配更少的元素,这意味着浏览器能够很快的找到它们并渲染特定的样式,然后专注于下一件事。

另外,事实上我们可以用.social-link{}更清晰的选择,而不是过分限制它。阅读下一部分你会原因…

简单的重述一次,你的关键选择器会决定浏览器的工作量,因此,我们应该重视一下关键选择器

</``ul``>

关于作者:chokcoco

图片 1

经不住流年似水,逃不过此间少年。 个人主页 · 我的文章 · 63 ·    

图片 2

E:first-line 失效

如果在当前选择器内使用了 !important , :first-line 伪类内部的定义的属性会被完全忽略,示例:

CSS

p { color:blue; } p:first-line { color:red !important; }

1
2
3
4
5
6
p {
    color:blue;
}
p:first-line {
    color:red !important;
}

 

<p>第一行文字,<br/>第二行文字</p>

1
<p>第一行文字,<br/>第二行文字</p>

▲ 正常情况下第一行的文字会变成红色,但是在IE8浏览器却忽略它没有任何变化,如何来解决这个问题呢,把 !important 去掉就好了,如下:

CSS

p { color:blue; } p:first-line { color:red; }

1
2
3
4
5
6
p {
    color:blue;
}
p:first-line {
    color:red;
}

 

更多高效选择器

我还不能完全介绍Steve Souders的网站和书籍(《更快速网站》、《高性能网站》),它们是如此之好,以至于值得你花更多时间来阅读和推荐。这个家伙只有他自己才了解自己!

图片 3图片 4

 

 

英文原文:Writing efficient CSS selectors,编译:@freestyle21 和@沈涛-WEB工程师

译文链接:

【非特殊说明,转载必须在正文中标注并保留原文链接、译文链接和译者等信息,谢谢合作!】

赞 3 收藏 4 评论

图片 5

首先我们需要清楚,浏览器是如何读取选择器,以识别样式,并将相应的样式附于对应的HTML元素,达到美化页面的效果。Chris Coyier曾在《Efficiently Rendering CSS》一文中说过“浏览器读取你的选择器,遵循的原则是从选择器的右边到左边读取。换句话说,浏览器读取选择器的顺序是由右到左进行”。比如说:

法一::target 伪类选择器

首先,我们要解决的问题是如何接收点击事件,这里第一种方法我们采用 :target 伪类接收。

:target 是 CSS3 新增的一个伪类,可用于选取当前活动的目标元素。当然 URL 末尾带有锚名称 #,就可以指向文档内某个具体的元素。这个被链接的元素就是目标元素(target element)。它需要一个 id 去匹配文档中的 target 。

解释很难理解,看看实际的使用情况,假设我们的 HTML 代码如下:

XHTML

<ul class="nav">     <li>列表1</li>     <li>列表2</li> </ul> <div>列表1内容:123456</div> <div>列表2内容:abcdefgkijkl</div>

1
2
3
4
5
6
<ul class="nav">
    <li>列表1</li>
    <li>列表2</li>
</ul>
<div>列表1内容:123456</div>
<div>列表2内容:abcdefgkijkl</div>

由于要使用 :target,需要 HTML 锚点,以及锚点对应的 HTML 片段。所以上面的结构要变成:

JavaScript

<ul class="nav"> <li><a href="#content1">列表1</a></li> <li><a href="#content2">列表2</a></li> </ul> <div id="content1">列表1内容:123456</div> <div id="content2">列表2内容:abcdefgkijkl</div>

1
2
3
4
5
6
<ul class="nav">
    <li><a href="#content1">列表1</a></li>
    <li><a href="#content2">列表2</a></li>
</ul>
<div id="content1">列表1内容:123456</div>
<div id="content2">列表2内容:abcdefgkijkl</div>

这样,上面 <a href="#content1"> 中的锚点 #content1 就对应了列表1 <div id="content1"> 。锚点2与之相同对应列表2。

接下来,我们就可以使用 :target 接受到点击事件,并操作对应的 DOM 了:

CSS

#content1, #content2{     display:none; }   #content1:target, #content2:target{     display:block; }

1
2
3
4
5
6
7
8
9
#content1,
#content2{
    display:none;
}
 
#content1:target,
#content2:target{
    display:block;
}

上面的 CSS 代码,一开始页面中的 #content1 与 #content2 都是隐藏的,当点击列表1触发href="#content1" 时,页面的 URL 会发生变化:

  1. 由 www.example.com 变成 www.example.com#content1
  2. 接下来会触发 #content1:target{ } 这条 CSS 规则,#content1 元素由 display:none 变成display:block ,点击列表2亦是如此。

如此即达到了 Tab 切换。当然除了 content1 content2 的切换,我们的 li 元素样式也要不断变化,这个时候,就需要我们在 DOM 结构布局的时候多留心,在 #content1:target 触发的时候可以同时去修改 li 的样式。

在上面 HTML 的基础上,再修改一下,变成如下结构:

XHTML

<div id="content1">列表1内容:123456</div> <div id="content2">列表2内容:abcdefgkijkl</div> <ul class="nav"> <li><a href="#content1">列表1</a></li> <li><a href="#content2">列表2</a></li> </ul>

1
2
3
4
5
6
<div id="content1">列表1内容:123456</div>
<div id="content2">列表2内容:abcdefgkijkl</div>
<ul class="nav">
    <li><a href="#content1">列表1</a></li>
    <li><a href="#content2">列表2</a></li>
</ul>

仔细对比一下与上面结构的异同,这里我只是将 ul 从两个 content 上面挪到了下面,为什么要这样做呢?

因为这里需要使用兄弟选择符 ~ 。

E~F{ cssRules } ,CSS3 兄弟选择符(E~F) ,选择 E 元素后面的所有兄弟元素 F。

注意这里,最重要的一句话是 E~F 只能选择 E 元素 之后 的 F 元素,所以顺序就显得很重要了。

在这样调换位置之后,通过兄弟选择符 ~ 可以操作整个 .nav 的样式。

CSS

#content1:target ~ .nav li{     // 改变li元素的背景色和字体颜色     &:first-child{         background:#ff7300;         color:#fff;     } } #content2:target ~ .nav li{     // 改变li元素的背景色和字体颜色     &:last-child{         background:#ff7300;         color:#fff;     } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#content1:target ~ .nav li{
    // 改变li元素的背景色和字体颜色
    &:first-child{
        background:#ff7300;
        color:#fff;
    }
}
#content2:target ~ .nav li{
    // 改变li元素的背景色和字体颜色
    &:last-child{
        background:#ff7300;
        color:#fff;
    }
}

上面的 CSS 规则中,我们使用 ~ 选择符,在 #content1:target 和 #content2:target 触发的时候分别去控制两个导航 li 元素的样式。

至此两个问题,1. 如何接收点击事件 与 2. 如何操作相关DOM 都已经解决,剩下的是一些小样式的修补工作。

Demo戳我:纯CSS导航切换(:target伪类实现)

See the Pen 纯CSS导航切换(:target伪类实现) by Chokcoco (@Chokcoco) on CodePen.

避免使用标签或 class 选择器限制 id 选择器

CSS

/* Bad */ div#nav {…} .menuBalck#menu {…} /* Good */ #nav {…} #menu {…}

1
2
3
4
5
6
7
/* Bad */
div#nav {…}
.menuBalck#menu {…}
 
/* Good */
#nav {…}
#menu {…}

▲ ID选择器本身就是唯一的,加上div反而增加不必要的匹配;

CSS选择器:

对我们大多数人来说,CSS选择器并不陌生。最基本的选择器是元素选择器(比如div),ID选择器(比如#header)还有类选择器(比如.tweet)。

一些的不常见的选择器包括伪类选择器(:hover),很多复杂的CSS3和正则选择器,比如:first-child,class ^= “grid-”.

CSS选择器具有高效的继承性,引用Steve Souders的话, CSS选择器效率从高到低的排序如下:

  1. ID选择器 比如#header
  2. 类选择器 比如.promo
  3. 元素选择器 比如 div
  4. 兄弟选择器 比如 h2 + p
  5. 子选择器 比如 li > ul
  6. 后代选择器 比如 ul a 7. 通用选择器 比如 *
  7. 属性选择器 比如 type = “text”
  8. 伪类/伪元素选择器 比如 a:hover

以上引用自Steve Souders的Even Faster网站、

我们不得不提的是,纵使ID选择器很快、高效,但是它也仅仅如此。从Steve Souders的CSS Test我们可以看出ID选择器和类选择器在速度上的差异很小很小。

在Windows系统上的Firefox 6上,我测得了一个简单类选择器的(reflow figure)重绘速度为10.9ms,而ID选择器为12.5ms,所以事实上ID比类选择器重绘要慢一点点。

ID选择器和类选择器在速度上的差异基本上没有关系。

在一个标签选择器(a)的测试上显示,它比类或ID选择器的速度慢了很多。在一个嵌套很深的后代选择器的测试上,显示数据为440左右!从这里我们可以看出ID/类选择器 和 元素/后代选择器中间的差异较大,但是相互之间的差异较小。

注意: 这些数据可能在不同计算机和浏览器中间的差异较大。强烈地建议大家在自己的机子上测试一下。

A 不要用标签修饰ID

有趣的CSS题目(8):纯CSS的导航栏Tab切换方案

2016/10/28 · CSS · 1 评论 · CSS

本文作者: 伯乐在线 - chokcoco 。未经作者许可,禁止转载!
欢迎加入伯乐在线 专栏作者。

避免过度限制选择器

CSS

/* Bad */ html body .wrapper #content a {} /* Good */ #content a {}

1
2
3
4
5
/* Bad */
html body .wrapper #content a {}
 
/* Good */
#content a {}

▲ 这里至少有3个选择器是完全不需要的,过度限制选择器使浏览器工作比它实际需要的更繁重,花费的时间更多,所以这里应该避免。

这些真的需要吗?

最短的答案是:或许不是。

最长的答案是:它取决于你正在搭建的站点。如果你正在为你的晋升而努力,那么就好好写出简单、高效的CSS代码吧,因为你可能不会感觉到它给你带来的改变。 如果你正在搭建下一个每个页面都以毫秒计算的Amazon网站,这样有时速度会很快,但有时可能不是。

浏览器将会在解析CSS的速度上变得更好,甚至在手机端。在一个网站上,你不太可能会觉察到一个低效的CSS选择器,但是….

ul#main-navigation { }

8、纯CSS的导航栏Tab切换方案

不用 Javascript,使用纯 CSS 方案,实现类似下图的导航栏切换:

图片 6

CSS 的强大之处有的时候超乎我们的想象,Tab 切换,常规而言确实需要用到一定的脚本才能实现。下面看看如何使用 CSS 完成同样的事情。

实现 Tab 切换的难点在于如何使用 CSS 接收到用户的点击事情并对相关的节点进行操作。即是:

  1. 如何接收点击事件
  2. 如何操作相关DOM

下面看看如何使用两种不同的方法实现需求:

伪元素选择器

选择器 描述 版本
E:first-letter 选择文本块的第一个字母 2.1
E:first-line 选择元素的第一行 2.1

过度限制选择器

现在我们知道了什么是关键选择器,还有它是大部分工作的来源,但是我们可以更乐观一点。拥有一个明确的关键选择器最大的好处就是你可以避免使用过度限制选择器。一个过度限制选择器可能像:

CSS

html body .wrapper #content a {}

1
html body .wrapper #content a {}

这里的写的太多了,至少3个选择器是完全不需要的。它可以最多像这个样子:

CSS

#content a {}

1
#content a {}

这会发生什么呢? 首先第一个意味着浏览器不得不寻找所有的 a 元素,然后检查他们是否在一个ID为”content”的元素中,然后如此循环直到HTML标签。这样造成了太多的我们不太想要的花费。了解了这个,我们得到一些更现实的例子:

CSS

#nav li a{}

1
#nav li a{}

变成这个:

CSS

#nav a {}

1
#nav a {}

我们知道如果a在li里面,它也必定在#nav里面,所有我们可以马上把li从选择器组中拿掉。然后,既然我们知道在页面中只有一个ID为nav的元素,那么它依附的元素就是完全没有关系得了,我们也可以拿掉ul

过度限制选择器使浏览器工作比它实际需要的更繁重,花费的时间更多。我们可以删掉不必需的限制,来使我们的选择器更简单和高效。

 

打赏支持我写出更多好文章,谢谢!

任选一种支付方式

图片 7 图片 8

3 赞 4 收藏 1 评论

* 通配符造成继承失效

CSS

* { color:red; } #test{ color:blue; }

1
2
3
4
5
6
7
* {
    color:red;
}
 
#test{
    color:blue;
}

 

<div id='test'> <a href="#">text</a> </div>

1
2
3
<div id='test'>
    <a href="#">text</a>
</div>

▲ 最终text的颜色却是红色的

按照我们的理解, id 的优先级是高于 * 通配符的,而文字也本应该继承 id 元素的color值,所以最终的文字应该是蓝色呀。

所以这里混淆了一个概念,继承的样式的优先级永远低于元素本身的样式,包括通配符选择器,所以大家在开发中,应该尽可能的避免滥用通配符,以免带来一些隐性问题。

关于这个问题,还可以参考《关于CSS特殊性的问题》

而在IE6及更早浏览器并不支持通配选择符(*),只是将它忽略了,所以也变相的能看到效果。

编写高效的 CSS 选择器

2013/03/08 · CSS · 4 评论 · CSS

伯乐在线注:我们昨日在@程 序员的那些事 微博上推荐了英文原文,感谢@freestyle21 和@沈涛-WEB工程师 的热情参与。

 

高效的CSS已经不是一个新的话题了,也不是我一个非得重拾的话题,但它却是我在Sky公司工作之时,所感兴趣的,关注已久的话题。

有很多人都忘记了,或在简单的说没有意识到,CSS在我们手中,既能很高效,也可以变得很低能。这很容易被忘记,尤其是当你意识到你会的太少,CSS代码效率很低的时候。

下面的规则只真正被应用到那些速度要求很高,有成百上千的DOM元素被绘制在页面上的大型网站。但是,实践出真理,这和你是在创建下一个Facebook,还是写一个本地的展示页面都没有关系,多知道一点总是好的。

div.nav < ul li a[title]

E:hover 失效

E:hover 伪类用于设置元素在其鼠标悬停时的样式,但是在某种情况会导致效果失效,如下:

CSS

#test { background:red; } #test div { display:none; } #test:hover div{ display:block; background:yellow; }

1
2
3
4
5
6
7
8
9
10
#test {
    background:red;
}
#test div {
    display:none;
}
#test:hover div{
    display:block;
    background:yellow;
}

 

<div id="test">触发我<div>看到我了吧</div></div>

1
<div id="test">触发我<div>看到我了吧</div></div>

▲ 当触发 #test:hover 时,此效果是在IE6中是无效的,因为在IE6中, E:hover 伪类仅能用于a(超链接)对象,且该a对象必须要拥有href属性。

E:hover 还有一种失效的状态,是大家最常见的,代码如下:

CSS

a:link {color:gray;} a:hover{color:green;} a:visited{color:yellow;} a:active{color:blue;}

1
2
3
4
a:link {color:gray;}
a:hover{color:green;}
a:visited{color:yellow;}
a:active{color:blue;}

 

<a href="#nogo">文字</a>

1
<a href="#nogo">文字</a>

▲ 当超链接处于 a:hover 时,你会发现其效果是无效,文字的颜色不会变成绿色,这是因为超链接的伪类样式书写是有固定顺序的,不能颠倒,这四个属性正确的定义顺序为:

CSS

a:link {} a:visited {} a:hover {} a:active {}

1
2
3
4
a:link {}
a:visited {}
a:hover {}
a:active {}

 

但是

它确实发生了,浏览器还是不得不去做我们讨论的所有工作,无论它们变得多快。即使你不需要或者甚至不想实践任何一个,但是它都是我们值得学习的知识。请记住选择器可能会让你付出很大代价,你应该避免盯着一个看。这意味着如果你发现你自己在写像这样的:

CSS

div:nth-of-type(3) ul:last-child li:nth-of-type(odd) *{ font-weight:bold }

1
div:nth-of-type(3) ul:last-child li:nth-of-type(odd) *{ font-weight:bold }

这时,你可能就做错了。

现在,在高效选择器的世界我还是一个新人。所以如果我忘记了什么,或者你有需要补充的,请在评论里面留言。

``<``li``><``a href``=``"#" class``=``"social-link gplus"``>Google+</``a``></``li``>

前言

上一篇系列文章整理了CSS选择器的基础使用方法,因为内容较多且细致,写了很多DEMO,目前将它整理成适合移动端浏览器的CSS选择器的参考手册,方便学习CSS的人参考使用,马上就要搞定了,之后会放出 (笑脸)。

本节内容会跟着上一节的内容继续完善,首先会补充CSS选择器的浏览器支持情况(主要是说IE),比如我们最常用的s1,s2,…,sN群组选择器在IE7时才被支持,并且IE7还支持了很多我们没有想到的选择器,如子元素选择器,属性选择器,了解后你会发现IE7还是挺了不起的。

之后还会补充平常使用选择器遇到的一些问题以及解决方案,最后了解浏览器是如何读取选择器的,怎样使用选择器能达到高效率。

一些更现实的例子:#nav li a{}变成这个:#nav a {}

避免使用多层标签选择器。使用 class 选择器替换,减少css查找

CSS

/* Bad */ a[href="#"] > span > em {…} /* Good */ .className {}

1
2
3
4
5
/* Bad */
a[href="#"] > span > em {…}
 
/* Good */
.className {}

▲ 这种情况建议直接定义.className 选择器,然后使用 <em class="className"></em>

避免过渡使用子选择器

CSS

/* Bad */ div ul li a {} div > ul > li > a {} /* Good */ .className {…}

1
2
3
4
5
6
/* Bad */
div ul li a {}
div > ul > li > a {}
 
/* Good */
.className {…}

▲ 这种情况建议直接定义.className 选择器,然后使用 <a class="className"></a>

另外,事实上我们可以用.social-link{}更清晰的选择,而不是过分限制它。

伪元素选择器

选择器 描述 版本
E:before 在元素前面插入内容,配合”content”使用 2.1
E:after 在元素后面插入内容,配合”content”使用 2.1

C 一个选择器渲染失败比这个选择器被渲染更高效

伪类选择器

选择器 描述 版本
E:hover 设置元素在其鼠标悬停时的样式 2.1
E:first-child 匹配父元素的第一个子元素E 2.1

E:hover在IE6中只有a元素可用

David Hyatt:
后代选择器是CSS里最昂贵的选择器,昂贵得可怕——特别是当它放在标签和通用符后面时。
就如下面这个东东一样,绝对的效 率毒瘤:

E > F 失效

就是子选择器中间有注释会导致属性失效,如下:

CSS

#test > /*子选择器*/ p { color:red; }

1
2
3
4
5
#test >
/*子选择器*/
p {
    color:red;
}

 

<div id="test"> <p>文字</p> </div>

1
2
3
<div id="test">
    <p>文字</p>
</div>

▲ 如果你非要这样写注释,那么在IE7下会导致子选择器失效,同样, E + F 邻近选择器也有同样的问题,如何解决呢,不在选择器中间添加注释就可以了。

``<li><a href=``"#" class=``"twitter"``>Twitter</a></li>

基本选择器

选择器 描述 版本
s1,s2,…,sN 群组选择器,同时匹配所有s1元素或s2元素 2.1
E > F 子元素选择器,匹配所有E元素的子元素F 2.1
E + F 毗邻元素选择器,匹配所有紧随E元素之后的同级元素F 2.1
E ~ F 匹配任何E标签之后的同级F标签 3

``<``li``><``a href``=``"#" class``=``"social-link dribble"``>Dribbble</``a``></``li``>

伪类选择器

选择器 描述 版本
E:focus 设置对象在成为输入焦点时的样式 2.1

这里发生的情况是浏览器会在定位到#social区域下的四个链接之前得到页面上所有成千上万的链接。我们的关键选择器匹配了太多我们不感兴趣的其他元素。

伪类选择器

选择器 描述 版本
E:checked 匹配用户界面上处于选中状态的元素E 3
E:enabled 匹配用户界面上处于可用状态的元素E 3
E:disabled 匹配用户界面上处于禁用状态的元素E 3
E:root 匹配文档的根元素,对于HTML文档,就是HTML元素 3
E:last-child 匹配父元素的最后一个子元素E 3
E:nth-last-child(n) 匹配父元素的倒数第n个子元素E 3
E:nth-of-type(n) 匹配同类型中的第n个同级兄弟元素E 3
E:nth-last-of-type(n) 匹配同类型中的倒数第n个同级兄弟元素E 3
E:first-of-type 匹配同类型中的第一个同级兄弟元素E 3
E:last-of-type 匹配同类型中的最后一个同级兄弟元素E 3
E:only-child 匹配父元素仅有的一个子元素E 3
E:only-of-type 匹配同类型中的唯一的一个同级兄弟元素E 3
E:empty 匹配没有任何子元素(包括text节点)的元素E 3
E:not(s) 匹配不含有s选择符的元素 3
E:target 匹配文档中特定”id”点击后的效果 3

选择器的最后一部分,也就是选择器的最右边(在这个例子中就是a[title]部分)部分被称为“关键选择器”,它将决定你的选择器的效率如何?是高还是低。

性能优化

CSS 选择器我们都在使用,但是如何让它变的更简洁,高效呢?
首先选择器对性能的影响源于浏览器匹配选择器和文档元素时所消耗的时间,所以优化选择器的原则是应尽量避免使用消耗更多匹配时间的选择器,但是在此之前我们需要先了解浏览器的匹配机制,就是它是如何读取我们的选择器的。

思考 下这东东:

避免使用通用选择器

CSS

#nav * {…}

1
#nav * {…}

▲ 这个选择器所做的是选择所有在页面上的单个元素(是每个单个的元素),然后去看看它们是否有一个#nav的父元素。这是非常不高效选择器,开销太大了,应该避免关键选择器是通配选择器的情况。

#main-navigation { font-family: Georgia, Serif; }

避免使用标签限制 class 选择器

CSS

/* Bad */ span.red {…} /* Good */ .text-red {…}

1
2
3
4
5
/* Bad */
span.red {…}
 
/* Good */
.text-red {…}

▲ 在标签上定义 class 选择器,在开发和维护时容易混淆,一般不建议这样写。

改变后:

E:first-letter 失效

E:first-letter 失效和 E:first-line 失效的问题是相同的,解决方案请参考上方。

``<``li``><``a href``=``"#" class``=``"social-link twitter"``>Twitter</``a``></``li``>

平庸的IE8浏览器

虽然来到IE8的时代,但是对于新选择器的支持并不多,不过还好我们最常用的E:beforeE:after配合content属性都在IE8中得到了很好的支持。

以下选择器不支持IE6,IE7,仅支持 IE8 及以上的浏览器

D 试想一下为何你这样写选择器

常见问题与Bug

B 绝对没有比用后代选择器更糟糕的做法了

玩转CSS选择器(二) 之 浏览器支持,常见Bug,性能优化

2015/08/29 · CSS · 选择器

原文出处: Alsiso   

如果你可以避免的话,也不要用它修饰 class 。class 不是唯一的,所以理论上你可以把它用在不同的标签。如果你愿意的话,你可以用标签控制不同的样式,这样你可能需要标签修饰(比如:li.first),但 这样做的人很少,所以,don’t .

属性选择器

选择器 描述 版本
E[attr] 匹配att属性的E元素 2.1
E[attr=”val”] 匹配att属性且属性值等于val的E元素 2.1
E[attr~=”val”] 匹配att属性且属性值中的词列表有一个等于val的E元素 2.1
E[attr^=”val”] 匹配att属性且属性值为以val开头的字符串的E元素 3
E[attr$=”val”] 匹配att属性且属性值为以val结尾的字符串的E元素 3
E[attr*=”val”] 匹配att属性且属性值为包含val的字符串的E元素 3
E[att|=”val”] 匹配att属性且属性值为以val开头并用连接符”-“分隔的字符串的E元素 2.1

IE7浏览器,单复选框的checked在属性选择器中是不被支持的,这部分内容会在下面的常见问题中详细说明。

我们知道ID’s 是最高效的选择器。当你想让渲染速度最高效时,你可能会给每个独立的标签配置一个ID,然后用这些ID写样式。那会超级快,也超级荒唐。这样的结果是语义 极差,维护难到了极点。即使在核心部分你也不应该见过这样做的。我认为这个可以提醒我们不要为了高效的CSS放弃语义和可维护性。

选择器匹配机制

CSS

#nav > a { color:red; }

1
2
3
#nav > a {
    color:red;
}

当我们看到这个选择器的时候,会认为首先会找到id为 nav 的元素,然后在找到其子元素,将样式属性应用到 a 元素上。

事实上,却恰恰相反,因为浏览器读取选择器时,不是按照我们的阅读习惯从左到右,而是遵循的从选择器的右边到左边进行读取的

当我们知道这个匹配机制后,再回来看这个选择器,浏览器必须先遍历页面中所有的 a 元素,然后查找其父元素的id是否为 nav ,这样一来你就会发看似高效的选择器在实际中的匹配开销是很高的。

理解了CSS选择器从右到左匹配的机制后,我们再看以下两种选择器:

div #nav

1
div #nav

 

CSS

#nav div

1
#nav div

你是否会认为第2种选择器的效率要高于第1种,那么就错了,其实第一个选择器的效率更高,因为第一个选择器的关键选择器使用了 #id 选择器”,而第二个选择器的关键选择器使用的是 div 标签选择器。

这里所说的关键选择器,就是CSS选择器中最右边部分,它是被浏览器最先寻找的,那么哪类选择器是最高效的?哪个是会影响选择器效率的关键选择器?

``<li><a href=``"#" class=``"dribble"``>Dribbble</a></li>

了不起的IE7

当我们在开发网页时,如果网页需要兼容IE6,那么自然地会把IE6和IE7浏览器归为一路货色,对于不兼容的选择器和属性都将不再考虑使用,可是你是否知道IE7相比IE6增加了许多选择器可以用,如群组选择器,相邻选择器,兄弟选择器,属性选择器。

以下选择器是不支持IE6,仅支持 IE7 及以上的浏览器

我们不得不提的是,纵使ID选择器很快、高效,但是它也仅仅如此。从Steve Souders的CSS Test我们可以看出ID选择器和类选择器在速度上的差异很小很小。

选择器效率

在上面内容中我们了解浏览器的匹配机制,以及关键选择器的重要性,那么哪些CSS选择器能够减少性能损耗呢?

Google 资深web开发工程师 Steve Souders 对 CSS 选择器的执行效率从高到低做了一个排序:

  1. id选择器(#id)
  2. 类选择器(.className)
  3. 标签选择器(div,h1,p)
  4. 相邻选择器(h1+p)
  5. 子选择器(ul > li)
  6. 后代选择器(li a)
  7. 通配符选择器(*)
  8. 属性选择器(a[rel=”external”])
  9. 伪类选择器(a:hover,li:nth-child)

从Steve Souders的CSS Test我们可以看出 #id 选择器和 .className 类选择器在速度上的差异很小很小。而在一个a标签选择器的测试上显示,它比#id选择器和类选择器的速度慢了很多,从这里我们可以看出 #id 、 .className 选择器 和  a 标签、 li a 后代选择器中间的差异较大,但是相互之间的差异较小。

接下来举几个示例:

CSS

#nav {} .menu{}

1
2
#nav {}
.menu{}

 

CSS

p#nav {} p.menu {}

1
2
p#nav {}
p.menu {}

▲ 上面的选择器效率要高于下面的选择器,标签元素会降低选择器效率

CSS:#social a {}

E:focus 失效

CSS

#test:focus + p { font-weight:bold; }

1
2
3
#test:focus + p {
    font-weight:bold;
}

 

<button id="test">点击我触发focus</button> <p>文字</p>

1
2
<button id="test">点击我触发focus</button>
<p>文字</p>

▲ 当点击 button 按钮触发 :focus 时将邻近元素的文字进行加粗,但是这个效果在IE8是失效的,如何来修复它呢,只需要添加一个空的 :focus 选择器,如下:

CSS

#test:focus + p { font-weight:bold; } #test:focus {}

1
2
3
4
#test:focus + p {
    font-weight:bold;
}
#test:focus {}

 

过度限制选择器使浏览器工作比它实际需要的更繁重,花费的时间更多。我们可以删掉不必需的限制,来使我们的选择器更简单和高效。

狂拽炫酷*炸天的IE9

IE最好的时代就是迎接CSS3的到来,从IE9支持了一大坨新CSS3的伪类以及伪元素,我就勉强给IE使用上这个酷炫点的修饰语。

以下选择器不支持IE6,IE7,IE8,仅支持 IE9 及以上的浏览器

 

利用可继承性

CSS

/* Bad */ #nav > li > a { color:red; } /* Good */ #nav { color:red; }

1
2
3
4
5
/* Bad */
#nav > li > a { color:red; }
 
/* Good */
#nav { color:red; }

▲ 在使用选择器之前,请先考虑利用继承性实现

下一节继续整理选择器的优先级和继承性相关内容。

1 赞 1 收藏 评论

图片 9

你可能不需要从 a 选择器开始(如果你只是想换个字体)。下面这个可能更高效些:

优化建议

我们理解了CSS选择器从右到左匹配的机制,也了解关键选择器的重要性,以及CSS选择器的效率排序,那么在使用选择器的时候,通过避免不恰当的使用,来提升 CSS 选择器性能。

死也不要像下 面这样干:

浏览器支持

我不是很确定是否有更好的证据去证明这一点,因为如果你有大量的选择 器在CSS样式表里无法找到,这样的事情貌似很离奇,但一点必需注意的是,从右到左的解释一个选择器来说,一旦它找不到,那它就会停止尝试。然而如果它找 到了,那它就需要花更多精力去解释了。

让IE6-8支持伪类和属性选择器

如何才能让IE6~8支持CSS3伪类和属性选择器,也许你已经想到了,我们会用JavaScript工具来进行辅助,那么刚好|8e50989464f7517425e2c31ba2d6dd59424|就可以完成这件事情,而且使用起来很简单,只要把selectivizr.js引入到页面上就可以了,如下:

<!- -[if (gte IE 6)&(lte IE 8)]> <script type="text/javascript" src="selectivizr.js"></script> <![endif]- ->

1
2
3
4
5
<!- -[if (gte IE 6)&(lte IE 8)]>
 
      <script type="text/javascript" src="selectivizr.js"></script>
 
<![endif]- ->

但是使用它还有一些注意事项:

  1. 必须要引用一个JavaScript库,比如jQuery
  2. 只能解析<link>标签引入的样式,如果是<style>定义的样式是不会解析的
  3. 动态生成的DOM不会做二次映射
  4. 需要在标准模式的DTD才能够生效

项目地址:http://selectivizr.com

#content a {}

<``ul id``=``"social"``>

3 书写规范

 

``<``li``><``a href``=``"#" class``=``"social-link facebook"``>Facebook</``a``></``li``>

``<li><a href=``"#" class=``"gplus"``>Google+</a></li>

html body ul li a { }

``<li><a href=``"#" class=``"facebook"``>Facebook</a></li>

这里的写的太多了,至少3个选择器是完全不需要的。它可以最多像这个样子:

那么如何让关键选择器更有效,性能化更高呢?其实很简单,主要把握一点“越具体的关键选择器,其性能越高”。

我们知道如果a在li里面,它也必定在#nav里面,所有我们可以马上把li从选择器组中拿掉。然后,既然我们知道在页面中只有一个ID为nav的元素,那么它依附的元素就是完全没有关系得了,我们也可以拿掉ul

</ul>

1 浏览器如何识别你的选择器

2 CSS选择器的效率
如 果你阅读了本站的有关于选择器类型的介绍的话,你对选择器并不会感到陌生。就算你没读过,我想CSS选择器不会让我们觉得是新东西,比如我们常用的基本选 择器“元素标签选择器div”、“id选择器#header”、“类选择器.class”,或者说我们很少见的伪类选择器“:focus”以及更复杂的 css3选择器“:nth-child”等等。
选择器有一个固有的效率,我们来看Steve Souders给排的一个顺序:
id选择器(#myid)
类选择器(.myclassname)
标签选择器(div,h1,p)
相邻选择器(h1+p)
子选择器(ul > li)
后代选择器(li a)
通配符选择器(*)
属性选择器(a[rel="external"])
伪类选择器(a:hover,li:nth-child)
上面九种选择器的效率是从高到低排下来的,基中ID选择器的效率是最高,而伪类选择器的效率则是最低。

html body .wrapper #content a {}

这个新的关键选择器将会匹配更少的元素,这意味着浏览器能够很快的找到它们并渲染特定的样式,然后专注于下一件事。

CSS:#social .social-link {}

上面的实例来说,浏览器首先会尝试在你的HTML标签中寻找“a[title]”元素,接着在匹配“li和ul”,最后在去匹配“div.nav”。这就是前成所主的“选择器从右到左的原则”。

<ul id=``"social"``>

 拥有一个明确的关键选择器最大的好处就是你可以避免使用过度限制选择器。一个过度限制选择器可能像:

 

#main-navigation li a { font-family: Georgia, Serif; }

ID’s 是唯一的,所以不需要用标签修饰,这只会让它更低效。

为了补救我们可以给每个在社交链接区域的 a 增加一个更特殊、明确的选择器 .social-link , 但是这好像有点违背我们的认知:当我们能用组合选择器的时候就不要放不必要的类标示在元素上。

假设你有一个复杂的页面,它相当巨大并且在你的一个很大很大的站点上。在那个页面上有成百上千甚至上万的 a 标签。它还有一个小的社交链接区域放在一个ID为#social的Ul里面。我们假设它们是Twitter,Facebook,Dribbble还有 Google+的链接吧。在这个页面上我们有四个社交链接和成百上千的其他链接。 下面的这个选择器就自然的不是那么高效和合理了:#social a {…}

4 案例详解:

E 不要过度限制选择器

本文由9159.com发布于前端,转载请注明出处:CSS选择器的基础使用方法,未经作者许可

关键词:

上一篇:没有了
下一篇:没有了