4

见微知著,从两道有意思的 CSS 面试题,考察你的基础 - ChokCoco

 1 year ago
source link: https://www.cnblogs.com/coco1s/p/16734039.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

见微知著,从两道有意思的 CSS 面试题,考察你的基础

今天在论坛,有看到这样一道非常有意思的题目,简单的代码如下:

<div>
    <p id="a">First Paragraph</p>
</div>

样式如下:

p#a {
    color: green;
}
div::first-line {
    color: blue;
}

试问,标签 <p> 内的文字的颜色,是 green 还是 blue 呢?

有趣的是,这里的最终结果是蓝色,也就是 color: blue 生效了。

4e2f68e9b9ec4b87a365348fe85279be~tplv-k3u1fbpfcp-zoom-1.image

不对,正常而言,ID 选择器的优先级不应该比伪类选择器高么?为什么这里反而是伪类选择器的优先级更高呢?

并且,打开调试模式,我们定位到 <p> 元素上,只看到了 color: green 生效,没找到 div::first-line 的样式定义:

89793ee62c184afbb4d602ff19171d58~tplv-k3u1fbpfcp-zoom-1.image

只有再向上一层,我们找到 <div> 的样式规则,才能在最下面看到这样一条规则:

d3f6fd5473b346848608ec7781dda295~tplv-k3u1fbpfcp-zoom-1.image

因此,这里很明显,是<p> 标签继承了父元素 <div> 的这条规则,并且作用到了自身第一行元素之上,覆盖了原本的 ID 选择器内定义的 color: green

再进行验证

这里,另外一个比较迷惑的点在于,为什么 ID 选择器的优先级比 ::first-line 选择器更低。

我们再做一些简单的尝试:

下面的 DEMO 展示了 ::first-line 样式和各种选择器共同作用时的优先级对比,甚至包括了 !important 规则:

  • 第 1 段通过标签选择器设置为灰色
  • 第 2 段通过类选择器设置为灰色
  • 第 3 段通过 ID 选择器设置为灰色
  • 第 4 段通过 !important bash 设置为灰色

综上的同时,每一段我们同时都使用了 ::first-line 选择器。

<h2>::first-line vs. tag selector</h2>
<p>This paragraph ...</p>  

<h2>::first-line vs class selector</h2>
<p class="p2">This paragraph color i...</p>  

<h2>::first-line vs ID selector</h2>
<p id="p3">This paragraph color is set ...</p>  

<h2>::first-line vs !important</h2>
<p id="p4">This paragraph color is ....</p>  
p {
  color: #444;
}
p::first-line {
  color: deepskyblue;
}

.p2 {
  color: #444;
}
.p2::first-line {
  color: tomato;
}

#p3 {
  color: #444;
}
#p3::first-line {
  color: firebrick;
}

#p4 {
  color: #444 !important;
}
#p4::first-line {
  color: hotpink;
}

CodePen Demo -- ::first-line: demo

看看效果:

f17e819b8b4e4922816d45b7e61dd96c~tplv-k3u1fbpfcp-zoom-1.image

可以看到,无论是什么选择器,优先级都没有 ::first-line 高。

究其原因,在于,::first-line 其实是个伪元素而不是一个伪类,被其选中的内容其实会被当成元素的子元素进行处理,类似于 ::before::after 一样,因此,对于父元素的 color 规则,对于它而言只是一种级联关系,通过 ::first-line 本身定义的规则,优先级会更高!

这也是为什么,在 MDN 文档中,更推荐的是双冒号的写法(当然浏览器都支持单冒号的写法)-- MDN -- ::first-line

57f331a55d1f4b4bad123ae91a84d40e~tplv-k3u1fbpfcp-zoom-1.image

再来一题,MDN 的错误例子?一个有意思的现象

说完上面这题。我们再来看看一题,非常类似的题目。

在 MDN 介绍 :not 的页面,有这样一个例子:

/* Selects any element that is NOT a paragraph */
:not(p) {
  color: blue;
}

意思是,:not(p) 可以选择任何不是 <p> 标签的元素。然而,上面的 CSS 选择器,在如下的 HTML 结构,实测的结果不太对劲。

<p>p</p>
<div>div</div>
<span>span</span>
<h1>h1</h1>

结果如下:

64fe8ae7ded7453aa2c054637f812dd1~tplv-k3u1fbpfcp-zoom-1.image

CodePen Demo -- :not pesudo demo

意思是,:not(p) 仍然可以选中 <p> 元素。是的,在多个浏览器,得到的效果都是一致的。

看到这里,你可以再停一下,思考一下,为什么 <p> 元素的颜色仍旧是 color: blue

这是为什么呢?解答一下:

这是由于 :not(p) 同样能够选中 <body>,那么 <body> 的 color 即变成了 blue,由于 color 是一个可继承属性,<p> 标签继承了 <body> 的 color 属性,导致看到的 <p> 也是蓝色。

我们把它改成一个不可继承的属性,试试看:

/* Selects any element that is NOT a paragraph */
:not(p) {
  border: 1px solid;
}
d483b64db53b476b9e97fff7d3002e37~tplv-k3u1fbpfcp-zoom-1.image

OK,这次 <p> 没有边框体现,没有问题!

因此,实际使用的时候,需要一定要注意样式继承的问题!

本文到此结束,希望对你有帮助 😃

更多精彩 CSS 技术文章汇总在我的 Github -- iCSS ,持续更新,欢迎点个 star 订阅收藏。

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

想 Get 到最有意思的 CSS 资讯,千万不要错过我的 iCSS 公众号 😄 :

image

如果觉得文章对您有用,请随意打赏。您的支持将鼓励我继续创作!

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK