相关文章推荐
近视的镜子  ·  LDAP安装步骤开发者社区·  7 月前    · 
近视的镜子  ·  Method always returns ...·  7 月前    · 
近视的镜子  ·  Python搞定表格可视化!·  7 月前    · 
近视的镜子  ·  Control.ControlCollect ...·  10 月前    · 
近视的镜子  ·  Qt - XML和JSON - [BORUTO] ·  11 月前    · 
文雅的沙滩裤  ·  WKWebView拦截请求资源 ·  1小时前    · 
独立的眼镜  ·  如何连接Babelfish for RDS ...·  2 小时前    · 
发财的蛋挞  ·  Microsoft Azure Data ...·  2 小时前    · 
冷冷的投影仪  ·  Secure an ASP.NET ...·  3 小时前    · 
不羁的生姜  ·  PSPSDK 开发的时候出现 ...·  3 小时前    · 

CSS3选择器:nth-child和:nth-of-type之间的差异

这篇文章发布于 2011年06月21日,星期二,23:04,归类于 CSS相关 。 阅读 198688 次, 今日 2 次 40 条评论

一、深呼吸,直接内容

:nth-child和:nth-of-type都是CSS3中的伪类选择器,其作用近似却又不完全一样,对于不熟悉的人对其可能不是很区分,本文就将介绍两者的不同,以便于大家正确灵活使用这两类选择器。

先看一个简单的实例,首先是HTML部分:

<section>
    <p>我是第1个p标签</p>
    <p>我是第2个p标签</p>  <!-- 希望这个变红 -->
</section>

然后两个选择器相对应的CSS代码如下:

p:nth-child(2) { color: red; }
p:nth-of-type(2) { color: red; }

上面这个例子中,这两个选择器所实现的效果是一致的,第二个 p 标签的文字变成了红色,如下截图(截自IE9):

您可以狠狠地点击这里: :nth-child测试demo1 :nth-of-type测试demo1

尽管上面两个demo的最后效果一致,但是两个选择器之间存在差异是必然的。

