1. 问题描述

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

本以为问题出现在选择器方面,最后发现可能是某些原理之前理解错了,或者没有理解。明白之后,感觉对某些知识有了新的认知。

案例效果具体描述(简化)

HTML代码:

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

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;
}

效果(非预期效果):

image

预期效果:

image

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是鼠标移入才生效,样式表代码也生效,此时存在样式值的冲突,而不是一开始就有冲突

所以并不是说当鼠标移入时,就直接生效伪类选择器样式。

注意状态的不同:

  • 伪类选择器是非默认状态,样式表的值当伪类生效才生效
  • 一般选择器是默认状态,即设置后,立即生效。
⚠️也这说明选择器并不是选择某个元素,而是选择某个状态下的元素。即元素是存在默认样式的,就存在默认的状态。更贴近点,选择器是选择状态的,状态才有“可选性”,因为元素都是同一个。

image

这里案例错误,让我意识到了存在默认状态非默认状态之分,对于选择器的「选择」也有更进一步的理解

优先级是当产生了冲突时,才需要考虑优先级(如正确代码的最后的样式表,伪类就不是一开始会和其他样式表产生冲突,哪怕伪类的样式表优先级高,也并不会选择height:100px的,当使用到伪类,值生效,值发生冲突)。

记住当选择器生效时,值才生效,效果才生效。

相关文章:

  1. CSS选择器的优先级(精讲版)
  2. CSS选择器优先级总结 - wanglehui - 博客园
  3. 优先级 - CSS(层叠样式表) | MDN

nathannie
15 声望1 粉丝

better and better, day by day.