我正在尝试用纯 JavaScript 制作一个工具提示,如
hover
所示。就像 Stack Overflow 中的一样,将鼠标悬停在配置文件名称上时会显示 div
。
我尝试使用
onmouseover
、 onmouseout
并添加 setTimeout
让用户有几秒钟的时间将鼠标移动到工具提示内容上。但它并没有像我想象的那样工作。
我真的更喜欢纯 JavaScript,而不是使用任何库。有人可以帮帮我吗?
这就是我在纯 JavaScript 中所做的。
HTML
<div class = "name" onmouseover="show()" onmouseout="hide()">
NAME
<div class = "tooltip">
PROFILE DETAILS
</div>
</div>
<div class = "name" onmouseover="show()" onmouseout="hide()">
NAME 2
<div class = "tooltip" >
PROFILE DETAILS 2
</div>
</div>
<div class = "name" onmouseover="show()" onmouseout="hide()">
NAME 3
<div class = "tooltip" >
PROFILE DETAILS 3
</div>
</div>
CSS
.name{
float:left;
margin:100px;
border:1px solid black;
}
.tooltip{
position:absolute;
margin:5px;
width:200px;
height:100px;
border:1px solid black;
display:none;
}
JavaScript
var name = document.getElementsByclassName("name");
var tp = document.getElementsByclassName("tooltip");
function show(){
tp.style.display="block";
}
function hide(){
tp.style.display="";
}
这使用CSS伪悬停来设置隐藏元素的显示。显示内容不需要在样式中而不是在元素上,这样它就可以在悬停时被覆盖。
.couponcode:hover .coupontooltip {
/* NEW */
display: block;
}
.coupontooltip {
display: none;
/* NEW */
background: #C8C8C8;
margin-left: 28px;
padding: 10px;
position: absolute;
z-index: 1000;
width: 200px;
height: 100px;
}
.couponcode {
margin: 100px;
}
<div class="couponcode">First Link
<span class="coupontooltip">Content 1</span>
<!-- UPDATED -->
</div>
<div class="couponcode">Second Link
<span class="coupontooltip"> Content 2</span>
<!-- UPDATED -->
</div>
后续:
如果您需要支持非常旧的浏览器,则需要在鼠标进入 div 时向外部元素添加一个类。当鼠标离开时删除该类。
你的代码不起作用,因为 tp 是什么?是元素的集合,您将其视为一个元素。您需要做的就是传递对元素的引用
HTML:
<div class = "name" onmouseover="show(this)" onmouseout="hide(this)"> <!-- added "this" 2 times -->
**JavaScript:
//var name = document.getElementsByclassName("name"); /* not needed */
// var tp = document.getElementsByclassName("tooltip"); /* not needed */
function show (elem) { /* added argument */
elem.style.display="block"; /* changed variable to argument */
}
function hide (elem) { /* added argument */
elem.style.display=""; /* changed variable to argument */
}
问题说:
纯 JavaScript 工具提示
但我认为在现代我们可以使用普通的 JS 和 CSS。特别是,当我们想要提供好看的款式时,这是必须的。
这个例子是纯JS和CSS的简单实现。
让我们使用
CSS
创建工具提示,并使用 JS
添加修改行为。对于此示例,我们将定义一个 tip
属性来存储将在工具提示上显示的文本。
visibility: hidden;
和 opacity: 0;
将保持 .tooltip
隐藏,并在 [tip]:hover
时出现。此外,我们可以使用 style.transform
重新定位工具提示的发射点。
const elements = [...document.querySelectorAll('[tip]')]
for (const el of elements) {
const tip = document.createElement('div')
tip.classList.add('tooltip')
tip.textContent = el.getAttribute('tip')
const x = el.hasAttribute('tip-left') ? 'calc(-100% - 5px)' : '16px'
const y = el.hasAttribute('tip-top') ? '-100%' : '0'
tip.style.transform = `translate(${x}, ${y})`
el.appendChild(tip)
el.onpointermove = e => {
if (e.target !== e.currentTarget) return
const rect = tip.getBoundingClientRect()
const rectWidth = rect.width + 16
const vWidth = window.innerWidth - rectWidth
const rectX = el.hasAttribute('tip-left') ? e.clientX - rectWidth : e.clientX + rectWidth
const minX = el.hasAttribute('tip-left') ? 0 : rectX
const maxX = el.hasAttribute('tip-left') ? vWidth : window.innerWidth
const x = rectX < minX ? rectWidth : rectX > maxX ? vWidth : e.clientX
tip.style.left = `${x}px`
tip.style.top = `${e.clientY}px`
}
}
[tip] .tooltip {
position: fixed;
font-size: 16px;
line-height: 20px;
padding: 5px;
background: #444;
border: 1px solid #222;
visibility: hidden;
opacity: 0;
box-shadow: -2px 2px 5px rgba(0, 0, 0, 0.2);
transition: opacity 0.3s, visibility 0s;
color: white;
min-width: 120px;
}
[tip]:hover .tooltip {
visibility: visible;
opacity: 1;
}
button {
display: block;
cursor: pointer;
padding: 8px 15px;
border: 1px solid gray;
border-radius: 4px;
margin: 50px 5px;
width: 200px;
font-size: 18px;
background: white;
}
button:hover {
border-color: dodgerblue;
}
<button tip="Click me here!">I have a tooltip</button>
<button tip="Click me aswell!" tip-top tip-left>Top-left tooltip</button>
对于非自定义的工具提示,您只需在主
div
的标题属性中添加您想要在工具提示中显示的消息即可。就像这样:
<div class = "name" onmouseover="show()" onmouseout="hide()" title="PROFILE DETAILS">
那么就不需要添加
onmouseover
和 onmouseout
事件处理程序。
我正在寻找类似的东西,我发现了这个页面。 它对我有帮助,但我必须修复你的代码才能使其正常工作。我认为这就是你尝试过的。 您必须通过对象的“ID”来引用它们。 这是我所做的,它有效:
function show(elem) {
elem.style.display = "block";
}
function hide(elem) {
elem.style.display = "";
}
.name {
float: left;
margin: 100px;
border: 1px solid black;
}
.tooltip {
position: absolute;
margin: 5px;
width: 200px;
height: 50px;
border: 1px solid black;
display: none;
}
<div class="name" onmouseover="show(tooltip1)" onmouseout="hide(tooltip1)">
NAME
<div class="tooltip" id="tooltip1">
PROFILE DETAILS
</div>
</div>
<div class="name" onmouseover="show(tooltip2)" onmouseout="hide(tooltip2)">
NAME 2
<div class="tooltip" id="tooltip2">
PROFILE DETAILS 2
</div>
</div>
<div class="name" onmouseover="show(tooltip3)" onmouseout="hide(tooltip3)">
NAME 3
<div class="tooltip" id="tooltip3">
PROFILE DETAILS 3
</div>
</div>
即使是 $(document).ready,也很难用纯 JS 来完成——看这里: $(document).ready 相当于没有 jQuery
所以我使用一个简单的版本:
window.addEventListener("load", function () {
var couponcodes = document.getElementsByClassName("couponcode");
for (var i = 0; i < couponcodes.length; i++) {
couponcodes[i].addEventListener("mouseover", function () {
var coupontooltip = this.getElementsByClassName("coupontooltip")[0];
coupontooltip.removeAttribute("style");
});
couponcodes[i].addEventListener("mouseout", function () {
var coupontooltip = this.getElementsByClassName("coupontooltip")[0];
coupontooltip.style.display = "none";
});
}
});
使用 popper+tippy 遇到了一些滞后,开始搜索替代方案并找到了 @Teocci 的上面很好的答案!
我需要进行以下调整,因此这是修改后的代码:
CSS
.tooltip {
position: fixed;
z-index: 99;
font-size: 12px;
line-height: 12px;
padding: 5px;
background: #222;
color: #fff;
border: 1px solid #aaa;
border-radius: 5px;
font-family: sans-serif;
box-sizing: border-box;
/*box-shadow: -1px 2px 5px rgba(0, 0, 0, 0.2);*/
transition: opacity 0.3s, visibility 0s;
visibility: hidden;
opacity: 0;
}
.tooltip-arrow{
position: absolute;
top: -4px;
width: 7px;
height: 7px;
background: inherit;
transform: rotate(45deg);
border-top: 1px solid #aaa;
border-left: 1px solid #aaa;
}
/* just for demo */
.box{
margin: 25px;
padding: 25px;
}
HTML
<div class="box" style="background:orange;" data-tip="hello i'm the parent">
<div class="box" style="background:green;" data-tip="hi i'm the child"></div>
</div>
JS
function initTips(){
// purge previous for dynamic render
Array.from(document.querySelectorAll('.tooltip')).forEach(el => {
el.remove()
})
// built upon: https://stackoverflow.com/a/69340293/10885535
Array.from(document.querySelectorAll('[data-tip]')).forEach(el => {
// tip
let tip = document.createElement('div')
tip.classList.add('tooltip')
tip.innerText = el.getAttribute('data-tip')
document.body.appendChild(tip)
// arrow
let arrow = document.createElement('div')
arrow.classList.add('tooltip-arrow')
tip.appendChild(arrow)
// position tip + arrow once added
setTimeout(() => {
let elmPos = el.getBoundingClientRect()
let tipPos = tip.getBoundingClientRect()
tip.style.left = (elmPos.left + (elmPos.width - tipPos.width)/2) + 'px'
tip.style.top = (elmPos.bottom + 5)+'px'
arrow.style.left = (tipPos.width/2 - 5) + 'px'
}, 0)
// toggle with mouse
el.onmouseover = e => {
tip.style.opacity = 1
tip.style.visibility = 'visible'
e.stopPropagation() // stop parent
};
el.onmouseout = e => {
tip.style.opacity = 0
tip.style.visibility = 'hidden'
};
});
}
// kickoff
initTips()
// test calling again ie after dynamic content
setTimeout(initTips, 1000)