HTML Dog

跳至导航

Sons of Suckerfish

作者:Patrick Griffiths 和 Dan Webb

Sons of Suckerfish 是一系列文章,旨在讲解如何最好地创建 :hover:active:focus:target CSS 伪类效果,以便在几乎任何浏览器上对几乎任何 HTML 元素实现一些有趣的效果。嘿,孩子们——Suckerfish 不仅仅用于下拉菜单(尽管它也是一种非常棒、轻量级的制作方法)。

早在 2003 年 11 月,“Suckerfish Dropdowns”发布在 A List Apart 上。自那时起,由于其轻量级、符合标准、可访问且跨浏览器的特性,它已成为应用下拉菜单的一种流行方法。

基本思想是,您使用 CSS 构建一个下拉菜单,然后附加一小段 JavaScript 来模拟某些浏览器(主要是 Internet Explorer)不支持的 :hover 伪类。当然,这种模拟 :hover 的方法可以用在任何元素上,而不仅仅是下拉菜单。

在开发新的、改进的 Suckerfish Dropdowns 方法时,我们有点得意忘形,扩展了这个想法并使其更加通用。所以现在,不仅有一个全新改进的 Suckerfish Dropdowns 版本,其改进的 Suckerfish :hover JavaScript 小到您几乎需要电子显微镜才能看到它,还有几个“兄弟”也出现了,用于模仿其他动态伪类——:focus:active:target

这套文章包含七篇文章

The Suckerfish

好了。基本上,在 Mozilla、Opera 和 Safari 等浏览器中,您可以使用 :hover:active:focus 来实现 CSS 标准所期望的效果。问题是,当涉及到链接以外的任何内容时,Internet Explorer 会忽略这些伪类(并且它根本不喜欢 :focus)。为了解决这个问题,我们可以使用类似于以下内容的 JavaScript。


sfHover = function() {
	var sfEls = document.getElementById("nav").getElementsByTagName("LI");
	for (var i=0; i<sfEls.length; i++) {
		sfEls[i].onmouseover=function() {
			this.className+=" sfhover";
		}
		sfEls[i].onmouseout=function() {
			this.className=this.className.replace(new RegExp(" sfhover\\b"), "");
		}
	}
}
if (window.attachEvent) window.attachEvent("onload", sfHover);

这是在 Suckerfish :hoverSon of Suckerfish Dropdowns 文章中使用的代码。

该函数在页面加载后启动,并遍历相关元素(在上面的示例中是 'nav' 元素下的 li 元素),并在调用特定事件处理程序(在本例中是 onmouseover)时添加一个类名,并在调用另一个事件处理程序(在本例中是 onmouseout)时移除该类名。通过对 CSS 进行一点调整,这基本上可以用来模拟伪类的行为(例如 :hover)。

Suckerfish :hoverSuckerfish :activeSuckerfish :focus 之间的主要区别仅仅是使用的事件处理程序(Suckerfish :target 稍微复杂一些,并在该文章中有详细解释)。

一旦 Suckerfish 设置好,您所需要做的就是用标准的类选择器来复制伪类选择器。例如:


li:hover { display: block }

变成


li:hover, li.sfhover { display: block }

与 Suckerfish 的原始版本相比,主要变化是函数调用使用了仅限 IE 的 window.attachEvent() 方法,以确保只有 IE 运行它。这比旧的 document.all&&document.getElementById 更精确,并且还可以让您轻松地将其他事件添加到 onload 中,而不会中断 Suckerfish 的运行。

它查找要附加行为的元素的方式也已更改。现在收集容器下的所有元素,而不仅仅是第一个子元素,这更加灵活,对于例如多级 Suckerfish Dropdown 的工作至关重要。

最后,现在使用正则表达式来删除最初添加的类,以提高准确性。使用旧的 Suckerfish,在极不可能的情况下,如果您的元素已经具有像 'sfhovermonkeymonkey' 这样的类名,并且 Suckerfish 被指示删除 'sfhover',它将留下一个无用的类 'monkeymonkey'。

上面的示例特别查找 ID 为 'nav' 的元素内的 li 元素。但是,您可以修改 JavaScript 的第二行,使其更具体或更通用。例如,通过像这样调整第二行:


var sfEls = document.getElementsByTagName("LI");

Suckerfish 将适用于页面上的所有 li 元素,无论它们位于哪个元素中。

这种更通用的方法可能看起来更可取,因为您可以拥有更通用的代码,但这也会增加浏览器的负担,因此您越具体(例如,如果您知道只想将其应用于具有特定 id 的元素中的 li 元素),效果就越好。

Suckerfish vs. .htc

在蓝色角落,我们有 Suckerfish,它是原始的轻量级、可访问、跨浏览器、符合标准的 :hover 模拟。在红色角落,我们有 '.htc'——通过 CSS 访问的 JavaScript 文件来模拟 :hover

叮叮!

Suckerfish 立即对 .htc 的有效性造成了沉重打击——.htc 根本不是符合标准的 CSS。

哦…… .htc 在无需额外选择器的情况下,巧妙地出击……

Suckerfish 在场地周围跳跃。他比对手轻巧得多。

而且哦!IE 5.0 的上勾拳!这是 .htc 无法企及的,而 Suckerfish 可以无缝地在 IE 5.0 中工作。

.htc 晕头转向!比赛结束!Suckerfish 以积分获胜!TKO!

继续!

这就是理论。要更深入地了解如何实现这一切,并包含一些示例,请查看 Suckerfish :hoverSuckerfish DropdownsSuckerfish :focusSuckerfish :activeSuckerfish :target 以及如何将它们与 Suckerfish Shoal 结合使用。