JSFiddle - React, Tailwind, and code Playground
HTML
<div class="tooltip">
<span class="dot"></span>
<div class="content">
<h1>Tooltip heading</h1>
<p>Some random text blah blah...</p>
</div>
</div>
<br><br>
<div class="tooltip">
<span class="dot"></span>
<div class="content">
<h1>Tooltip heading</h1>
<p>Some random text blah blah...</p>
</div>
</div>
<br><br>
<div class="tooltip specificLocation">
<span class="dot"></span>
<div class="content">
<h1>Different location</h1>
<p>Some random text blah blah...</p>
</div>
</div>
CSS
.tooltip {
position: relative;
}
.dot {
display: block;
margin: 15px;
width: 35px;
height:35px;
border-radius: 50%;
background-color: orange;
}
.content {
position: absolute;
top: 0px;
left: 75px;
opacity: 0;
transition: opacity .5s ease-in;
}
.content h1,
.content p {
margin: 0;
}
.dot:hover + .content {
opacity: 1;
}
.specificLocation {
margin-left: 100px;
}
JavaScript
window.onmousemove = function(e) {
if (e.target.classList.contains('dot')) {
// Content of dot which is hovered
var $target = e.target.nextElementSibling;
// Only work with hovered target
// Add visible class hovered elem to distinguish
if (!$target.classList.contains('visible')) {
$target.classList.add('visible');
} else {
// Get viewport offset of tooltip element
var offset = $target.parentElement.getBoundingClientRect();
// Tooltip distance from mouse(px)
var tipDist = 15;
// Calc and set new tooltip location
$target.style.top = (e.clientY - offset.top + tipDist) + 'px';
$target.style.left = (e.clientX - offset.left + tipDist) + 'px';
}
} else {
// Remove visible class
var content = document.getElementsByClassName('content');
for (var i = 0; i < content.length; i++) {
content[i].classList.remove('visible');
}
}
};