How do you create a tooltip on hover

How do you create a tooltip on hover? I would like people to be able to hover over my list of items include in the price and learn more about the features.

Any tips on tooltips?

Thanks!


Here is my public share link: LINK
(how to access public share link)

1 Like

Hello @ljgrohn

Check this > https://webflow.com/blog/how-to-build-tooltips recreate the tooltip and you will have the basic knowledge for building different kinds of tooltips.

If you have any questions feel free to ask :blush:

Piter :webflow_heart:

3 Likes

Hey @PeterDimitrov that’s a really long and complex process for a tooltip. I assume there is a much simpler process for a tooltip on regular text?

I’m trying to do tooltips in CMS for my citations/references like Wikipedia does it.

Thanks for any tips.

1 Like

@eric594 Here’s what I found after digging around to find an answer to the same question - Tooltips for Webflow - Webflow

:point_right: [Cloneable] Native Webflow Tooltips :point_left:

tooltip

Dropping this here in case folks are looking for a cloneable or 100% Webflow approach. Hope it helps!

2 Likes

Nobody with any solution like Wikipedia does it?
I’m searching for a site-wide solution so every link (at least in ever rich-text field) get’s auto tooltip, with title and og-media image.

1 Like

Update - this first project no longer works. Webflow Showcased | load-content-from-other-pages

Here are the Showcased search results for “link preview

These don’t seem to work here on Chrome

1 Like

Yeah, stopped working for me too…

Here’s a better one Webflow Showcased | Automatic Link Preview

I decided to build my own wikipedia-like tooltip.

Which works for all pages that are on the website itself - so not for external pages.

If you want full internet support for tooltip/rich links then you can use https://linkz.ai/ - I’ve used it, though it was too pricey for us since we have a ton of page-views. But it works brilliantly, nice and fast.


My own setup was build with a custom JS script in combination with Tippy.js:

You need to style your own classes as you wish for:

  • tooltip-content-link
  • tooltip-arrow
  • tooltip-subtitle
  • tooltip-heading
  • tooltip-image
  • tooltip-text"

Example page: Advanced mechanics | Advanced ⇀ Guide ★ Beyond All Reason RTS

image

image

You can hover over links and see the Tippy Tooltips popping up, with content from it’s meta-data.

Main benefits:

  • No cost for uses/views/generations
  • Can use all the meta-data from pages within your website
  • Even uses url-stripping for additional title/category based on URL
  • Fast
  • Full control over design

Head Code:

<link
  rel="stylesheet"
  href="https://unpkg.com/tippy.js@6/animations/scale-subtle.css"
/>

Footer Code:

<!-- Include the Tippy.js library -->
<script src="https://unpkg.com/@popperjs/core@2.11.6/dist/umd/popper.min.js"></script>
<script src="https://unpkg.com/tippy.js@6.3.3/dist/tippy-bundle.umd.min.js"></script>


<!-- HTML template for tooltip content -->
<div id="tooltip-template" style="display: none;">
    <div>
        <a href="" class="tooltip-content-link">
            <div class="tooltip-arrow"></div>
            <h5 class="tooltip-subtitle"></h5>
            <h4 class="tooltip-heading"></h4>
            <img src="" loading="lazy" alt="Image" class="tooltip-image">
            <div class="tooltip-text"></div>
        </a>
    </div>
</div>

<!-- CSS styles for tooltip content -->
<style>
    /* Custom arrow styles */
    .tippy-arrow {
        color: #050404;
    }

    /* Increase the z-index */
    .tippy-box {
        z-index: 99999;
    }
</style>

