我需要一些提示工具。在寻找一些灵感时,我无需去更远的地方,我的码头就足够了

这就是我最终的结果

HTML:保持简洁
链接可以在 HTML 中使用提示工具,无需任何花哨的编码。只需为链接提供一个 title
属性。
<a href="#" title="Hi, I'm a tooltip thingy.">link</a>
然后,当您将鼠标悬停在该链接上 1 或 2 秒时,您将获得黄色框。

我们不要修改它。我们的 HTML 将与上面显示的完全一样。
问题是,那个黄色框完全无法设置样式。也许有一天,一旦像这样的 Shadow DOM 内容被规范化,它就会成为可能,但今天,在任何浏览器中都不可能。因此,我们将运行一些 JavaScript 代码,该代码将提取该属性并使用相同文本创建 <div>
,我们将根据需要定位/隐藏/显示这些 <div>
。
JavaScript:jQuery 插件
像往常一样,我们将使用 jQuery。这正是将其制成插件的完美类型。您可能希望在您自己选择的任意元素集合上使用此功能,以及将其链接起来,因此插件模式是理想的选择。
调用它将像这样简单:
$("article a[title]").tooltips();
这将使所有恰好位于 <article>
元素内部且具有标题的链接都具有提示功能。您可以根据需要更改该选择器。
我们的插件将执行以下操作:
- 循环遍历每个链接。
- 为每个链接创建一个(隐藏的)div.tooltip,其内部文本与该链接的 title 属性匹配。
- 删除链接的 title 属性(唯一摆脱默认黄色框弹出窗口的方法)。
- 当鼠标悬停在链接上时…
- 相应地定位提示工具并将其滑动到可见状态。
- 当鼠标移出链接时…
- 将链接从可见状态滑动出去。
大量代码转储,已添加注释供您欣赏。
// IIFE to ensure safe use of $
(function( $ ) {
// Create plugin
$.fn.tooltips = function(el) {
var $tooltip,
$body = $('body'),
$el;
// Ensure chaining works
return this.each(function(i, el) {
$el = $(el).attr("data-tooltip", i);
// Make DIV and append to page
var $tooltip = $('<div class="tooltip" data-tooltip="' + i + '">' + $el.attr('title') + '<div class="arrow"></div></div>').appendTo("body");
// Position right away, so first appearance is smooth
var linkPosition = $el.position();
$tooltip.css({
top: linkPosition.top - $tooltip.outerHeight() - 13,
left: linkPosition.left - ($tooltip.width()/2)
});
$el
// Get rid of yellow box popup
.removeAttr("title")
// Mouseenter
.hover(function() {
$el = $(this);
$tooltip = $('div[data-tooltip=' + $el.data('tooltip') + ']');
// Reposition tooltip, in case of page movement e.g. screen resize
var linkPosition = $el.position();
$tooltip.css({
top: linkPosition.top - $tooltip.outerHeight() - 13,
left: linkPosition.left - ($tooltip.width()/2)
});
// Adding class handles animation through CSS
$tooltip.addClass("active");
// Mouseleave
}, function() {
$el = $(this);
// Temporary class for same-direction fadeout
$tooltip = $('div[data-tooltip=' + $el.data('tooltip') + ']').addClass("out");
// Remove all classes
setTimeout(function() {
$tooltip.removeClass("active").removeClass("out");
}, 300);
});
});
}
})(jQuery);
需要注意的两件事:1) 最终演示将使提示工具略微动画化。这里 JavaScript 代码中没有发生任何动画。动画是设计。设计是 CSS。因此,我们在 CSS 中执行所有这些操作。2) 这些提示工具的一个小设计细节是它们以相同的方向滑入和滑出。在 CSS 中,仅通过添加和删除单个类并使用过渡,这实际上是不可能的。当类被删除时,过渡将反向运行,因此将以与进入相同的方向滑出。通过使用 setTimeout
,我们可以应用一个临时类,并对其进行动画处理。如果有更优雅的想法,请在下面的评论中告诉我。
语义上的问题?
在文档底部添加 div 感觉很糟糕;感觉不太语义化。它们与它们来自的链接之间没有任何有意义的方式通过 HTML 本身连接。
此外,删除 title 标签也让我不太舒服。我听说它们对可访问性没有太大帮助,但仍然如此。我希望 preventDefault()
可以阻止它显示,但它没有。
关于这些内容有任何想法,请在下面的评论中告诉我。
CSS:数量很重要
请注意,在本文顶部的 OS X 屏幕截图中,背景和边框本身稍微透明。我无法在这里实现这一点。这些东西通常是可能的,但是向下的尖箭头是一个额外的元素,并且边框和背景如何相互连接仅仅是通过重叠,并且在任何透明度下看起来都很糟糕。因此,纯色,无伤大雅。
通常,像我们这里这样的尖箭头可以使用伪元素和 CSS 三角形在没有额外标记或图像的情况下实现。在我们的案例中,我们将使用伪元素,但我们也需要一个真实的元素。真实的元素(JavaScript 在每个提示工具 <div>
中插入的 <span>)充当位置框并进行裁剪。伪元素是实际的指针。一个样式与提示工具完全相同的框,只是旋转了 45 度,并被其父级裁剪掉。这是示意图。

