区别:
p:first-child的含义:匹配父元素的第一个子元素、并且这个元素必须是P,如果不是则匹配不到;p:first-of-type的含义:匹配父元素的第一个类型是P的子元素;
最大误区:大部分人刚开始接触时会想当然以为first-child是first-of-type的效果,但其实,first-of-type才是大部分人想要的。
示例:
<style>
p:first-child {color: red}
div:first-of-type{color: blue}
</style>
<section>
<p>第1个元素</p>
<div>第2个元素</div>
<span>第3个元素</span>
<span>第4个元素</span>
</section>
如上面示例:
p:first-child匹配第一个元素;div:first-child匹配不到任何元素;div:first-of-type匹配第二个元素;
其他诸如last-of-type、nth-of-type类似。
再次更新
2021-01-20 再次更新:之前还没注意到,:first-of-type前面写tagName和写其他选择器(比如class或者id等)含义完全不同:
:first-of-type:从所有子元素中查找第一次出现的某种元素类型,例如第一个div、第一个span、第一个p,等等,同一个父元素下可能同时命中多次;tagName:first-of-type:从所有子元素中查找第一个tagName,同一个父元素下最多只可能命中一次;.className:first-of-type:从所有class是className的子元素中查找第一次出现的某种元素类型,例如第一个div、第一个span、第一个p,等等,同一个父元素下可能同时命中多次(特别注意,并不是从子元素中查找第一个.className)。tagName.className:first-of-type:从所有class是className的子元素中查找第一个tagName,同一个父元素下最多只可能命中一次(特别注意,并不是从子元素中查找第一个tagName.className);
举个例子说明第3点:
<style>
.test:first-of-type{color: red;}
.test:last-of-type {color: blue;}
</style>
<section>
<p>第1个p元素</p>
<p class="test">第2个p元素</p>
<div class="test">第1个div元素</div>
<div>第2个div元素</div>
<div class="test">第3个div元素</div>
<p class="test">第3个p元素</p>
<span>第1个span元素</span>
</section>

上面例子中,第1个div元素命中了,但是第2个p元素没有命中,因为它虽然是第一个p.test,但不是第一个p。
再举个例子说明第4点:
<style>
div.test:first-of-type {color: blue;}
</style>
<section>
<div>第1个干扰div元素</div>
<div>第2个干扰div元素</div>
<div>第N个干扰div元素</div>
<div class="test">第1个div.test元素</div>
<div class="test">第2个div.test元素</div>
<p class="test">第1个p元素</p>
<span>第1个span元素</span>
</section>
上面例子中,没有命中任何元素,实际上这种情况也没法使用CSS去命中(假设干扰div数量不确定)
