Doug Neiner 在今年的 前端设计大会 上做了一个精彩的演讲。他在演讲中涵盖了很多内容,您可以在 他的幻灯片 中看到,但我想特别强调其中一点:他在演示中处理弹出信息的方式。我将尝试重新解释一下……
假设我们的目标是:**将鼠标悬停在图像上以显示额外信息**(如图像标题和 URL)。

非常简单的设计模式,对吧?其实不然。有很多细微之处需要考虑。让我们从最简单的方法开始,然后逐步改进。
最简单的方法:使用 CSS 隐藏/显示
如果我们的标记是
<figure>
<img src="image.jpg" alt="cool image">
<figcaption>
<h3>Cool Image</h3>
<a href="http://coolplace.com">http://coolplace.com</a>
</figcaption>
</figure>
我们将使用<figcaption>
作为弹出信息。默认情况下我们将隐藏它,然后在鼠标悬停在图像上时显示它。
figcaption {
display: none;
}
figure:hover figcaption {
display: block;
}
但是……它太**突然**了。
淡入/淡出
我们可以使用 CSS 过渡来缓和它。
ficaption {
opacity: 0;
transition: opacity 0.3s ease-out;
}
figure:hover figcaption {
opacity: 1;
}
如果需要,我们可以通过 应用不同的持续时间 来使其更加花哨。
但是……即使我们只是快速地将鼠标移过图像,也可能会弹出弹出窗口,而我们可能并不想看到弹出窗口。
“悬停意图”
如果我们使用 JavaScript,可以实现更花哨的效果。有一个名为 hoverIntent 的 jQuery 插件,它可以帮助防止不必要的悬停行为。它在事件触发之前会引入一点延迟,因此快速将鼠标悬停在事物上不会触发弹出窗口,但如果放慢速度并在图像上停留,则会触发。
您可以像这样应用它。
$("figure").hoverIntent(function() {
$("figcaption", this).fadeTo(400, 1);
}, function() {
$("figcaption", this).fadeTo(400, 0);
});
但是……现在所有图像都使用了 hoverIntent,这意味着**如果要专门浏览图像并查看信息,则看到弹出窗口的轻微延迟可能会非常烦人**。正如 Doug 所说,“我的大脑思考速度比这快。”
最后:非常棒的方式 (doTimeout)
我们喜欢 hoverIntent 的第一部分,即快速鼠标悬停不会触发弹出窗口,但一旦我们触发了一个弹出窗口,我们就希望后续的弹出窗口快速出现,没有任何延迟。如果用户离开图像区域一段时间,则会再次引入延迟。
这使用了 Ben Alman 的 doTimeout 插件。不可否认,这有点复杂。
var li_cache, over = false;
$( "figure" )
.delegate( "figcaption", "mouseenter", function ( e ) {
var $li = $( this ), speed;
if ( li_cache === this && over ) {
$.doTimeout( "hoverOut" );
return;
}
if ( over ) {
$.doTimeout( "hoverOut", true );
speed = 0;
} else {
$.doTimeout( "hoverOut" );
speed = 500;
}
$.doTimeout( "hoverIn", speed, function () {
over = true;
$li.find( "div" ).fadeTo( 200, 1.0 );
});
})
.delegate( "figcaption", "mouseleave", function ( e ) {
var $li = $( this );
$.doTimeout( "hoverIn" );
$.doTimeout( "hoverOut", 500, function () {
over = false;
$li.find( "div" ).stop( true ).fadeOut();
});
});
非常棒。这以一种自然而微妙的方式改善了弹出信息的显示,以至于它有点可惜实现起来如此困难。但它值得一试。
Doug 的 GitHub 仓库
获取此 GitHub 仓库。Doug 做了很棒的工作,它很有教育意义。您可以通过注释/取消注释一些函数名称来查看所有不同悬停功能的演变过程。除此之外,此示例还涵盖了使用 jQuery 模板、“Mockjax”(劫持 AJAX 请求以进行本地开发)等。
说真的,我甚至不会发布一个实时演示,请下载他的仓库并在浏览器中打开 index.html 文件。
即使我理解在 JS 中执行它更简单,您也可以
#1. 设置一个超时,在几百毫秒后添加一个类名。
#2. 使用 CSS 动画,从 0% 到 30% 不做任何操作,从 30% 到 100% 执行所需的动画(然后可以硬件加速,而 JS 则不能)。
#3. 使用 transition-delay。
是的,查看 transition-delay http://www.w3.org/TR/css3-transitions/#the-transition-delay-property-
这很酷,伙计们,感谢你们的重申(我在文章中简要提到了这一点),但它与 Doug 的最终示例并不完全相同或不那么优雅。
区别在于,只有第一次悬停有延迟,后续悬停没有延迟,除非您离开该区域一段时间。
这就是它的全部魅力所在。
呵呵呵……
这可能是错误的……
http://jsbin.com/orineq
您写了两次 ficaption。
很棒的教程和一些好点子。
我对实现悬停约定有点矛盾,因为触摸屏交互模型的原因。
在 iPad 出现之前,我非常支持悬停菜单和其他悬停约定,但现在我发现悬停会导致触摸屏用户的用户体验不那么流畅。
不错,谢谢 Chris。
作为 jQuery 的新手,如果在您未来的某些代码片段中,您可以在重要的部分包含一两个内联注释,以帮助理解这些行的作用,那就太好了。
干杯
不错!请注意,您可以使用 transition-delay 属性产生与 hoverIntent 相同的效果,例如
我在文章中简要提到了 transition-delay,但它存在与 hoverIntent 相同的问题:它应用于每次鼠标悬停。
Doug 做的非常酷的事情是为第一次悬停应用延迟,然后为后续悬停移除延迟。
Chris,您的姓氏应该是“Rock”。因为您就是!
另一方面,完全偏离主题。是否可以通过某种方式链接伪类。有点像这样
那应该是一个问号:“……链接伪类**?**”
或者更糟糕的是,这是否可能
cnwtx 提到的
p:after:before
目前还不可行。精彩的文章!
谢谢,您帮了大忙。
您可以提供一个演示吗?
谢谢
下载文章底部链接的 GitHub 仓库。在浏览器中打开 index.html 文件。这是 Doug 的作品,我想确保他对人们看到的内容拥有 100% 的控制权。
不错的技巧,而且对我的时机很好。
我一直在为客户的网站努力实现这种效果。与我尝试过的其他技术相比,这种方法看起来更易于实现,并且更“完善”和专业。
感谢你的分享,Chris。
这真的很容易理解,谢谢
实际上有一段时间没法运行,但这只是我自己的问题
再次感谢
我喜欢你提供了一些替代技术来实现这一点。我在一些项目中大量使用了 hoverIntent,但它并不适合这种情况。
我真的很喜欢这个网站:http://frontenddesignconference.com/
太棒的想法了!<3 我喜欢它
很酷的东西,Chris,感谢分享。
你在第一个 CSS 部分有一个错别字
ficaption { /*figcaption */
display: none;
}
随意删除此评论,我只是想让你知道。
AG
或者,你可以使用这个
添加一些缓动效果,你基本上就得到了相同的东西,代码量却少得多。
感谢分享代码=)
但需要说明的是,它并不完全相同。当悬停在 figcaptions 上时,该代码会停止当前动画,然后将其淡入或淡出。
此处提供的最终代码功能更强大。它不会立即触发动画,会有一定的延迟。但这种延迟只在第一次将鼠标移入该区域时出现。后续的悬停不会受到延迟的影响,除非你离开该区域一段时间后再回来。
我只是想把这一点说清楚,因为本文的重点是以微妙但重要的方式改进这种简单的交互。
非常有趣的文章,Chris。我一定会将其添加到我的书签中,以备将来参考。
很棒的文章,谢谢。
我正在为 WordPress 中的特色图片网格实现此功能——我的弹出窗口比用作触发器的图像更宽,并且绝对定位在右侧一点(有意地与设计相匹配)。如果可以,将其用作非移动工具提示。但是,发生的情况是,网格最右侧图像的弹出窗口会被切断(部分隐藏),然后在图像网格容器元素旁边添加一个水平滚动条。
这似乎是由于在容器元素中使用 overflow:auto; 造成的,但这是粘性页脚正常工作所必需的。http://www.cssstickyfooter.com/
关于如何强制弹出窗口显示在所有内容之上(包括容器)的任何建议?
我尝试过 overflow 和 z-index,但它仍然在内部/下方/被裁剪。
感谢你的想法。
如果你想做得更完善,或者如果你认为基本机制非常适合菜单(尤其是带有子菜单的菜单),那么你需要使用这个:https://github.com/kamens/jQuery-menu-aim