Skip to content

Instantly share code, notes, and snippets.

@Arifursdev
Last active December 16, 2023 14:03
Show Gist options
  • Save Arifursdev/94db44777efea585f7a530a05f990ef0 to your computer and use it in GitHub Desktop.
Save Arifursdev/94db44777efea585f7a530a05f990ef0 to your computer and use it in GitHub Desktop.
Simple Vanilla JS Tooltip

adev-tooltip.js

class Tooltip {
  constructor() {
    this.tooltipElement = this.createTooltipElement();
    this.init();
  }

  init() {
    document.querySelectorAll('[data-adev-tooltip]:not(.tooltip-init)').forEach(element => {
      element.classList.add('tooltip-init');

      element.addEventListener('mouseover', (event) => this.showTooltip(event));
      element.addEventListener('mouseout', () => this.hideTooltip());

      element.addEventListener('touchstart', (event) => this.showTooltip(event));
      element.addEventListener('touchend', () => this.hideTooltip());
      element.addEventListener('touchcancel', () => this.hideTooltip());

    });
  }

  createTooltipElement() {
    let tooltipElement = document.querySelector('.adev-tooltip');
    if (!tooltipElement) {
      tooltipElement = document.createElement('div');
      tooltipElement.className = 'adev-tooltip';
      document.body.appendChild(tooltipElement);
    }

    return tooltipElement;
  }

  showTooltip(event) {
    let target = event.target;
    if (!target.getAttribute('data-title')) {
      target = target.closest('[data-title]');
    }

    this.tooltipElement.textContent = target.dataset.title;
    this.tooltipElement.style.display = 'block';

    const position = target.getBoundingClientRect();
    const tooltipPosition = this.tooltipElement.getBoundingClientRect();

    const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
    const top = (position.top + scrollTop) - this.tooltipElement.scrollHeight;

    const viewportWidth = document.documentElement.clientWidth;

    let tooltipPositionSide;
    if (position.left + tooltipPosition.width <= viewportWidth) {
      this.tooltipElement.style.left = `${position.left}px`;
      this.tooltipElement.style.right = 'auto';
      tooltipPositionSide = 'left';
    } else if (viewportWidth - position.right + tooltipPosition.width <= viewportWidth) {
      this.tooltipElement.style.right = `${viewportWidth - position.right}px`;
      this.tooltipElement.style.left = 'auto';
      tooltipPositionSide = 'right';
    } else {
      this.tooltipElement.style.left = '0';
      this.tooltipElement.style.right = 'auto';
      tooltipPositionSide = 'left';
    }

    this.tooltipElement.style.top = `${top - 5}px`;
    this.tooltipElement.style.visibility = 'visible';
    this.tooltipElement.setAttribute('data-tooltip-position', tooltipPositionSide);
  }

  hideTooltip() {
    if (this.tooltipElement) {
      this.tooltipElement.style.display = 'none';
    }
  }
}

document.addEventListener('adev:tooltip:init', function (e) {
  new Tooltip();
});

document.dispatchEvent(new CustomEvent('adev:tooltip:init'));
.adev-tooltip {
      position: absolute;
      width: max-content;
      max-width:240px;
      padding: 8px 12px;
      background: #000;
      color: #fff;
      font-size: 12px;
      border-radius: 5px;
      z-index: 10000;
      visibility: hidden;
      display: none;
}
.adev-tooltip::after {
    content: '';
    position: absolute;
    --size: 13px;
    width: var(--size);
    height: var(--size);
    background: #000;
    bottom: 0;
    left: 3px;
    transform: rotate(45deg)translateX(50%);
    z-index: 1;
}

.adev-tooltip[data-tooltip-position="right"]::after {
    left: auto;
    right: 10px;
}

Usage:

data-adev-tooltip on element and data-title for the text.

<div class="shipping-icon" data-adev-tooltip data-title="Your Text here">
        <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 12a9 9 0 1 0 18 0a9 9 0 0 0-18 0m9-4v4m0 4h.01"/></svg>
</div>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment