论坛里有人问了一个关于 影响未悬停项目 的问题。 他们想要的效果是,有一个无序列表,当鼠标悬停在列表项上时,所有列表项都会变暗(降低不透明度),除了被悬停的那个。
这可以通过 CSS 使用伪选择器来实现。
ul li:not(:hover) { opacity: 0.5; }
但是我们知道 伪选择器 的跨浏览器支持不是很好。 而且,不透明度 也不好。 jQuery 在缓解跨浏览器问题方面非常出色,所以我认为我可以尝试一下。 在尝试的过程中,我获得了一段不错的学习旅程。
我的第一个想法是,我需要编写一个选择器来选择所有列表项,除了当前被悬停的那个。 我最近因为另一个原因遇到了这个问题,并且为此写了一个代码片段:从选择器中排除 this。 在这个例子中
$("ul li").not(this).css("opacity", "0.5");
我们只需要把它包装在一个悬停函数中。 最明显的方法是
$("li").hover(function() {
$("li").not(this).css("opacity", 0.5);
}, function() {
$("li").not(this).css("opacity", 1);
});
但是我一直被教导,像这样绑定事件效率低下,因为 1) 它需要为每个元素单独创建一个事件处理程序,以及 2) 在此代码运行后附加到页面的新元素需要重新绑定。(更不用说,你肯定想缓存上面那个选择器了var $listItems = $("li");).
所以我认为我会直接使用新的 delegate 函数,我们之前在 CSS-Tricks 上已经多次提到过它。 这一点很棒,因为它解决了上面提到的两个问题。 这是我第一次(完全错误的)尝试。
$("ul").delegate("li", "hover", function() {
$("ul li").not(this).css("opacity", "0.5");
}, function() {
$("ul li").not(this).css("opacity", "1");
});
不要在家尝试这个,它不会工作。 为什么不行?James Padolsey 提醒我,“hover” 不是一个事件。 它是一个 jQuery 函数,但不是一个真正的事件。 你可以把它与 delegate 一起使用,但不能使用我尝试的那种语法。 Delegate 期望只有三个参数:元素、事件和函数,而不是像我传递的那样四个参数(假设它会知道最后一个函数应该是一个回调/mouseleave)。
然后,下一个最明显的转换变成了这样
$("ul").delegate("li", "mouseenter", function() {
$("ul li").not(this).css("opacity", "0.5");
}).delegate("li", "mouseleave", function() {
$("ul li").not(this).css("opacity", "1");
});
这次使用两个 delegate 函数,使用真正的事件来完成任务。 这样可以,但我们可以通过将这两个事件映射到一个 delegate 函数,然后只测试触发了哪种类型的事件来提高效率。David Link 有这个想法
$("ul").delegate("li", "mouseover mouseout", function(e) {
if (e.type == 'mouseover') {
$("ul li").not(this).css("opacity", "0.5");
} else {
$("ul li").not(this).css("opacity", "1");
}
});
而 James Padolsey 有一个更简洁的版本
$("ul").delegate("li", "mouseover mouseout", function(e) {
$("ul li").not(this).css("opacity", e.type == 'mouseover' ? 0.5 : 1);
});
jQuery 的 live() 函数在这里也是一个不错的选择,但它也有一些怪癖。 事实证明,你可以将“hover”传递给 live,但你仍然只能提供一个函数。 该函数将在 mouseenter 和 mouseleave 事件上触发,并且你必须执行 event.type 测试(如上所述)来确定是哪个事件并相应地做出反应。 感谢 Paul Irish 和 Jeffrey Way 提供的这个方法。
还记得最开始的那个 CSS 选择器吗? 我们也可以在 jQuery 中使用它
$("ul li:not(:hover)").css("opacity", "0.5");
真是段旅程啊! 就像网络上的所有事物一样,总有多种方法可以 解决问题。
不错的文章 - 我只想提一下,delegate 实际上已经添加了对 hover 的支持(我相信是在 1.4.1 中)。
它本质上只是将 mouseover 和 mouseout 都映射到回调函数(因此你仍然需要区分事件类型,就像你的示例中一样)。 这是一个简单的示例:http://jsbin.com/idibu/edit
Chris,你所有的文章都是像这样实时撰写的吗?
当我觉得是个好主意的时候,我会这样做。
从别人的错误中学习。 你不可能活得足够长去犯下所有的错误。
–埃莉诺·罗斯福
糟糕……刚用 1.4.1 尝试了一下,失败了。 一定是 1.4.2 中添加的功能。
是的。
delegate() 是 1.4.2 中的新功能。
我希望同样的功能可以更轻松地实现,并且无需像这样使用 delegate
很好地使用了 .siblings()。 但我认为这会导致需要与列表项数量一样多的事件处理程序,而 delegate 正是为了避免这种情况。
但我还听到一些传言说 hover 函数会自动使用 live? 这是真的吗?
Hover 不会自动使用 live,所以正如你所说,它会为每个列表项创建一个事件处理程序(技术上是两个)。
现在 iPhone/iPad 不支持 mouseover 了,它是不是已经过时了? 替代方案是什么?
例如,我想创建一个“剧透”类,在鼠标悬停时显示。 是否有适用于基于鼠标的界面和触摸界面的解决方案?
嗯,一个未经测试的 CSS 想法
li:hover ~ li { ... }
你认为它可能有效吗?
无效;仅选择后面的兄弟元素,而不是左侧元素之前的兄弟元素 :(。
ul:hover li { opacity:0.5; }
ul:hover li:hover { opacity:1; }
这将完全实现你所说的……所有列表项都会变暗 50%,除了你当前悬停的列表项……不需要花哨的伪选择器或 JS。
好吧,也许我没有说清楚,但重点还在于,当没有鼠标悬停在任何列表项上时,所有列表项都是完全不透明的。
但是使用“ul:hover”而不是“ul”会使列表项仅在列表悬停时变为半透明,从而满足了这个要求。
它仍然存在浏览器兼容性问题,因为不透明度,以及某些浏览器不支持非锚元素的悬停。 因此,需要使用 jQuery 来解决浏览器兼容性问题。
这只会使其他列表项在你将鼠标悬停在 UL 上时变为透明。
当然,它在 IE6 中不起作用(无法检测列表或列表项的悬停)。 但对于不透明度,我们只需使用 IE 过滤器……
在我失败之后,我想出了同样的想法(唯一的区别是:ul li:hover…)。 因此,我完全同意你的观点,Sean。 想法不错。
除了浏览器兼容性问题外,CSS 实现了所需的功能,它是一个快速的解决方案。
不透明度可以通过条件注释、ms-filter 和 csshover.htc 来管理,用于非锚元素的悬停 :)。 工作量稍微多一点,但文件大小更小,并且在某些浏览器中减少了 HTTP 请求。 应该可以在 IE6 到 IE8 中正常工作。
我本来想发布相同的代码片段,它看起来不那么像黑客方法。 Chris,我认为你可能过度思考了这个问题。
也许你需要所有这些 JS 来支持 IE6,但我已经不再识别/支持那个“浏览器”了。
感谢你的撰写。 很高兴我的问题引发了一篇很棒的文章。 :)
等一下,Chris,这里有一些你还没有完全想清楚的地方。 你绝对必须使用$(this).siblings()(就像 abhishek 的示例中那样,但最好与delegate
) 像这样为什么?
好吧,原因是当页面上存在多个列表时,你的所有示例都会失效,因为它们不是相对于li或ul进行操作,而是对页面上的每个列表进行操作!
查看这些示例,你就会明白我的意思:你的版本(糟糕) 和 修复后的版本(耶)。
当然,这是一个很酷的增强功能……整个概念一开始就非常抽象,我们并没有真正定义多列表时的期望行为,所以我并没有太担心它。我能想到一些情况下,你可能希望得到任何一种结果。
Chris,我发现,总的来说,使用上下文感知的相对选择器,并在可能的情况下从 $(this) 开始,可以使代码更容易维护……我知道这两种方法都可以争论,但对于像这样的行为,每个列表而不是全局的,似乎是最常见的使用场景。
尽管这个问题的具体情况存在主观性,但我最近最关心的问题之一仍然是:我们这些写文章的人如何以一种不仅能让人们思考这个概念,还能让人们思考实现方式的方式来呈现概念和示例。
我已经考虑写一篇关于这方面的文章有一段时间了,也许我应该开始写了……别介意我! :)
我想我们的大脑在共享。我过去几天一直在诅咒鼠标事件,试图让 live() 和 hover 与多个 jsonp 对象很好地配合使用。我最终放弃了,并将其改为一个普通的点击事件。
不错的帖子,在网页开发中,你确实可以用大约一百万种方法来做任何你想做的事情,并且进行大量的探索来找到最有效的方法是非常棒的。
但是,我确实需要更正你在这里说的一件事
你在第一部分是正确的,hover 是一个 jQuery 函数而不是一个事件,但在第二部分上你是错误的。Hover 确实可以与 delegate(以及 live)一起使用。你只需要以不同的方式使用它。
事实上,hover 函数在 jQuery API 文档的 delegate() 中被特别使用:https://api.jqueryjs.cn/delegate/
在这种情况下,我将选择渐进增强:只需使用 CSS 实现它,并且对不支持它的浏览器毫不留情。
我们应该通过降低不支持浏览器的体验来表明一些浏览器很糟糕。这将推动供应商改进,并推动用户升级。
相反,我们再次延长了问题,使用 JS 技巧来完成不应该在 JS 中完成的事情。
对这篇文章和解决方案背后的巧妙之处没有不敬。我也理解客户如何将你推向这样的解决方案。
我使用了
$("ul").delegate("li", "mouseover mouseout", function(e) {
$("ul li").not(this).css("opacity", e.type == 'mouseover' ? 0.5 : 1);
});
IE(当然)会弄乱我的菜单项的对齐方式。它还会导致文本看起来参差不齐。
太棒了,伙计,鼠标悬停和 hover 函数我都刚刚学习 CSS
对此进行一个小的增强,你也可以为此添加 webkit 过渡(对于支持它的浏览器)
ul {-webkit-transition: all 0.2s ease-out;}
你们对 javascript 的了解比我多得多。
我发现 javascript 是一项非常有用的技能,所以我才刚刚开始学习。
我使用 wordpress 作为 CMS,我一直在尝试将一些 javascript 实现到我的主题(基于 starkers 构建)中,并且当按照网上的教程将 JS 实现到我的网站时,我发现我无法使其工作。
这看起来像一个非常酷的技术,我想尝试一下。**我把所有代码放在哪里???** 我不知道从哪里开始,也不知道如何使它工作。
实际上我指的是 jquery……这说明我有多需要帮助!
这是一个非常有趣的想法,从未想过使用这样的效果。但我认为看起来会非常不错!
jQuery 非常好,但我认为对于这种效果来说有点矫枉过正,浏览器的支持正在不断增加,随着 IE9 的发布,我认为 IE6 将会寿终正寝(希望如此!)。
就我个人而言,我将坚持使用上面提到的 CSS 编码,刚刚使用 Sean 发布的代码进行了一个快速测试
ul:hover li { opacity:0.5; }
ul:hover li:hover { opacity:1; }
它运行得非常好。如果你使用的是不支持 opacity 的浏览器,那么你将看不到效果,但在我看来,这不会对你的设计造成太大的损害……只需为那些使用不错浏览器的用户增强它!
感谢你的想法以及人们提供的有用回复!
这是一种非常有见地且不同的向元素添加不透明度的方法。
这是一篇有趣的文章,但我仍然不明白为什么你要这样做,而不是像上面提到的那样做。
ul:hover li { opacity:0.5; }
ul:hover li:hover { opacity:1; }
也许可以添加 JS 来向 ul 和 li 添加类,而不是使用伪类 :hovers,但这已经足够了。
就像你试图用你的左手从后面摸你的右耳一样!解决的问题太多,而解决的太少。保持简单。:]
这一点现在已经被提到 3-4 次了……为了清楚起见,这并没有按照它被要求的方式工作。这将使所有列表项都变为透明,直到它们被悬停。这不是目标。目标是使它们在被悬停之前完全不透明,然后为其他列表项提供 50% 的透明度。查看本文中的第一行 CSS,它可以解决这个问题。
此外,这里的重点是一个关于学习新概念和更好地做事方法的理论/抽象旅程,而不是一个超级实用的现实世界示例。
探索事物当然很棒,这里不是在抨击。
只是想指出它不会默认使所有项目都变为透明。只有在列表被悬停时才会,因此是
ul:hover li
哦,是的,没错,我错了。尽管如此,本文中的第一行 CSS 还是用一行代码实现了相同的功能,并且我认为它具有相同的浏览器兼容性水平。
但是,如果你只是添加 JS 来添加类,那么浏览器的兼容性将会大大提高……因为你不会使用伪类 :not。
如果我必须这样做,我会这样做的。XD
如果只有鼠标悬停的 li 保持可见是必要的,那么
ul:hover li {
opacity: 0;
}
ul:hover li:hover {
opacity: 1;
}
显然 IE6 不支持,也没有动画(当然除了 -webkit-transitions),但这可以完成工作……
对不起,可能我错过了目标
对不起,我刚刚看到它已经被说过了,抱歉 ^^
很棒的文章,这是一种获得这种效果的好方法。迫不及待想尝试一下。
谢谢。