css_伪类选择器踩坑

1. 问题描述 今日看web前端视频之小米官网实战案例,过程中有一个效果(下拉层),讲师讲解时翻车了,最后讲师发现是css声明部分代码位置写反了,问题解决了,但暂停视频反复检查也不知道具体清晰的原因,虽然效果上可以满足案例效果,但还是一知半解,不知所措,本以为是哪些基础知识掌握不牢,于是想着私下做一个demo研究一下。对于基础阶段,任何问题,任何疑问都要尽可能的解决,不留疑惑。
本以为问题出现在选择器方面,最后发现可能是某些原理之前理解错了,或者没有理解。明白之后,感觉对某些知识有了新的认知。
案例效果具体描述(简化)
HTML代码:

我是box每个人都不得不面对这些问题。 在面对这种问题时, 在这种困难的抉择下,本人思来想去,寝食难安。 非洲在不经意间这样说过,最灵繁的人也看不见自己的背脊。

CSS代码:
/* 为span设置默认样式*/ .show { color: red; background-color: #bfa; } /* 当鼠标移入到 .show时,样式变成小手 */ .show:hover { cursor: pointer; } /* 目的: 当鼠标移入到 .show时,显示 .box2的内容 */ .show:hover ~ .box1 > .box2 { height: 100px; cursor: pointer; } /* 当鼠标移出 .show外,仍显示下拉内容 */ /* 给 .box2设置样式,此时 选择器优先级是 10+10=20 */ .box2:hover { height: 100px; cursor: pointer; background-color: rgb(190, 190, 236); }/* 默认时 .box2的高度为0,且裁剪溢出内容 */ /* 给 .box2设置样式,此时 选择器优先级是 10+10 =20 */ .box1 .box2 { height: 0; overflow: hidden; background-color: orange; }

效果(非预期效果):
css_伪类选择器踩坑
文章图片

预期效果:
css_伪类选择器踩坑
文章图片

2. 问题分析 关于实现非预期效果,首先需要阐述一下关键一步,实现预期效果的需求:
当鼠标移入span文字区域“我是box”时,弹出下拉层,当鼠标移出span时,下拉层继续显示。这要求hover不能仅设置在span,还需设置给这个下拉层本身。问题出现就出现在设置给下拉层本身box2存在某些属性被覆盖了。
/* 当鼠标移出 .show外,仍显示下拉内容 */ /* 给 .box2设置样式,此时 选择器优先级是 10+10=20 */ .box2:hover { height: 100px; cursor: pointer; background-color: rgb(190, 190, 236); }/* 默认时 .box2的高度为0,且裁剪溢出内容 */ /* 给 .box2设置样式,此时 选择器优先级是 10+10 =20 */ .box1 .box2 { height: 0; overflow: hidden; background-color: orange; }

当代码顺序设置如上,经过分析,上面样式表的选择器优先级是20,而下面的选择器优先级也是20,即存在对一个对象(元素)设置样式,优先级相等,根据优先级原则(就近原则),优先使用后面编写的样式表。
模拟一下过程:
  1. 一开始height:0overflow:hidden则元素不显示,自然没有颜色orange
  2. 当鼠标移入时才使用到样式表(hover),此时注意此时才使用height:0这个值,这个值和下面的0冲突了,使用后面的代码的值,所以heigh还是0,并且overflow:hidden,则元素不显示。
这样会导致鼠标移出box2元素还是不显示。
将代码调换顺序,再看预期效果代码:
/* 默认时 .box2的高度为0,且裁剪溢出内容 */ /* 给 .box2设置样式,此时 选择器优先级是 10+10 =20 */ .box1 .box2 { height: 0; width: 100px; overflow: hidden; background-color: orange; }/* 当鼠标移出 .show外,仍显示下拉内容 */ /* 给 .box2设置样式,此时 选择器优先级是 10+10=20 */ .box2:hover { height: 100px; cursor: pointer; background-color: rgb(190, 190, 236); }

模拟过程:
  1. 同样以下面的样式表为先,由于hover没有启用(只有鼠标移入才启用),而默认状态的设置.box1, box2被启用,所以此时height的值是0
  2. 当鼠标移入时,此时的hover才启用,height:100px生效,因为是后面的代码,优先级高,所以采用这个值,效果上,元素显示。
3. 问题解决 将:hover伪类的样式表放置后面
/* 默认时 .box2的高度为0,且裁剪溢出内容 */ /* 给 .box2设置样式,此时 选择器优先级是 10+10 =20 */ .box1 .box2 { height: 0; width: 100px; overflow: hidden; background-color: orange; }/* 当鼠标移出 .show外,仍显示下拉内容 */ /* 给 .box2设置样式,此时 选择器优先级是 10+10=20 */ .box2:hover { height: 100px; cursor: pointer; background-color: rgb(190, 190, 236); }

对于这样的场景需求,首先调整优先级,如果优先级一样,则将伪类:hover的样式表放置后面的位置。
总结分析:
关于这个问题,主要不是优先级问题会踩坑,而是样式表什么时候生效
错误的以为: “当鼠标移入:hover生效,则不用考虑下面的默认样式表,不用和下面的height:0比较”
容易忽视的地方是,以为伪类:hover和其他选择器可以独立处理: “既然:hover是鼠标移入才生效,那等到该移入的时候生效就可以,不用考虑什么优先级”。其实是优先级都是一样的原则,当冲突时都需要抉择,关键就是样式表生效时间,正是:hover是鼠标移入才生效,样式表代码也生效,此时存在样式值的冲突,而不是一开始就有冲突。
所以并不是说当鼠标移入时,就直接生效伪类选择器样式。
注意状态的不同:
  • 伪类选择器是非默认状态,样式表的值当伪类生效才生效。
  • 一般选择器是默认状态,即设置后,立即生效。
??也这说明 选择器并不是选择某个 元素,而是选择 某个状态下的 元素。即元素是存在默认样式的,就存在默认的状态。更贴近点,选择器是选择状态的,状态才有“可选性”,因为元素都是同一个。
css_伪类选择器踩坑
文章图片

这里案例错误,让我意识到了存在默认状态和非默认状态之分,对于选择器的「选择」也有更进一步的理解
【css_伪类选择器踩坑】优先级是当产生了冲突时,才需要考虑优先级(如正确代码的最后的样式表,伪类就不是一开始会和其他样式表产生冲突,哪怕伪类的样式表优先级高,也并不会选择height:100px的,当使用到伪类,值生效,值发生冲突)。
记住当选择器生效时,值才生效,效果才生效。
相关文章:
  1. CSS选择器的优先级(精讲版)
  2. CSS选择器优先级总结 - wanglehui - 博客园
  3. 优先级 - CSS(层叠样式表) | MDN

    推荐阅读