对于 :nth-child 选择器,在简单白话文中,意味着选择一个元素如果:

  • 这是个段落元素
  • 这是父标签的第二个孩子元素
  • 对于 :nth-of-type 选择器,意味着选择一个元素如果:

  • 选择父标签的第二个段落子元素
  • :nth-of-type 选择器,恩……怎么讲呢?限制条件少点~~

    我们把上面的实例稍作修改,就可以看到这两个选择器之间的差异表现了,如下HTML代码:

    <section>
        <div>我是一个普通的div标签</div>
        <p>我是第1个p标签</p>
        <p>我是第2个p标签</p>  <!-- 希望这个变红 -->
    </section>

    还是与上面例子一致的CSS测试代码:

    p:nth-child(2) { color: red; }
    p:nth-of-type(2) { color: red; }

    这时候两个选择器所渲染的结果就不一样了。

    p:nth-child(2) 悲剧了,其渲染的结果不是第二个 p 标签文字变红,而是第一个 p 标签,也就是父标签的第二个子元素。如下效果截图:

    您可以狠狠地点击这里: :nth-child测试demo2

    p:nth-of-type(2) 的表现显得很坚挺,其把希望渲染的第二个 p 标签染红了,如下截图:

    您可以狠狠地点击这里: :nth-of-type测试demo2

    对照上面两个选择器的语义,此处的效果表现差异不难理解。

    对于 p:nth-child(2) 表示这个元素要是 p 标签,且是第二个子元素,是两个必须满足的条件。于是,就是第一个 p 标签颜色为红色(正好符合:p标签,第二个子元素)。如果在 div 标签后面再插入个 span 标签,如下:

    <section>
        <div>我是一个普通的div标签</div>
        <span>我是一个普通的span标签</span>
        <p>我是第1个p标签</p>
        <p>我是第2个p标签</p>  <!-- 希望这个变红 -->
    </section>

    那么 p:nth-child(2) 将不会选择任何元素。

    p:nth-of-type(2) 表示父标签下的第二个 p 元素,显然,无论在 div 标签后面再插入个 span 标签,还是 h1 标签,都是第二个 p 标签中的文字变红。

    这两者的差异用一个跟切合实际的情况比喻就是计划生育查人口:前者是如果是第二胎,且是女孩,罚款!后者是管他第几胎,第二个出身的女孩,罚款!

    二、二次深呼吸,个人体会

    老实讲,对于 :nth-child :nth-of-type 这两个选择器自己用的并不多,对这两个选择器的认识就像是一团浆糊。印象在使用 :last-child 这个类似选择器的时候,出现了没有效果的情况,现在想想,就是因为对选择器的理解不够透彻,所以使用的时候出问题的。

    今天对这两个选择器好好地过了遍之后,个人觉得 :nth-of-type 更彪悍些,不容易出问题,尽管 :nth-child 貌似更常见些。所以以后要选择某某元素下的第几个什么标签,建议使用 :nth-of-type ,因为页面元素插入其他标签啊什么的是比较常见的,如果使用 :nth-child ,选择器可能就是嗝屁。

    不过嘛,世事无绝对,最靠谱的就是对这两个选择器彻彻底底地了解,具体情况具体使用。

    另外一个小小的建议,为了避免出现“尼玛我的:nth-child变成打酱油的不顶鸟用啦!”这样的疑问,最好使用父标签层级限制,而不是当前标签类型限制。如下示例:

    dl :nth-child(2) {  } /* 恩,这个要靠谱些 */
    dd:nth-child(2) {  } /* 这个还需要多多斟酌 */

    当然,还是那句话,要看实际情况如何,没有一劳永逸,一方通行的代码。

    目前各个浏览器对这两个选择器的支持还是挺让人欣慰的,Firefox 3.5+, Opera 9.5+, Chrome 2+, Safari 3.1+, IE 9+都是pass的。外带一提的是jQuery支持基本上大多的选择器,但是,其中并不包括这里的 :nth-of-type ,好像是因为这个选择器用的比较少。如果你想让jQuery也支持该选择器,可以使用jQuery选择器扩展插件,完美支持各个CSS3选择器,要查看此插件请轻轻地点击这里: jQuery CSS3选择器扩展插件

    对了,同等类型的CSS3伪类选择器并不止这两个, :first-of-type , :last-of-type , :nth-last-of-type 以及 :only-of-type 等,以后有机会的话会简单介绍这几个选择器的。

    三、最后的深呼吸,吐气,淡然的结语

    我之前写过一篇颇有争议的文章: 精简高效的CSS命名准则/方法 。根据里面的观点,像 :nth-child :nth-of-type 这类选择器应该少用为妙,一是性能,二是本身限制了内容的重用性。

    但是,还是那句话,凡事无绝对。有时候因为设计的特殊性,我们可能需要有可以方便控制某些特殊元素的方法,例如浮动列表边缘处的列表不能有 margin 值以实现两端对齐效果,等。此时CSS3选择器是权衡下来的最优解决方案。因此,熟悉与理解CSS3中的各个选择器还是有必要的。

    随着IE6~8浏览器缓慢地日落,CSS3的时代可能就会在不知不觉中到来,面对这必然的趋势,我们是时候做好准备了。

    感谢阅读,欢迎纠错。

    参考文章: The Difference Between :nth-child and :nth-of-type

    (本篇完)

    分享 到:

    前者是如果是第二胎,且是女孩,罚款!后者是管他第几胎,第二个出身的女孩,罚款,这句话有些不通畅,我稍微润色一下:
    前者:如果第一胎是女孩,第二胎还是女孩,罚款!
    后者:管他第几胎,如果已经有一胎是女孩,第二胎生的还是女孩,罚款!

    2016年11月10日 15:21

    last-of-type用于评论表单里填写网站的那一个input挺有用,但是我的站却怎么也不能把右边距调到0,查看源码显示,last-of-type根本就没起作用,不知道怎么回事。

    2017年05月7日 18:55

    我也遇到这样的问题,总结起来nth-child 直接根据父元素下子元素的排列顺序选择,无视标签类型。而nth-of-type 是父元素下筛选相同标签的元素根据顺序选择,class直接无视,而没有一个根据class来选择的,如果你找到了纯css方法麻烦告诉我,联系方式lidongjie63@163.com。

    一直以来使用的相安无事。。直到今天我用了类选择器结合:last-of-child,却发现问题相当蛋疼。
    测试发现使用 .class:last-of-child{xxx} 这种方式,并没有按照理想的方式工作。
    感觉是个大坑。。。

    2.想问一下nth是什么词语的缩写呢?
    3.其实这个东西还有一个比较实用的用法:数据列表中的隔行变色
    table tr:nth-of-type{ background-color:#eee;}

    张鑫旭 ,09年 华中科技大学 毕业,现 上海 ,就职于 阅文集团 ,专注 web前端 偏前领域,著有 《CSS世界》 《CSS选择器世界》 《CSS新世界》

    邮箱: zhangxinxu@zhangxinxu.com

    关注我: 微信 微博 掘金 知乎 头条 B站 Gitee

  • 小tip: 如何让contenteditable元素只能输入纯文本 (102)
  • jQuery powerFloat万能浮动层下拉层插件 (52)
  • 以20像素为基准的CSS网页布局实践分享 (49)
  • 小tip: 子元素scroll父元素容器不跟随滚动JS实现 (33)
  • 深入理解CSS中的层叠上下文和层叠顺序 (32)
  • CSS border三角、圆角图形生成技术简介 (20)
  • 大小不固定的图片、多行文字的水平垂直居中 (18)
  • jQuery页面滚动图片等元素动态加载实现 (15)
  • 残忍:IE10↘IE7-IE9 type=email的完全抛弃 (14)
  • 一万年了,CSS text-align-last终于可以用了 (14)
  • 今年热议

  •  
    推荐文章