mouseover()和mouseout()问题 jQuery add/removeClass函数

7

我正在尝试使用mouseover、mouseout、addClass和removeClass等方法创建一个简单的鼠标悬停效果。基本上,当用户将鼠标悬停在元素上时,我想应用不同的边框(1像素虚线灰色)。初始状态为“1像素实线白色”。我有一个名为“highlight”的类,其中只有“border: 1像素虚线灰色”。我想在mouseover时添加该类,并在mouseout时删除它,但除非我在“highlight”类中使用!important,否则无法获得我想要的效果。


1
顺便说一句,Brian:既然你正在使用jQuery,你可能想要查看hover事件辅助方法:http://docs.jquery.com/Events/hover - Shog9
7个回答

14
似乎你的javascript已经正常工作,只是CSS规则的特异性存在问题,这就是为什么!important可以使其工作的原因。
你只需要让突出显示的CSS规则比非突出显示的规则更具体即可。
#someItem ul li { /* Specificity = 102 */
    border-color: white;
}

.highlight { /* Specificity = 10 -- not specific enough! */
    border-color: grey;    
}

#someItem ul li.highlight { /* Specificity = 112 -- this will work */
    border-color: grey;    
}

进一步解释:
假设你的HTML相关部分如下所示:

<div id="someItem">
    <ul>
        <li>Item 1</li>
        <li>Item 2</li>
        <li>Item 3</li>
    </ul>
</div>

并且你有这个CSS:

#someItem ul li {
    border: 1px solid white;
}
.highlight {
    border-color: grey;
}

目前,#someItem div 中的 ul 所有列表项都具有白色边框,并且没有任何类名为 highlight 的元素,因此没有灰色。

通过您想要的任何方式(在 jQuery 中使用悬停事件),您可以向其中一个项目添加类:

$(this).addClass('highlight'); 

HTML现在看起来应该是这样的:
<div id="someItem">
    <ul>
        <li>Item 1</li>
        <li class="highlight">Item 2</li>
        <li>Item 3</li>
    </ul>
</div>