<!-- JavaScript code -->
<script>
    // Retrieve all divs with the class "rich-text" and "w-richtext"
    const richtextDivs = document.querySelectorAll('.rich-text.w-richtext, .rich-text-unit-description.w-richtext, .rich-text-faq.w-richtext');

    // Create a map to store the tippy instances
    const tippyInstances = new Map();

    // Fetch and prefetch the page metadata for each link
    richtextDivs.forEach(div => {
        const links = div.querySelectorAll('a');

        links.forEach(link => {
            const href = link.href;

            // Exclude external links
            if (!isInternalLink(href)) {
                return;
            }

            // Prefetch the metadata for the link
            fetchMetadata(href)
                .then(metadata => {
                    // Get the tooltip template element
                    const template = document.getElementById('tooltip-template');

                    // Clone the template to create a new instance
                    const tooltipContent = template.cloneNode(true);

                    // Extract the first part of the URL after the domain name as the subtitle
                    const url = new URL(href);
                    const pathSegments = url.pathname.split('/').filter(segment => segment.trim() !== '');
                    const subtitle = pathSegments[0] || '';

                    // Remove " ⇀" from the title if it exists
                    const title = metadata.title;
                	const strippedTitle = title.split(' ⇀')[0];

                    // Remove "DPS 0" from the description if it exists
					const description = metadata.description.replace(/.{3}DPS 0$/, '');

                    // Populate the tooltip content with metadata
                    tooltipContent.querySelector('.tooltip-subtitle').textContent = subtitle;
                    tooltipContent.querySelector('.tooltip-heading').textContent = strippedTitle;
                    tooltipContent.querySelector('.tooltip-text').innerHTML = description;
                    tooltipContent.querySelector('.tooltip-content-link').href = href; // Set the original link URL

                    // Set the ogImage source if it exists
                    const ogImage = tooltipContent.querySelector('.tooltip-image');
                    if (metadata.ogImage) {
                        ogImage.src = metadata.ogImage;
                        ogImage.style.display = 'block'; // Show the ogImage
                    } else {
                        ogImage.style.display = 'none'; // Hide the ogImage if not found
                    }

                    // Make the tooltip content visible
                    tooltipContent.style.display = 'block';

                    // Create the Tippy.js tooltip
                    const tippyInstance = tippy(link, {
                        content: tooltipContent.innerHTML,
                        allowHTML: true,
                        // maxWidth: 240, // Set the maximum width of the tooltip to 240
                        animation: 'scale-subtle',
                        arrow: false, // Disable the arrow
                        placement: 'top',
                        interactive: true,
                        trigger: 'mouseenter',
                        touch: false,
                        delay: [150, 250],
                        popperOptions: {
                            strategy: 'fixed',
                            modifiers: [
                                {
                                    name: 'preventOverflow',
                                    options: {
                                        boundariesElement: document.body,
                                        rootBoundary: 'document',
                                        padding: 10,
                                    },
                                },
                            ],
                        },
                    });

                    // Store the tippy instance in the map
                    tippyInstances.set(link, tippyInstance);
                })
                .catch(error => {
                    console.error('Error prefetching metadata:', error);
                });
        });
    });

    // Fetches the page metadata using the link's URL
    function fetchMetadata(url) {
        return fetch(url)
            .then(response => response.text())
            .then(html => {
                // Parse the HTML response to extract the metadata
                const parser = new DOMParser();
                const doc = parser.parseFromString(html, 'text/html');
                const title = doc.querySelector('title')?.innerText || '';
                const ogImage = doc.querySelector('meta[property="og:image"]')?.content || '';
                const description = doc.querySelector('meta[name="description"]')?.content || '';

                // Return the metadata as an object
                return { title, ogImage, description };
            });
    }

    // Checks if a link is an internal link within the current domain
    function isInternalLink(url) {
        const currentOrigin = window.location.origin;
        const linkOrigin = new URL(url).origin;
        return linkOrigin === currentOrigin;
    }
</script>
1 Like

This one seems nice yes.
Easy code and to build.

Some questions:

  • Is each tooltip-card-link refreshed on page?
  • Meaning you get the latest screenshot?
  • Does it take long to load - f.e. what if you have 20+ links on your page?
  • What if the website is unavailable at that time?

Though it does rely on an external service to generate the screenshots.
I’m a bit worried that it might stop working as well - or will charge you for that later on.

Also this version does not seem to include other meta-data like the link, title or description.

Awesome solution! Thanks for sharing, Martijn :partying_face:

As for your questions I’m not 100% sure. That project was created by someone else and I did not look too deeply into how it works. Great questions though! I am curious now myself.

1 Like

If anyone is looking to generate the browser/System tooltips. It has to be on a Span/Link/Button etc…

Style panel: Custom properties
Add “cursor: default”
Settings panel: Custom attributes
Add “Title: Your tooltip text”
Screenshot 2024-09-02 143634

Screenshot 2024-09-02 143650

1 Like