Published: June 19, 2024
When you can't show all information on the webpage, it comes in handy to have a tooltip to show additional information on demand.
This could be an info button that looks like this:
Hover over the info button to see what it has to say to you
You can see that hovering over the info button shows some information, which becomes available as you hover over the info button.
Now let's see how we can create a tooltip with JavaScript and Svelte.
In this blog post, we will create a bare-minimum dynamic tooltip, whose position will be adjusted depending on the mouse's location, with a simple syntax using JavaScript and Svelte.
The tooltip should also support HTML, as we'd like to show rich content in the tooltip, such as titles and images.
First, add an element which you'd like to show a tooltip when hovered:
<Info size={50} color="#0ea5e9" />
Currently this button is dead. Now, let's develop the backend for enabling tooltip:
<script>
// OnMount is needed to find all tooltips once the component is mounted
import { onMount } from 'svelte';
// info: the tooltip DOM element (info window)
// container: main container DOM element in the page
// innerWidth: window innerWidth. Use to calculate the location of info window
// innerHeight: window innerHeight. Use to calculate the location of info window
let info, container, innerWidth, innerHeight;
// showInfo: Used to control whether to show an info
$: showInfo = false;
// Function that controls the location of tooltip based on mouse location
function handleMouseMove(event) {
// Get mouse location
let x = event.clientX;
let y = event.clientY;
// Get container location
let rect = container.getBoundingClientRect();
// If mouse is in the top half of the screen, set its 'top' style, otherwise none
info.style.top = y < innerHeight / 2 ? y - rect.top + 10 + 'px' : '';
// If mouse is in the bottom half of the screen, set its 'bottom' style, otherwise none
info.style.bottom = y < innerHeight / 2 ? '' : rect.bottom - y + 10 + 'px';
// If mouse is in the left half of the screen, set its 'left' style, otherwise none
info.style.left = x < innerWidth / 2 ? x - rect.left + 10 + 'px' : '';
// If mouse is in the left right of the screen, set its 'right' style, otherwise none
info.style.right = x < innerWidth / 2 ? '' : rect.right - x + 10 + 'px';
}
onMount(() => {
// Get all elements which require showing a tooltip when hovered
let tooltips = document.querySelectorAll('[tooltip]');
for (const element of Array.from(tooltips)) {
// When hovered, show tooltip
element.addEventListener('mouseenter', () => {
showInfo = true;
info.innerHTML = element.getAttribute('tooltip');
});
// When hover is gone, hide the tooltip element
element.addEventListener('mouseleave', () => {
showInfo = false;
info.innerHTML = '';
});
}
});
</script>
// Get innerWidth and innerHeight by binding to window
// Listen to mousemove on the window
<svelte:window bind:innerWidth bind:innerHeight on:mousemove={(e) => handleMouseMove(e)} />
// Overall Container. Bind to container variable.
// This is used to adjust the location of tooltip
<div class="flex gap-4 flex-col relative" bind:this={container}>
<!-- Tooltip element. It's contents are only assigned when the user hovers over an info button -->
<div bind:this={info}
class={`z-50 bg-white px-4 max-w-[500px] py-2 flex absolute rounded overflow-hidden shadow-xl hidden`}></div>
<!-- Info button. This triggers the tooltip -->
<div class="inline-block"
tooltip="<p class='font-bold'>Thanks for checking out this tooltip. Much appreciated.</p>">
<Info size={50} color="#0ea5e9" />
</div>
</div>
It's a long code and most of it is boilerplate, so I want to focus on the 3 key parts of the code.
Info elements are the elements which trigger a tooltip. In our example, it was an Info button.
These elements should have a tooltip
attribute. The value of this
attribute should be the HTML element that you'd like to show inside the tooltip when this element
is hovered.
// Info button. This triggers the tooltip
<div class="inline-block"
tooltip="<p class='font-bold'>Thanks for checking out this tooltip. Much appreciated.</p>">
<Info size={50} color="#0ea5e9" />
</div>
Assigning tooltip
attribute to all info elements will help us identify
them when the component is mounted.
Once all elements with tooltip attribute are identified, we listen to the mouseenter
event and show the tooltip. This event also assigns the tooltip's HTML to the value of tooltip
attribute.
When mouse leaves the info element, tooltip should be hidden.
This is how we control the visibility of tooltip:
onMount(() => {
// Get all elements which require showing a tooltip when hovered
let tooltips = document.querySelectorAll('[tooltip]');
for (const element of Array.from(tooltips)) {
// When hovered, show tooltip
element.addEventListener('mouseenter', () => {
showInfo = true;
info.innerHTML = element.getAttribute('tooltip');
});
// When hover is gone, hide the tooltip element
element.addEventListener('mouseleave', () => {
showInfo = false;
info.innerHTML = '';
});
}
});
Now that we can show/ hide tooltip when the info element is hovered, now we need to determine where to locate the tooltip.
Below code is responsible for achieving that:
// Function that controls the location of tooltip based on mouse location
function handleMouseMove(event) {
// Get mouse location
let x = event.clientX;
let y = event.clientY;
// Get container location
let rect = container.getBoundingClientRect();
// If mouse is in the top half of the screen, set its 'top' style, otherwise none
info.style.top = y < innerHeight / 2 ? y - rect.top + 10 + 'px' : '';
// If mouse is in the bottom half of the screen, set its 'bottom' style, otherwise none
info.style.bottom = y < innerHeight / 2 ? '' : rect.bottom - y + 10 + 'px';
// If mouse is in the left half of the screen, set its 'left' style, otherwise none
info.style.left = x < innerWidth / 2 ? x - rect.left + 10 + 'px' : '';
// If mouse is in the left right of the screen, set its 'right' style, otherwise none
info.style.right = x < innerWidth / 2 ? '' : rect.right - x + 10 + 'px';
}
Above code is smart, beacuse it divides the screen into 4 quadrants and shows the tooltip accordingly, so that it doesn't bleed out from the screen.
Hover over below quadrants and see how this works in real life:
You can see that depending on the location of the info element, we smartly locate the tooltip. Works like charm doesn't it?
In this blogpost, we have developed a tooltip using Svelte and JavaScript.
Our solution only requires you to add tooltip
attribute to the elements
that you'd like to have tooltip on. The value of this attribute will be displayed in the tooltop.
Our solution accepts HTML and it smartly locates the tooltip so that it doesn't bleed out of screen.
Any questions? Let me know below.
Until further notice, happy hacking!
Leave comment
Comments
Check out other blog posts
2024/06/17
Create an Interactive Map of Tokyo with JavaScript
2024/06/14
How to Easily Fix Japanese Character Issue in Matplotlib
2024/06/13
Book Review | Talking to Strangers: What We Should Know about the People We Don't Know by Malcolm Gladwell
2024/06/07
Most Commonly Used 3,000 Kanjis in Japanese
2024/06/07
Replace With Regex Using VSCode
2024/06/06
Do Not Use Readable Store in Svelte
2024/06/05
Increase Website Load Speed by Compressing Data with Gzip and Pako
2024/05/31
Find the Word the Mouse is Pointing to on a Webpage with JavaScript
2024/05/29
Create an Interactive Map with Svelte using SVG
2024/05/28
Book Review | Originals: How Non-Conformists Move the World by Adam Grant & Sheryl Sandberg
2024/05/27
How to Algorithmically Solve Sudoku Using Javascript
2024/05/26
How I Increased Traffic to my Website by 10x in a Month
2024/05/24
Life is Like Cycling
2024/05/19
Generate a Complete Sudoku Grid with Backtracking Algorithm in JavaScript
2024/05/16
Why Tailwind is Amazing and How It Makes Web Dev a Breeze
2024/05/15
Generate Sitemap Automatically with Git Hooks Using Python
2024/05/14
Book Review | Range: Why Generalists Triumph in a Specialized World by David Epstein
2024/05/13
What is Svelte and SvelteKit?
2024/05/12
Internationalization with SvelteKit (Multiple Language Support)
2024/05/11
Reduce Svelte Deploy Time With Caching
2024/05/10
Lazy Load Content With Svelte and Intersection Oberver
2024/05/10
Find the Optimal Stock Portfolio with a Genetic Algorithm
2024/05/09
Convert ShapeFile To SVG With Python
2024/05/08
Reactivity In Svelte: Variables, Binding, and Key Function
2024/05/07
Book Review | The Art Of War by Sun Tzu
2024/05/06
Specialists Are Dead. Long Live Generalists!
2024/05/03
Analyze Voter Behavior in Turkish Elections with Python
2024/05/01
Create Turkish Voter Profile Database With Web Scraping
2024/04/30
Make Infinite Scroll With Svelte and Tailwind
2024/04/29
How I Reached Japanese Proficiency In Under A Year
2024/04/25
Use-ready Website Template With Svelte and Tailwind
2024/01/29
Lazy Engineers Make Lousy Products
2024/01/28
On Greatness
2024/01/28
Converting PDF to PNG on a MacBook
2023/12/31
Recapping 2023: Compilation of 24 books read
2023/12/30
Create a Photo Collage with Python PIL
2024/01/09
Detect Device & Browser of Visitors to Your Website
2024/01/19
Anatomy of a ChatGPT Response