0
0
SvelteHow-ToBeginner · 3 min read

How to Create Tooltip Action in Svelte: Simple Guide

In Svelte, you can create a tooltip action by defining a function that attaches event listeners to an element and manages a tooltip's visibility and position. Use the use: directive to apply this action to any element, showing a tooltip on hover or focus.
📐

Syntax

A tooltip action in Svelte is a function that receives the element and optional parameters. It sets up event listeners like mouseenter and mouseleave to show or hide the tooltip. The action returns an object with a destroy method to clean up listeners when the element is removed.

Use it in your component with use:tooltip={'Your tooltip text'}.

javascript
function tooltip(node, text) {
  let tooltipElement;

  function mouseEnter() {
    tooltipElement = document.createElement('div');
    tooltipElement.textContent = text;
    tooltipElement.style.position = 'absolute';
    tooltipElement.style.background = 'black';
    tooltipElement.style.color = 'white';
    tooltipElement.style.padding = '0.25rem 0.5rem';
    tooltipElement.style.borderRadius = '0.25rem';
    tooltipElement.style.fontSize = '0.75rem';
    tooltipElement.style.pointerEvents = 'none';
    document.body.appendChild(tooltipElement);
    const rect = node.getBoundingClientRect();
    tooltipElement.style.top = rect.bottom + window.scrollY + 'px';
    tooltipElement.style.left = rect.left + window.scrollX + 'px';
  }

  function mouseLeave() {
    if (tooltipElement) {
      tooltipElement.remove();
      tooltipElement = null;
    }
  }

  node.addEventListener('mouseenter', mouseEnter);
  node.addEventListener('mouseleave', mouseLeave);

  return {
    destroy() {
      node.removeEventListener('mouseenter', mouseEnter);
      node.removeEventListener('mouseleave', mouseLeave);
      mouseLeave();
    }
  };
}
💻

Example

This example shows how to use the tooltip action on a button. When you hover over the button, a black tooltip with white text appears below it.

svelte
<script>
  function tooltip(node, text) {
    let tooltipElement;

    function mouseEnter() {
      tooltipElement = document.createElement('div');
      tooltipElement.textContent = text;
      tooltipElement.style.position = 'absolute';
      tooltipElement.style.background = 'black';
      tooltipElement.style.color = 'white';
      tooltipElement.style.padding = '0.25rem 0.5rem';
      tooltipElement.style.borderRadius = '0.25rem';
      tooltipElement.style.fontSize = '0.75rem';
      tooltipElement.style.pointerEvents = 'none';
      document.body.appendChild(tooltipElement);
      const rect = node.getBoundingClientRect();
      tooltipElement.style.top = rect.bottom + window.scrollY + 'px';
      tooltipElement.style.left = rect.left + window.scrollX + 'px';
    }

    function mouseLeave() {
      if (tooltipElement) {
        tooltipElement.remove();
        tooltipElement = null;
      }
    }

    node.addEventListener('mouseenter', mouseEnter);
    node.addEventListener('mouseleave', mouseLeave);

    return {
      destroy() {
        node.removeEventListener('mouseenter', mouseEnter);
        node.removeEventListener('mouseleave', mouseLeave);
        mouseLeave();
      }
    };
  }
</script>

<button use:tooltip="Click me tooltip">Hover me</button>
Output
A button labeled 'Hover me' that shows a black tooltip with white text 'Click me tooltip' below it when hovered.
⚠️

Common Pitfalls

  • Not cleaning up event listeners in the destroy method can cause memory leaks.
  • Forgetting to position the tooltip relative to the element can make it appear in wrong places.
  • Not handling scrolling or window resizing may cause tooltip to stay in wrong position.
  • Using fixed tooltip elements inside the component instead of appending to document.body can cause clipping issues.
javascript
/* Wrong: No cleanup and tooltip inside node */
function tooltip(node, text) {
  const tooltipElement = document.createElement('div');
  tooltipElement.textContent = text;
  node.appendChild(tooltipElement);
  node.addEventListener('mouseenter', () => {
    tooltipElement.style.display = 'block';
  });
  node.addEventListener('mouseleave', () => {
    tooltipElement.style.display = 'none';
  });
  // No destroy method to remove listeners
}

/* Right: Cleanup and append to body with positioning */
function tooltip(node, text) {
  let tooltipElement;
  function mouseEnter() {
    tooltipElement = document.createElement('div');
    tooltipElement.textContent = text;
    tooltipElement.style.position = 'absolute';
    document.body.appendChild(tooltipElement);
    const rect = node.getBoundingClientRect();
    tooltipElement.style.top = rect.bottom + window.scrollY + 'px';
    tooltipElement.style.left = rect.left + window.scrollX + 'px';
  }
  function mouseLeave() {
    if (tooltipElement) {
      tooltipElement.remove();
      tooltipElement = null;
    }
  }
  node.addEventListener('mouseenter', mouseEnter);
  node.addEventListener('mouseleave', mouseLeave);
  return {
    destroy() {
      node.removeEventListener('mouseenter', mouseEnter);
      node.removeEventListener('mouseleave', mouseLeave);
      mouseLeave();
    }
  };
}
📊

Quick Reference

  • Define action: function with node and params.
  • Attach events: mouseenter and mouseleave to show/hide tooltip.
  • Position tooltip: use getBoundingClientRect() and window.scrollX/Y.
  • Cleanup: remove event listeners and tooltip element in destroy().
  • Use: use:tooltip="text" on any element.

Key Takeaways

Create tooltip as a Svelte action function that manages event listeners and DOM elements.
Always clean up event listeners and tooltip elements in the action's destroy method.
Position the tooltip absolutely relative to the target element using bounding rectangle and scroll offsets.
Apply the tooltip action with use:tooltip="text" on any element to show tooltips on hover.
Avoid placing tooltip elements inside the target node to prevent clipping and positioning issues.