对大多技术人员来讲都比较熟悉CSS选择器,举一例子来讲,假设给一个p标签增长一个类(class),但是执行后该class中的有些属性并无起做用。经过Firebug查看,发现没有起做用的属性被覆盖了,这个时候忽然意识到了CSS选择器的优先级问题。严格来说,选择器的种类能够分为三种:标签名选择器、类选择器和ID选择器。而所谓的后代选择器和群组选择器只不过是对前三种选择器的扩展应用。而在标签内写入style=""的方式,应该是CSS的一种引入方式,而不是选择器,由于根本就没有用到选择器。而通常人们将上面这几种方式结合在一块儿,因此就有了5种或6种选择器了。javascript
最基本的选择器是元素选择器(好比div),ID选择器(好比#header)还有类选择器(好比.tweet)。一些的不常见的选择器包括伪类选择器(:hover),不少复杂的CSS3和正则选择器,好比:first-child,class ^= “grid-”。CSS选择器具备高效的继承性,引用Steve Souders的话, CSS选择器效率从高到低的排序以下:css
1.id选择器(#myid)
2.类选择器(.myclassname)
3.标签选择器(div,h1,p)
4.相邻选择器(h1+p)
5.子选择器(ul > li)
6.后代选择器(li a)
7.通配符选择器(*)
8.属性选择器(a[rel="external"])
html
9.伪类选择器(a:hover, li:nth-child)前端
纵使ID选择器很快、高效,可是它也仅仅如此。从Steve Souders的CSS Test咱们能够看出ID选择器和类选择器在速度上的差别很小很小。
在Windows系统上的Firefox 6上,我测得了一个简单类选择器的(reflow figure)重绘速度为10.9ms,而ID选择器为12.5ms,因此事实上ID比类选择器重绘要慢一点点。
ID选择器和类选择器在速度上的差别基本上没有关系。
在一个标签选择器(a)的测试上显示,它比类或ID选择器的速度慢了不少。在一个嵌套很深的后代选择器的测试上,显示数据为440左右!从这里咱们能够看出ID/类选择器 和 元素/后代选择器中间的差别较大,可是相互之间的差别较小。java
div.test1 .span var 优先级 1+10 +10 +1 span#xxx .songs li 优先级1+100 + 10 + 1 #xxx li 优先级 10对于什么状况下使用什么选择器,用不一样选择器的原则是:
①最经常使用的选择器是类选择器。nginx
②li、td、dd等常常大量连续出现,而且样式相同或者相相似的标签,咱们采用类选择器跟标签名选择器结合的后代选择器 .xx li/td/dd {} 的方式选择。正则表达式
③极少的状况下会用ID选择器,固然不少前端开发人员喜欢header,footer,banner,conntent设置成ID选择器的,由于相同的样式在一个页面里不可能有第二次。浏览器
在这里不得不提使用在标签内引入CSS的方式来写CSS,即:性能
<div style="color:red">polaris</div>
这时候的优先级是最高的。咱们给它的优先级是1000,这种写法不推荐使用,特别是对新手来讲。这也彻底违背了内容和显示分离的思想。DIV+CSS的优势也不能再有任何体现。
.content * {color: red;}
浏览器匹配文档中全部的元素后分别向上逐级匹配 class 为 content 的元素,直到文档的根节点。所以其匹配开销是很是大的,因此应避免使用关键选择器是通配选择器的状况。测试
二、避免使用标签或 class 选择器限制 id 选择器
BAD button#backButton {…} BAD .menu-left#newMenuIcon {…} GOOD #backButton {…} GOOD #newMenuIcon {…}
三、避免使用标签限制 class 选择器
BAD treecell.indented {…} GOOD .treecell-indented {…} BEST .hierarchy-deep {…}
四、避免使用多层标签选择器。使用 class 选择器替换,减小css查找
BAD
treeitem[mailfolder="true"] > treerow > treecell {…} GOOD .treecell-mailfolder {…}
五、避免使用子选择器
BAD treehead treerow treecell {…} BETTER, BUT STILL BAD treehead > treerow > treecell {…} GOOD .treecell-header {…}
六、使用继承
BAD #bookmarkMenuItem > .menu-left { list-style-image: url(blah) } GOOD #bookmarkMenuItem { list-style-image: url(blah) }
不要在ID选择器前使用标签名
通常写法:DIV#divBox
更好写法:#divBox
解释: 由于ID选择器是惟一的,加上div反而增长没必要要的匹配。
不要再class选择器前使用标签名
通常写法:span.red
更好写法:.red
解释:同第一条,但若是你定义了多个.red,并且在不一样的元素下是样式不同,则不能去掉,好比你css文件中定义以下:
若是是这样定义的就不要去掉,去掉后就会混淆,不过建议最好不要这样写
尽可能少使用层级关系
通常写法:#divBox p .red{color:red;}
更好写法:.red{..}
使用class代替层级关系
通常写法:#divBox ul li a{display:block;}
更好写法:.block{display:block;}
* { margin: 0; padding: 0; }
在咱们看比较高级的选择器以前,应该认识下这个众所周知的清空选择器。星号呢会将页面上全部每个元素都选到。许多开发者都用它来清空`margin`和`padding`。固然你在练习的时候使用这个没问题,可是我不建议在生产环境中使用它。它会给浏览器凭添许多没必要要的东西。
`*`也能够用来选择某元素的全部子元素。
#container * { border: 1px solid black; }
它会选中`#container`下的全部元素。固然,我仍是不建议你去使用它,若是可能的话。
兼容性
IE6+
Firefox
Chrome
Safari
Opera
#container { width: 960px; margin: auto; }
在选择器中使用`#`能够用id来定位某个元素。你们一般都会这么使用,而后使用的时候你们仍是得至关当心的。
须要问本身一下:我是否是必需要给这个元素来赋值个id来定位它呢?
`id`选择器是很严格的而且你没办法去复用它。若是可能的话,首先试试用标签名字,HTML5中的新元素,或者是伪类。
兼容性
IE6+
Firefox
Chrome
Safari
Opera
.error { color: red; }
这是个`class`选择器。它跟`id`选择器不一样的是,它能够定位多个元素。当你想对多个元素进行样式修饰的时候就可使用`class`。当你要对某个特定的元素进行修饰那就是用`id`来定位它。
兼容性
IE6+
Firefox
Chrome
Safari
Opera
li a { text-decoration: none; }
下一个经常使用的就是`descendant`选择器。若是你想更加具体的去定位元素,你可使用它。例如,假如,你不须要定位全部的`a`元素,而只须要定位`li`标签下的`a`标签?这时候你就须要使用`descendant`选择器了。
专家提示:若是你的选择器像`X Y Z A B.error`这样,那你就错了。时刻都提醒本身,是否真的须要对那么多元素修饰。
兼容性
IE6+
Firefox
Chrome
Safari
Opera
a { color: red; } ul { margin-left: 0; }
若是你想定位页面上全部的某标签,不是经过`id`或者是’class’,这简单,直接使用类型选择器。
兼容性
IE6+
Firefox
Chrome
Safari
Opera
a:link {color:red;} a:visited {color: purple;}
咱们使用`:link`这个伪类来定位全部尚未被访问过的连接。
另外,咱们也使用`:visited`来定位全部已经被访问过的连接。
兼容性
IE7+
Firefox
Chrome
Safari
Opera
ul + p { color: red; }
这个叫相邻选择器。它指挥选中指定元素的直接后继元素。上面那个例子就是选中了全部`ul`标签后面的第一段,并将它们的颜色都设置为红色。
兼容性
IE7+
Firefox
Chrome
Safari
Opera
div#container > ul { border: 1px solid black; }
`X Y`和`X > Y`的差异就是后面这个指挥选择它的直接子元素。看下面的例子:
<div id="container"> <ul> <li> List Item <ul> <li> Child </li> </ul> </li> <li> List Item </li> <li> List Item </li> <li> List Item </li> </ul> </div>
`#container > ul`只会选中`id`为’container’的`div`下的全部直接`ul`元素。它不会定位到如第一个`li`下的`ul`元素。
因为某些缘由,使用子节点组合选择器会在性能上有许多的优点。事实上,当在javascript中使用`css`选择器时候是强烈建议这么作的。
兼容性
IE7+
Firefox
Chrome
Safari
Opera
ul ~ p { color: red; }
兄弟节点组合选择器跟`X+Y`很类似,而后它又不是那么的严格。`ul + p`选择器只会选择紧挨跟着指定元素的那些元素。而这个选择器,会选择跟在目标元素后面的全部匹配的元素。
兼容性
IE7+
Firefox
Chrome
Safari
Opera
a[title] { color: green; }
这个叫属性选择器,上面的这个例子中,只会选择有title属性的元素。那些没有此属性的锚点标签将不会被这个代码修饰。那再想一想若是你想更加具体的去筛选?那…
兼容性
IE7+
Firefox
Chrome
Safari
Opera
a[href="http://strongme.cn"] { color: #1f6053; /* nettuts green */ }
上面这片代码将会把`href`属性值为`http://strongme.cn`的锚点标签设置为绿色,而其余标签则不受影响。
注意咱们将值用双引号括起来了。那么在使用Javascript的时候也要使用双引号括起来。能够的话,尽可能使用标准的CSS3选择器。
这样能够用了,可是仍是有点死,若是不是这个连接,而是相似的连接,那么这时就得用正则表达式了。
兼容性
IE7+
Firefox
Chrome
Safari
Opera
a[href*="strongme"] { color: #1f6053; }
Tada,正是咱们须要的,这样,就指定了`strongme`这个值必须出如今锚点标签的`href`属性中,无论是`strongme.cn`仍是`strongme.com`仍是`www.strongme.cn`均可以被选中。
可是记得这是个很宽泛的表达方式。若是锚点标签指向的不是`strongme`相关的站点,若是要更加具体的限制的话,那就使用`^`和`$`,分别表示字符串的开始和结束。
兼容性
IE7+
Firefox
Chrome
Safari
Opera
a[href^="http"] { background: url(path/to/external/icon.png) no-repeat; padding-left: 10px; }
你们确定好奇过,有些站点的锚点标签旁边会有一个外链图标,我也相信你们确定见过这种状况。这样的设计会很明确的告诉你会跳转到别的网站。
用克拉符号就能够轻易作到。它一般使用在正则表达式中标识开头。若是咱们想定位锚点属性`href`中以`http`开头的标签,那咱们就能够用与上面类似的代码。
注意咱们没有搜索http://,那是不必的,由于它都不包含https://。
那若是咱们想找到全部指向一张图片的锚点标签呢?那咱们来使用下`&`字符。
兼容性
IE7+
Firefox
Chrome
Safari
Opera
a[href$=".jpg"] { color: red; }
此次咱们又使用了正则表达式`$`,表示字符串的结尾处。这段代码的意思就是去搜索全部的图片连接,或者其它连接是以`.jpg`结尾的。可是记住这种写法是不会对`gifs`和`pngs`起做用的。
兼容性
IE7+
Firefox
Chrome
Safari
Opera
a[data-filetype="image"] { color: red; }
在回到第8条,咱们如何把全部的图片类型都选中呢`png`,`jpeg`,’jpg’,'gif’?咱们可使用多选择器。看下面:
a[href$=".jpg"], a[href$=".jpeg"], a[href$=".png"], a[href$=".gif"] { color: red; }
可是这样写着很蛋疼啊,并且效率会很低。另一个办法就是使用自定义属性。咱们能够给每一个锚点加个属性`data-filetype`指定这个连接指向的图片类型。
[html]
Image Link </a[/html]
那有了这个钩子,咱们就能够去用标准的办法只去选定文件类型为`image`的锚点了。
a[data-filetype="image"] { color: red; }
兼容性
IE7+
Firefox
Chrome
Safari
Opera
a[data-info~="external"] { color: red; } a[data-info~="image"] { border: 1px solid black; }
这个我想会让你的小伙伴惊呼妙极了。不多有人知道这个技巧。这个`~`符号能够定位那些某属性值是空格分隔多值的标签。
继续使用第15条那个例子,咱们能够设置一个`data-info`属性,它能够用来设置任何咱们须要的空格分隔的值。这个例子咱们将指示它们为外部链接和图片连接。
<a href="path/to/image.jpg" data-info="external image"> Click Me, Fool </a>
给这些元素设置了这个标志以后,咱们就可使用`~`来定位这些标签了。
/* Target data-info attr that contains the value "external" */ a[data-info~="external"] { color: red; } /* And which contain the value "image" */ a[data-info~="image"] { border: 1px solid black; }
## 17. X:checked
input[type=radio]:checked { border: 1px solid black; }
上面这个伪类写法能够定位那些被选中的单选框和多选框,就是这么简单。
兼容性
IE9+
Firefox
Chrome
Safari
Opera
`before`和`after`这俩伪类。好像天天你们都能找到使用它们的创造性方法。它们会在被选中的标签周围生成一些内容。
当使用`.clear-fix`技巧时许多属性都是第一次被使用到里面的。
.clearfix:after { content: ""; display: block; clear: both; visibility: hidden; font-size: 0; height: 0; } .clearfix { *display: inline-block; _height: 1%; }
上面这段代码会在目标标签后面补上一段空白,而后将它清除。这个方法你必定得放你的聚宝盆里面。特别是当`overflow:hidden`方法不顶用的时候,这招就特别管用了。
根据CSS3标准规定,可使用两个冒号`::`。而后为了兼容性,浏览器也会接受一个双引号的写法。其实在这个状况下,用一个冒号仍是比较明智的。
兼容性
IE8+
Firefox
Chrome
Safari
Opera
div:hover { background: #e3e3e3; }
不用说,你们确定知道它。官方的说法是`user action pseudo class`.听起来有点儿迷糊,其实还好。若是想在用户鼠标飘过的地方涂点儿彩,那这个伪类写法能够办到。
注意旧版本的IE只会对加在锚点`a`标签上的`:hover`伪类起做用。
一般你们在鼠标飘过锚点连接时候加下边框的时候用到它。
a:hover { border-bottom: 1px solid black; }
专家提示:border-bottom:1px solid black;比text-decoration:underline;要好看不少。
兼容性
IE6+(IE6只能在锚点标签上起做用)
Firefox
Chrome
Safari
Opera
div:not(#container) { color: blue; }
`取反`伪类是至关有用的,假设咱们要把除`id`为`container`以外的全部`div`标签都选中。那上面那么代码就能够作到。
或者说我想选中全部出段落标签以外的全部标签。
*:not(p) { color: green; }
兼容性
IE9+
Firefox
Chrome
Safari
Opera
p::first-line { font-weight: bold; font-size:1.2em; }
咱们可使用`::`来选中某标签的部份内容,如地一段,或者是第一个字没有。可是记得必须使用在块式标签上才起做用。
伪标签是由两个冒号 :: 组成的。
定位第一个字
p::first-letter { float: left; font-size: 2em; font-weight: bold; font-family: cursive; padding-right: 2px; }
上面这段代码会找到页面上全部段落,而且指定为每一段的第一个字。
它一般在一些新闻报刊内容的重点突出会使用到。
定位某段的第一行
p::first-line { font-weight: bold; font-size: 1.2em; }
跟`::first-line`类似,会选中段落的第一行 。
为了兼容性,以前旧版浏览器也会兼容单冒号的写法,例如`:first-line`,`:first-letter`,`:before`,`:after`.可是这个兼容对新介绍的特性不起做用。
兼容性
IE6+
Firefox
Chrome
Safari
Opera
li:nth-child(3) { color: red; }
还记得咱们面对如何取到推跌式标签的第几个元素是无处下手的时光么,有了`nth-child`那日子就一去不复返了。
请注意`nth-child`接受一个整形参数,而后它不是从0开始的。若是你想获取第二个元素那么你传的值就是`li:nth-child(2)`.
咱们甚至能够获取到由变量名定义的个数个子标签。例如咱们能够用`li:nth-child(4n)`去每隔3个元素获取一次标签。
兼容性
IE9+
Firefox3.5+
Chrome
Safari
li:nth-last-child(2) { color: red; }
假设你在一个`ul`标签中有N多的元素,而你只想获取最后三个元素,甚至是这样`li:nth-child(397)`,你能够用`nth-last-child`伪类去代替它。
这个技巧能够很正确的代替第16个TIP,不一样的就是它是从结尾处开始的,倒回去的。
兼容性
IE9+
Firefox3.5+
Chrome
Safari
Opera
ul:nth-of-type(3) { border: 1px solid black; }
曾几什么时候,咱们不想去选择子节点,而是想根据元素的类型来进行选择。
想象一下有5个`ul`标签。若是你只想对其中的第三个进行修饰,并且你也不想使用`id`属性,那你就可使用`nth-of-type(n)`伪类来实现了,上面的那个代码,只有第三个`ul`标签会被设置边框。
兼容性
IE9+
Firefox3.5+
Chrome
Safari
ul:nth-last-of-type(3) { border: 1px solid black; }
一样,也能够相似的使用`nth-last-of-type`来倒序的获取标签。
兼容性
IE9+
Firefox3.5+
Chrome
Safari
Opera
ul li:first-child { border-top: none; }
这个结构性的伪类能够选择到第一个子标签,你会常用它来取出第一个和最后一个的边框。
假设有个列表,没个标签都有上下边框,那么效果就是第一个和最后一个就会看起来有点奇怪。这时候就可使用这个伪类来处理这种状况了。
兼容性
IE7+
Firefox
Chrome
Safari
Opera
ul > li:last-child { color: green; }
跟`first-child`相反,`last-child`取的是父标签的最后一个标签。
例如
标签
<ul> <li> List Item </li> <li> List Item </li> <li> List Item </li> </ul>
这里没啥内容,就是一个了 List。
ul { width: 200px; background: #292929; color: white; list-style: none; padding-left: 0; } li { padding: 10px; border-bottom: 1px solid black; border-top: 1px solid #3c3c3c; }
上面的代码将设置背景色,移除浏览器默认的内边距,为每一个`li`设置边框以凸显必定的深度。
兼容性
IE9+
Firefox
Chrome
Safari
Opera
div p:only-child { color: red; }
说实话,你会发现你几乎都不会用到这个伪类。然而,它是可用的,有会须要它的。
它容许你获取到那些只有一个子标签的父标签。就像上面那段代码,只有一个段落标签的`div`才被着色。
<div><p> My paragraph here. </p></div> <div> <p> Two paragraphs total. </p> <p> Two paragraphs total. </p> </div>
上面例子中,第二个`div`不会被选中。一旦第一个`div`有了多个子段落,那这个就再也不起做用了。
兼容性
IE9+
Firefox
Chrome
Safari
Opera
li:only-of-type { font-weight: bold; }
结构性伪类能够用的很聪明。它会定位某标签只有一个子标签的目标。设想你想获取到只有一个子标签的`ul`标签?
使用`ul li`会选中全部`li`标签。这时候就要使用`only-of-type`了。
ul > li:only-of-type { font-weight: bold; }
兼容性
IE9+
Firefox 3.5+
Chrome
Safari
Opera
30. X:first-of-type `first-of-type`
伪类能够选择指定标签的第一个兄弟标签。
测试
<div> <p> My paragraph here. </p> <ul> <li> List Item 1 </li> <li> List Item 2 </li> </ul> <ul> <li> List Item 3 </li> <li> List Item 4 </li> </ul> </div>
来你把List Item 2取出来,若是你已经取出来或者是放弃了,来继续。
解决办法1
办法不少,咱们看一些比较方便的。首先是`first-of-type`。
ul:first-of-type > li:nth-child(2) { font-weight: bold; }
找到第一个`ul`标签,而后找到直接子标签`li`,而后找到第二个子节点。
解决办法2
另外一个解决办法就是邻近选择器。
p + ul li:last-child { font-weight: bold; }
这种状况下,找到`p`下的直接`ul`标签,而后找到它的最后一个直接子标签。
解决办法3
咱们能够随便玩耍这些选择器。来看看:
ul:first-of-type li:nth-last-child(1) { font-weight: bold; }
先获取到页面上第一个`ul`标签,而后找到最后一个子标签。
兼容性
IE9+
Firefox 3.5+
Chrome
Safari
Opera
若是你想向旧版本浏览器妥协,好比IE6,那你用这些新的选择器的时候仍是得当心点。但别别让IE6组织你去学这些新的技能。那你就对本身太残忍了。记得多查查[兼容性列表](http://www.quirksmode.org/css/contents.html),或者使用[Dean Edward's excellent IE9.js script ](http://code.google.com/p/ie7-js/)来让你的浏览器具备这些特性。
第二个,使用向jQuery的时候,尽可能使用原生的CSS3选择器。可能 活让你的代码跑的很快。这样选择器引擎就可使用浏览器原生解析器,而不是选择器本身的。