到目前为止,您的Javascript和HTML都运行良好,但是您没有看到灰色边框!问题出在CSS上。当浏览器尝试决定如何对元素进行样式设置时,它会查看所有不同的选择器来针对一个元素和在这些选择器中定义的样式。如果有两个不同的选择器都定义了相同的样式(在我们的例子中,边框颜色存在争议),那么它必须决定应用哪种样式以及忽略哪种样式。它通过所谓的“特异性”来实现这一点,即选择器的特异性。正如HTML Dog article所述,它通过为选择器的每个部分分配一个值来完成这项工作,具有最高得分的选择器获胜。得分如下:
- 元素选择器(例如:“ul”,“li”,“table”)= 1分 - 类选择器(例如:“.highlight”,“.active”,“.menu”)= 10分 - ID选择器(例如:“#someItem”,“#mainContent”)= 100分
还有一些其他规则,例如关键字!important和内联样式,但这对于本“课程”大多数都不相关。您唯一需要知道的另一件事是,如果两个选择器具有相同的特异性,则文件中后定义的选择器获胜。
回到您的问题,考虑到我们之前的CSS,我们可以看到为什么它仍然没有灰色边框:
#someItem ul li = id + element + element = 100 + 1 + 1 = 102分
.highlight = class = 10分
如前所述,解决方法是创建更具体的选择器:
#someItem ul li.highlight
   = id + element + element + class
   = 100 + 1 + 1 + 10
   = 112 点
并回答您在评论中的问题,您不需要更改任何javascript或HTML即可使其正常工作。如果您分解该选择器,它的含义是:

查找ID为“someItem”的元素,在其中查找ul元素,然后查找带有“highlight”类的li元素。

现在,鉴于您之前简单的addClass()调用,li满足这些条件,因此边框应变为灰色。

@nickf: 我觉得你这里有点眉目了。那我该如何使用 addClass 方法呢?我已经修改了我的特异性,但现在,在 jQuery 中如何引用这个类呢? - Brian David Berman
我认为你的jQuery没问题,只需要使用.addClass('highlight')和.removeClass('highlight')就足够了,如果你的CSS构建得正确的话。 - nickf
同意。最具体的CSS规则将优先生效。如果您使用“#ItemList ul li”设置基础样式,那么使用“#ItemList ul li.highlight”设置悬停样式可以确保更高的特异性。 - Cheekysoft
@Cheekysoft:在jQuery中使用addClass/removeClass方法时,如何指定#ItemList ul li.highlight? - Brian David Berman
像我说的那样,您根本不需要更改您的Javascript。我会编辑答案以进一步解释。 - nickf

6
从Jquery 1.3.3开始,您可以更简单地执行此操作。将提供一个增强版的.toggleClass(),非常强大。
如果您不需要将其拆分为函数,则可以从1.3.3开始简单地执行以下操作:
$(".myclass").hover(function(){ $(this).toggleClass('highlight'); });

如果您需要使用!important,则可能需要让您的突出显示类更加具体(请参见CSS特异性)。


1

我猜测您在元素上使用了内联样式来设置初始样式:

<style type="text/css">
  .hover { border: 1px dashed gray; } /* will never apply */
</style>

...

<!-- this style has priority over class styles! -->
<div style="border: 1px solid white"> 
...
</div>

这将覆盖使用类应用的样式... 因此,不要使用内联样式,只需使用不同的初始类来应用初始样式:

<style type="text/css">
  .normal { border: 1px solid white; }
  .hover { border: 1px dashed gray; }
</style>

...

<div class="normal">
...
</div>

好的观点。只是为了澄清提问者,使用jQuery中的css()方法会应用内联样式。 - TM.
我没有使用内联样式。原始样式是通过样式表应用的,标签或css()方法中没有应用任何样式,但是通过addClass()添加另一个类不会覆盖已在原始样式中定义的样式规则,除非我使用!important。 - Brian David Berman
然后确保原始样式的规则要么不够具体,要么在样式表中位于突出显示样式之前。 - Shog9

0

或者您可以使用简单的CSS来完成:

#namehere { border: 1px solid #fff; }
#namehere:hover { border: 1px dashed #aaa }

1
我不确定这是否是跨浏览器的解决方案(尚未确定),但话说回来,我从未说过它必须是。 - Brian David Berman

0
你考虑过纯CSS的方法吗?
例如:
someClass {
    border: 1px solid white;
}

someClass:hover {
    border: 1px dashed gray;
}

hover 伪类将为您提供所需的行为:当用户将鼠标悬停在元素上时,它将使用较低的样式,否则它将使用第一个样式。

注意:正如某人评论的那样,在 IE 中,这对于非 a 元素不起作用。但是,在 Chrome、Firefox、Safari 和 Opera 中,它确实可以工作。

在 IE8 和 IE7 标准模式下,它也适用于任何元素。虽然我没有 IE6 进行测试。


这在IE6中不起作用,我相信。只有a元素可以在其中悬停。 - Paolo Bergantino
@Paolo 似乎在除了 IE 之外的所有浏览器中都能正常工作,适用于任何元素类型。 - TM.
@Paolo,看起来你说了两件事情。首先,你说它不能在IE6中工作。然后你又说hover只对a元素有效。抱歉我误解了,但是我认为你是在说它仅适用于任何浏览器中的a元素,并且在IE6中根本不起作用。 - TM.
当我说“可以在其中悬停”时,我的意思是IE6中的情况。 - Paolo Bergantino

0

这是我使用的一个悬停效果示例:

$(".myclass").hover(jbhovershow,jbhoverhide);


jbhovershow = function () {
            $(this).addClass("jimtest");
          }; 

jbhoverhide = function () {
            $(this).removeClass("jimtest");
          }

你真的不需要将这么简单的东西分成不同的函数。

我怀疑你的问题可能是与 CSS 冲突有关 - 尝试通过硬编码或点击应用你的高亮类,并查看是否确实起作用。

希望对你有所帮助。

Jim


0

CSS:

div.target {
    border: 1px solid #000000;
}

div.target-hover {
    border-color: #ff0000;
}

JS:

$("div.target").hover(
    function () {
        $(this).addClass("target-hover");
    },
    function () {
        $(this).removeClass("target-hover");
    }
);

我通常这样做。(可以有更多的选项)


这正是我正在做的,除了在div.target-hover中我有“border: 1px dashed gray”。除非我出于某种原因添加!important,否则边框不会覆盖原始设置。 - Brian David Berman
很奇怪,你是如何将第一个类添加到元素中的? - Chad Cache
@Chad 这是来自一个名为“#ItemList ul li”的规则,我已经将其样式设置为“border: 1px solid white”。我有一个名为“highlight”的类,它只有“border: 1px dashed gray”,我想要切换它。 - Brian David Berman
你是这样定位它的吗?$("#ItemList ul li").hover - Chad Cache

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接