Implementing Custom Tooltips with Vanilla JavaScript

The following script replaces the native browser tooltip with a custom-styled tooltip that appears when hovering over elements with the class hasTooltip.​

See the Pen JavaScript Title Tooltip by Ciprian (@ciprian) on CodePen.

HTML Structure

Ensure your HTML elements have the hasTooltip class and a title attribute containing the tooltip text:​

<a href="#" class="hasTooltip" title="This is a custom tooltip">Hover over me</a>

CSS Styling

Define the styles for your custom tooltip:​

.tooltip {
  position: absolute;
  background-color: #333;
  color: #fff;
  padding: 6px 10px;
  border-radius: 4px;
  font-size: 14px;
  pointer-events: none;
  white-space: nowrap;
  z-index: 1000;
  opacity: 0;
  transition: opacity 0.2s ease-in-out;
}

.tooltip.visible {
  opacity: 1;
}

JavaScript Functionality

Implement the tooltip behaviour using vanilla JavaScript:​

document.addEventListener('DOMContentLoaded', () => {
  const tooltip = document.createElement('div');
  tooltip.className = 'tooltip';
  document.body.appendChild(tooltip);

  const tooltipTargets = document.querySelectorAll('.hasTooltip');

  tooltipTargets.forEach(el => {
    el.addEventListener('mouseenter', () => {
      const titleText = el.getAttribute('title');
      if (!titleText) return;

      el.setAttribute('data-tooltip', titleText);
      el.removeAttribute('title');

      tooltip.textContent = titleText;
      tooltip.classList.add('visible');
    });

    el.addEventListener('mouseleave', () => {
      const originalTitle = el.getAttribute('data-tooltip');
      if (originalTitle) {
        el.setAttribute('title', originalTitle);
        el.removeAttribute('data-tooltip');
      }
      tooltip.classList.remove('visible');
    });

    el.addEventListener('mousemove', e => {
      tooltip.style.left = `${e.pageX + 20}px`;
      tooltip.style.top = `${e.pageY + 10}px`;
    });
  });
});

on in JavaScript DOM | Last modified on

Related Posts

Leave a Reply

Your email address will not be published. Required fields are marked *