所以就这样。
.tooltip, .arrow:after {
background: black;
border: 2px solid white;
}
.tooltip {
pointer-events: none;
opacity: 0;
display: inline-block;
position: absolute;
padding: 10px 20px;
color: white;
border-radius: 20px;
margin-top: 20px;
text-align: center;
font: bold 14px "Helvetica Neue", Sans-Serif;
font-stretch: condensed;
text-decoration: none;
text-transform: uppercase;
box-shadow: 0 0 7px black;
}
.arrow {
width: 70px;
height: 16px;
overflow: hidden;
position: absolute;
left: 50%;
margin-left: -35px;
bottom: -16px;
}
.arrow:after {
content: "";
position: absolute;
left: 20px;
top: -20px;
width: 25px;
height: 25px;
box-shadow: 6px 5px 9px -9px black,
5px 6px 9px -9px black;
transform: rotate(45deg);
}
.tooltip.active {
opacity: 1;
margin-top: 5px;
transition: all 0.2s ease;
}
.tooltip.out {
opacity: 0;
margin-top: -20px;
}
请注意,.active
类是执行滑动动画的类,而 .out
类是执行滑动出动画的类。
感谢
感谢 Adrian Adkison 在此过程中提供的一些想法和代码。
关于 Opera 的公平警告
Opera 不支持 CSS 中的 pointer-events
,因此整个演示似乎无法正常工作。这是因为提示工具实际上是定位在链接的正上方,只是其不透明度被设置为 0。如果要在 Opera 中修复它,您需要在 JavaScript 中将其文字显示设置为 none/block,或者使用 CSS 将它们从链接上移开足够远的距离,以免妨碍可点击性。如果有人想进行此更改,但希望它在其他方面与本演示完全一样,我愿意更新它。
演示
查看 CodePen 上 Chris Coyier (@chriscoyier) 编写的笔
气泡点提示。
在 CodePen 上。
嗯,看起来很有趣! :)
有趣。
无论如何,我想指出它在 IE8 上不起作用:提示工具全部一起显示。在第一个提示工具中,爱心后面有 – 不知道是不是故意的;)
要处理 IE 8,您可以
不确定是否更好,因为它更冗长,但您可以绑定
animationEnd
而不是setTimeout
,并在回调中添加/删除一个类。我能够应用类似的逻辑并应用一个新的
animationName
来触发一个新的动画退出,但还没有尝试过非关键帧动画。然后您必须处理
animationEnd
的各种浏览器前缀,但这只需要几行代码。看起来很棒,而且效果也很好,我可以看到它会很有用,谢谢!
此外,您的评论表单很棒,我已经在文本区域中点击了大约五分钟了。
我担心的一件事是,当您移除title属性时,链接的可访问性会受到怎样的影响。由于该信息旨在为链接提供额外的指导和含义,因此将其移除到另一个元素似乎可能会降低某些用户对该部分内容的可访问性。
(不过,如果使用辅助功能设备的用户没有 JavaScript,他们也不会丢失任何内容。)
这是一些相当旧的研究。http://www.paciellogroup.com/resources/articles/WE05/forms.html
当时,似乎对于链接来说,大多数阅读器不支持(即不执行任何操作)title属性。而那些支持的,也不是默认支持的。
它在 FF 3.6.24(=最新版本)上不起作用,
在 XP-Pro SP3(已完全更新)下。
根本没有弹出窗口出现,
在悬停或甚至点击
演示链接时! :-(
您应该更新您的浏览器……我认为最新的 FF 是 8.0
除了 IE > 8 之外,任何浏览器都不会加载 tooltip.js 吗?
是的,这不好。请参阅上面的评论以获取正确的代码。
看起来您遇到了一些兼容性问题。好吧,当您解决它们时,我有一个关于移除title属性的建议。
当您设置div时,为什么不鼠标悬停时移除它,然后在鼠标离开时添加回来呢?这样,您仍然可以使用键盘焦点并查看标题(以实现可访问性),但在使用鼠标时,您将获得视觉上的升级。
我绝对不喜欢的一件事是,一旦工具提示出现,我就无法将鼠标悬停在工具提示本身上。如果我想复制工具提示文本,我就很倒霉了。
使用 hoverIntent 可以解决这个问题。
好的,它现在可以在 Firefox 上运行了。伙计们,请在页面上进行硬刷新,因为它可能被缓存了。在 Firefox 上使用 COMMAND+SHIFT+R。
一个非常简单的方法是使用 Twitter Bootstrap CSS 库。http://twitter.github.com/bootstrap/
我很惊讶您使用 JavaScript 而不是伪元素、伪类和内容来实现这一点。
确实使用了伪元素。但是,是的,有一些方法可以使用仅 CSS 且不使用 JavaScript 来创建样式化的工具提示。但这要受限得多。例如,我想使用title属性,因为工具提示自然就具有该属性。如果没有一些 JavaScript,就无法做到这一点,因为无法阻止默认的黄色弹出窗口。您也无法仅使用伪元素获得带有箭头和边框的精确形状。您也无法获得相同方向的移动。所以是的,我使用了 JS 来获得所有这些。
一个词“哇”
我遇到的问题是,它在移动设备上会严重中断。它需要点击才能打开,这是可以理解的,但无法关闭它。这是一个大问题,因为它覆盖了下面的所有内容,您无法访问它们。
有没有办法在第二次点击时移除悬停状态?我还没有找到方法。
很棒的代码,但它是 jQuery 并且我的浏览器 Opera 存在问题;/。没关系,希望很快可以在 html 5 上实现 :)
很棒的文章。提示指针的一种替代方法,使其与不支持旋转的浏览器兼容:使用类似这样的 CSS“边框三角形”(未经测试)
.arrow {
width: 0;
height: 0;
border-left: 20px solid transparent;
border-right: 20px solid transparent;
border-top: 20px solid #fff;
}
.arrow:after {
width: 0;
height: 0;
border-left: 20px solid transparent;
border-right: 20px solid transparent;
border-top: 20px solid #000;
content: '';
position:absolute;
top: -2px;
}
尽管可能不如旋转的 div 清晰,但它可以在 IE7+ 中使用。
就像在 http://tutorialzine.com/2010/07/colortips-jquery-tooltip-plugin/
此外,您可以使用
.tooltip:before
和.tooltip:after
代替.arrow
和.arrow:after
,因此无需额外的元素。CSS 三角形很酷。那里的边框想法也是一个好主意。您可能需要整体增加三角形的大小才能获得最干净的边框。但是,是的,清晰度往往是一个问题。当三角形与其背景之间的对比度不高时,它最好使用。在最坏的情况下(黑色在白色上),会有很多“阶梯现象”。
@GreLI 除了不是,因为在我的设计中,一个需要是另一个的子元素。(请参阅上面的示意图)。
我认为如果仅在需要时添加工具提示(悬停时),在语义上会更友好。
快速示例
http://jsfiddle.net/stryju/Ygn42/
这样,您就不会用随机的工具提示元素污染文档,并且可以仅在需要时(工具提示出现时)移除title。
@stryju:您的代码非常漂亮整洁——这绝对是使用 jQuery 中的 .data() 函数的机会。做得好。
谢谢!
对其进行了一些更新,因此它具有正确的位置和“清晰的箭头” ;-)
我喜欢那个想法。我认为以任何一种方式执行它都可能存在优势。以我的方式,所有 DOM 操作都在前面发生,因此可能一开始执行速度较慢,而在您的方式中,每次悬停都会进行 DOM 操作,因此在整个页面使用过程中速度较慢。
最小的 DOM 操作——仅附加处理程序,不执行 DOM 操作 = 更好的性能,恕我直言。
我认为这种方法的最大优点是:没有脏 DOM(如果工具提示永远不会被使用,为什么要将其保留在 DOM 中?)。
如果您想污染 DOM,为什么要创建 X 个工具提示,而不是一个,然后赋予它文本(无论如何都会发生重绘)?
1 个工具提示,悬停时更改文本 = 更干净的 DOM
如果我错了,请纠正我 ;-)
“动画是设计。设计是 CSS。”
我不同意。网络开发人员有一种特定的倾向,即搞砸事情并混淆词语的正常含义,这种情况已经持续多年了。
这与其他情况没有什么不同。设计就是设计。动画是动作,是您也必须设计的动作。
而且我非常确定,任何了解或只是略微听说过卡通或动画的人都会告诉你同样的事情:动画不是设计,而是应用了设计的东西。网络开发也不例外。
我认为选择器开头的“<”不需要。
$tooltip = $(‘<div[data-tooltip=’ + $el.data(‘tooltip’) + ‘]’).addClass(“out”);
很酷,已修复。令人惊讶的是,即使有这个错误,它也能正常工作。
真的很棒,但是如果它在旧浏览器上不起作用,请限制其使用。总是同一个问题;(
引用
为了避免意外中断和/或未转义的安全漏洞,请使用 .text() 而不是暗示 .html() 式的行为(这是由于在开始/结束标签之间直接注入它造成的)。相反
关键在于使用 .text(),其余的只是通用的良好实践或偏好。
这不会破坏后面的
$tooltip = $('div[data-tooltip=' + $el.data('tooltip') + ']').addClass("out");
吗?我认为它确实破坏了它——jQuery 将 data-* 属性拉取到对象的任意 .data() 中,而不是反过来。
简短测试:http://jsfiddle.net/stryju/QjMYC/
我的意思是
.data('tooltip', i)
这行代码 ;-)不错。我最近也用类似的方式构建了一个基于 jQuery 的工具提示。我构建的工具提示需要显示 html 内容。而且在任何时候,dom 中都只有一个。我用新内容替换了这个 div 的内容。
如果用户可以点击弹出窗口中的菜单项或链接就好了
您可以修改它,使其在点击而不是悬停时执行操作。只是这里不是目标。
不过,需要指出的是,工具提示 div 不是锚链接的后代。如果是这种情况,默认情况下我们会获得更好的行为。如果将鼠标悬停在工具提示上,工具提示不会消失,允许您执行复制其文本等操作。但不幸的是,即使您可以在 HTML5 中使用 div 代替 a,在这种情况下,行为也不会完全正确。
很棒的教程,帮助我很多,我在许多网站上使用了这个工具提示。
现在运行良好。
仔细查看代码,如果使用不同的选择器两次调用 tooltips(),看起来会出现一些冲突。即,由于会有多个具有相同 data-tooltip 值的 div,因此多个工具提示会在悬停时出现。
非常酷,但就像其他人已经提到的那样,您可以完全使用 CSS 来实现。实际上,我在我最近的一个项目中遇到了类似的挑战。查看此 fiddle:http://jsfiddle.net/r7Q9m/
适用于 IE8 及更高版本,不依赖于
-webkit-transform
来创建三角形(尽管您不会在工具提示周围获得边框),但仍然有效,并且效果很好。我知道 jQuery 意味着我们可以拥有动画并放弃
title
属性的默认行为,但这真的是一件好事吗?当然,黄色文本可能会很烦人,但使用仅 CSS 技术,只需要一点preventDefault
,然后瞧——简单、仅 CSS 的工具提示,适用于 IE8 及更高版本,以及旧版浏览器的默认标题行为。太棒了!!!
非常简洁和简单,我喜欢它。
需要明确的是,您说“您可以完全使用 CSS 来实现”,指的是我的示例,这是不正确的。
– 您无法获得相同方向的滑动
– 您无法删除黄色弹出窗口(即使您的示例也有,preventDefault不起作用)
– 您无法获得阴影/带边框的三角形
所以是的,很棒的演示,我喜欢它,只是不想弄清楚我没有额外使用 JavaScript,我有一些我想做的事情,这是唯一的方法。
不错的插件。
对于相对定位的元素,您是否应该使用
offset
而不是position
?我认为您可能是对的。来自文档
尽管在我的简单演示案例中,它似乎工作正常。但是,为了作为插件分发,我必须对其进行测试,并可能替换它。
Chris,这一行让我很在意。
“动画是设计。设计是 CSS。”
我知道这有点不相关,但我一直都持有同样的观点,尽管其他人通常不同意。所以很高兴知道像您这样有地位和声誉的人也持有相同的观点。
不错,看起来像 iPhone 的工具提示
但是,它能否通过单个具有矩形和向下箭头形状的 PNG 图像来放置,而不是创建工具提示 CSS
(考虑到浏览器可以显示来自 PNG 的隔行图像)
如果您想使用 PNG,最好的方法可能是使用
border-image
,这样它仍然可以垂直和水平扩展,而不是固定大小。请参阅此处的搜索按钮示例:http://ejohn.org/blog/border-image-in-firefox/
我必须向工具提示添加 z-index 以确保它始终位于顶部。
哦,太棒了!!!:(o)
谢谢。很棒的工作 :)
有趣的是,我的评论没有显示出来。看来您有太多有效的评论进入了垃圾邮件文件夹。无论如何
我注意到工具提示在 IE8 中不起作用(我在评论中看到了您的修复)。
此外,对于 IE9,我注意到工具提示不一致,这意味着工具提示在一个链接中显示,但在其他链接中不显示。您是否注意到这种行为。
对于 Safari、Google Chrome 和 Mozilla(所有最新版本),工具提示运行良好。
谢谢。
太好了,我想在我的网站上使用它。
这在 IE 中不起作用。
查看以下 Fiddle
http://jsfiddle.net/r7Q9m/
您可以创建工具提示,而无需依赖 CSS3。这主要取决于您是想依赖 CSS3 还是 JavaScript。可能大多数人依赖 JavaScript 会导致更高的支持度。
使用来自“:before”和“:after”的伪元素,一个用于内容,另一个用于“引脚”,就足够了。
很棒的文章!我现在正在我的网站上实施!
在 Internet Explorer 中无法工作。
它在 IE 8 及更低版本中根本不起作用,因此请使用条件注释来防止脚本在那里加载(请参阅前面的评论)。
另请阅读文章中有关 Opera 的部分。问题是 pointer-events。您可以自行更改它,将“隐藏”的工具提示从位于链接顶部的位置移动,以解决此问题。例如,使其位于链接上方,然后向下浮动而不是向上浮动。
很棒而且非常有用!
一个问题:是否可以防止工具提示悬停到浏览器窗口之外。
谢谢!
我遇到了工具提示相对于包装容器定位的问题。我绞尽脑汁试图解决它,到处使用“relative”和“absolute”。我最终不得不将
var linkPosition = $el.position();
更改为var linkPosition = $el.offset();
,尽管我认为这不是推荐的做法。此外,谁能告诉我为什么这在 IE8 中不起作用?我添加了所有 IE 特定的“opacity”规则,但仍然完全不起作用。JS 或 CSS 中似乎没有任何异常情况,因此至少使残缺版本在 IE8 中工作并不难。
在 a 元素内使用 span,并将其定位为 absolute 并将其在悬停时显示,这在语义上是正确的吗?
看起来不错,但有点问题。title 属性的内容通常是纯文本,但此解决方案将其变成了 HTML——但并非对所有人如此,因为纯文本标题用作回退。因此,如果您想在标题文本中使用与号,或者甚至使用 <tag>,您会如何在 title 属性中编写呢?
因此,此工具提示实现也可能是 XSS 漏洞的潜在攻击媒介。想象一个应用程序,允许用户为工具提示输入一些文本,例如图像标题。然后管理员想要用这些工具提示来美化界面。糟糕!现在用户可以输入任意 HTML 代码了。
我的建议:让 title 属性保持纯文本。添加另一个属性,例如 data-fancy-html-title,当需要 HTML 时使用。
或者为工具提示内容提供回调函数。让用户决定工具提示中包含的内容——是富文本还是纯文本……我在我的 Elixon Tooltip 中实现了这一点,它尽可能地通用……我现在可以用它做很多事情……
对于一个小小的工具提示来说,CSS 代码太多了。我过去也做过工具提示,但我总是最终让它们变得冗余,通过重写我的内容,并更好地解释事情。这很遗憾,因为我真的很喜欢工具提示。:P
Daniel Piechnick
如果屏幕上没有空间,那个工具提示不会自动重新定位……我正在尝试制作一个,但我认为这个是最有效和最简单的
https://code.google.com/p/littletip/
感谢您的帖子!
那将是一个不错的功能。实际上并不难,如果您使用 jQuery UI 的 .postion() 而不是原生 jQuery。.postion() 具有碰撞检测功能,并将移动您要定位的内容以使其出现在屏幕上。
如何使这个工具提示出现在底部?任何人都可以帮忙吗?
如何使弹出窗口在鼠标移出它之前保持显示?
TypeError: $(…).tooltips 不是函数