Create tooltips quickly and easily

Create simple tooltips with HTML/CSS with minimal JavaScript? I'll show you how to do it πŸͺ„

Create tooltips quickly and easily
Photo by Glenn Carstens-Peters / Unsplash / Image

You just want to create a tooltip in HTML/CSS and don't want to use the title attribute, but create your own tooltip instead? It's easier than you think and you don't need any external libraries.

Data attribute to the rescue ⛑️

The core is the data attribute of HTML. This allows us not only to pass JavaScript data from HTML, but also to pass it to CSS and use it there. CSS offers a way to retrieve this attribute and use it in CSS classes. With attr() we can now grab the content and display it as content.

attr() - CSS: Cascading Style Sheets | MDN
The attr() CSS function is used to retrieve the value of an attribute of the selected element and use it in the stylesheet. It can also be used on pseudo-elements, in which case the value of the attribute on the pseudo-element's originating element is returned.

With a little styling and minimal JavaScript, you can create beautiful and appealing tooltips that also match the design of your website.

The code πŸ‘¨πŸΌβ€πŸ’»

Let's assume we want to add a tooltip to a button. Generally, you can do this with the title attribute, but they don't look nice and are also quite inflexible in terms of styling options.

title - HTML: HyperText Markup Language | MDN
The title global attribute contains text representing advisory information related to the element it belongs to.

In our example, we simply want to generate a button with a tooltip. This looks like this:

<button class="tooltip" data-tooltip="This is a tooltip!">Hover over me</button>

And this is where the Data attribute comes into play! We use it to create a new attribute data-tooltip. We then pass this attribute value on to CSS:

/* Styles for the tooltip */
.tooltip {
    position: relative; /* Position relative to contain the tooltip */
    cursor: pointer; /* Pointer cursor for better UX */
}

/* Hide the tooltip by default */
.tooltip::after {
    content: attr(data-tooltip); /* Use the data-tooltip attribute value */
    position: absolute; /* Position the tooltip */
    background-color: #333; /* Dark background */
    color: #fff; /* White text */
    padding: 5px; /* Some padding */
    border-radius: 5px; /* Rounded corners */
    white-space: nowrap; /* Prevent line breaks */
    opacity: 0; /* Start hidden */
    visibility: hidden; /* Start hidden */
    transition: opacity 0.3s; /* Smooth transition */
}

/* Show the tooltip on hover */
.tooltip:hover::after {
    opacity: 1; /* Show the tooltip */
    visibility: visible; /* Make the tooltip visible */
}

As you can see, we have passed the content of the attribute to CSS and can thus use and display the content quite smoothly.

content - CSS: Cascading Style Sheets | MDN
The content CSS property replaces content with a generated value. It can be used to define what is rendered inside an element or pseudo-element. For elements, the content property specifies whether the element renders normally (normal or none) or is replaced with an image (and associated "alt" text). For pseudo-elements and margin boxes, content defines the content as images, text, both, or none, which determines whether the element renders at all.

Positioning of the tooltip πŸ“°

Now, however, we may also want to be able to decide where the tooltip is displayed, whether at the top bottom or on the left and right. We can also use the data attribute for this by writing our own classes for this and positioning the tooltip accordingly with transform:

.tooltip[data-position="top"]::after {
    bottom: 100%; /* Position above the element */
    left: 50%; /* Center the tooltip */
    transform: translateX(-50%); /* Center the tooltip */
    margin-bottom: 10px; /* Space between tooltip and element */
}

.tooltip[data-position="bottom"]::after {
    top: 100%; /* Position below the element */
    left: 50%; /* Center the tooltip */
    transform: translateX(-50%); /* Center the tooltip */
    margin-top: 10px; /* Space between tooltip and element */
}

.tooltip[data-position="left"]::after {
    right: 100%; /* Position to the left of the element */
    top: 50%; /* Center the tooltip */
    transform: translateY(-50%); /* Center the tooltip */
    margin-right: 10px; /* Space between tooltip and element */
}

.tooltip[data-position="right"]::after {
    left: 100%; /* Position to the right of the element */
    top: 50%; /* Center the tooltip */
    transform: translateY(-50%); /* Center the tooltip */
    margin-left: 10px; /* Space between tooltip and element */
}
transform - CSS: Cascading Style Sheets | MDN
The transform CSS property lets you rotate, scale, skew, or translate an element. It modifies the coordinate space of the CSS visual formatting model.

Dynamic positions βš—οΈ

So that the tooltip does not run beyond the viewport limits, we use a small JavaScript that calculates the distances to the viewport and sets the appropriate data-position:

document.addEventListener('DOMContentLoaded', function() {
    const tooltips = document.querySelectorAll('.tooltip');

    tooltips.forEach(tooltip => {
        tooltip.addEventListener('mouseover', () => {
            const tooltipRect = tooltip.getBoundingClientRect();
            const viewportWidth = window.innerWidth;
            const viewportHeight = window.innerHeight;
            const tooltipText = tooltip.getAttribute('data-tooltip');
            
            if (tooltipRect.top > 50) {
                tooltip.setAttribute('data-position', 'top');
            } else if (viewportHeight - tooltipRect.bottom > 50) {
                tooltip.setAttribute('data-position', 'bottom');
            } else if (tooltipRect.left > 50) {
                tooltip.setAttribute('data-position', 'left');
            } else if (viewportWidth - tooltipRect.right > 50) {
                tooltip.setAttribute('data-position', 'right');
            }
        });
    });
});

That's it! You have now created your own tooltip with (almost) pure CSS and HTML, which you can style very well and use in your website.

Interactive example πŸ›