npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

easy-tooltips

v3.0.3

Published

A lightweight, zero-dependency tooltip library using modern JavaScript and CSS.

Readme

easy-tooltips

A lightweight, zero-dependency tooltip library using modern JavaScript and CSS.
Just add data-easy-tooltip to any element! No setup or config required.

npm version jsDelivr License: MIT

Live Demo

Features

  • No dependencies
  • Works with mouse, touch, and keyboard focus
  • Customizable via CSS variables
  • Automatically repositions and shifts to fit the screen
  • Smooth, non-interrupting animations with smart skip-delay between adjacent tooltips
  • Anchor to the trigger element, the cursor, or where the user first hovered
  • Plain text or arbitrary HTML content
  • Seamless body + arrow drawn as a single SVG path
  • Compatible with Vue, React, Svelte, and more

Quick Start

Install via npm

npm install easy-tooltips
import "easy-tooltips/styles.css"
import "easy-tooltips"

Or use via CDN

https://www.jsdelivr.com/package/npm/easy-tooltips

Add tooltips to your HTML

<button data-easy-tooltip="Click to save your changes">Save</button>
<span data-easy-tooltip="This field is required">Username *</span>
<div data-easy-tooltip="Multi-line tooltips&#10;are supported too">Info</div>

Multi-line text uses &#10; (newline). For full HTML content see Custom HTML below.

No additional setup is needed for Vue, React, Svelte, or other frameworks! Tooltips automatically update when the element updates!

Tooltips also show on keyboard focus. Natively focusable elements (buttons, links, inputs) work automatically; for other elements (such as a <div> or <span>), add tabindex="0" so they can receive focus.

Advanced Usage

Custom HTML

You can render custom HTML inside a tooltip using data-easy-tooltip-src. The value can be a CSS selector or the literal keyword next.

The matched element's content is copied into the tooltip.

Using a CSS selector Point to any element in the document. The value is matched by id first, then as a CSS selector, so tip-shipping and #tip-shipping both work.

<button data-easy-tooltip-src="#tip-shipping">Shipping info</button>
<template id="tip-shipping">
  <strong>Free shipping</strong> on orders over £50<br>
  Delivered in 2 to 4 working days
</template>

Using next Use next to automatically pull content from the next DOM element. The source element is automatically hidden.

<button data-easy-tooltip-src="next">Ingredients</button>
<div>
  <ul>
    <li>Oats</li>
    <li>Honey</li>
    <li>Sea salt</li>
  </ul>
</div>

Custom tooltip classes

For styling specific tooltips, add data-easy-tooltip-class. The value is applied as a class on the generated tooltip:

<button data-easy-tooltip="Saved!" data-easy-tooltip-class="success-tooltip">Save</button>
<button data-easy-tooltip="This cannot be undone!" data-easy-tooltip-class="danger-tooltip bold-tooltip">Delete</button>
.success-tooltip {
  --easy-tooltip-background-color: #f0fdf4;
  --easy-tooltip-border-color: #27ae60;
  --easy-tooltip-text-color: #27ae60;
}

.danger-tooltip {
  --easy-tooltip-background-color: #fef2f2;
  --easy-tooltip-border-color: #e74c3c;
  --easy-tooltip-text-color: #e74c3c;
}

.bold-tooltip {
  font-weight: bold;
}

Preferred side

Use data-easy-tooltip-prefer to control which side a tooltip shows on. It still flips to the opposite side when there isn't room. Using left or right switches the tooltip to horizontal mode.

  • above (default): show above, fall back to below
  • below: show below, fall back to above
  • left: show to the left, fall back to the right
  • right: show to the right, fall back to the left
<button data-easy-tooltip="Shows below" data-easy-tooltip-prefer="below">Hover me</button>
<button data-easy-tooltip="Shows on the right" data-easy-tooltip-prefer="right">Hover me</button>

Anchor modes

By default a tooltip is anchored to its trigger element. Use data-easy-tooltip-anchor to change the anchor point:

  • element (default): anchored to the trigger's bounding box.
  • cursor: anchored to the cursor (or touch point), follows the cursor as it moves around the element. On touch, the tooltip appears at the tap point and tracks the finger if you drag.
  • pin: anchored to the first cursor or touch point on entry, then frozen there. Continues tracking the page as you scroll so the anchor stays at the same content position.
<div data-easy-tooltip="I follow your cursor" data-easy-tooltip-anchor="cursor">…</div>
<div data-easy-tooltip="I stay where you first hovered" data-easy-tooltip-anchor="pin">…</div>

Keyboard focus has no coordinates and automatically falls back to element anchoring.

Customization

You can style tooltips using CSS variables (recommended) or by targeting the tooltip classes directly. Note that some CSS variables are required for proper positioning:

:root {
  /* Tooltip appearance */
  --easy-tooltip-background-color: #fff;     /* Background color */
  --easy-tooltip-text-color: #000;           /* Text color */
  --easy-tooltip-border-color: #aaa;         /* Border color */
  --easy-tooltip-border-size: 1px;           /* Border thickness */
  --easy-tooltip-border-radius: 4px;         /* Corner radius of the tooltip */
  --easy-tooltip-padding: 8px 12px;          /* Inner padding */
  --easy-tooltip-max-width: 100%;            /* Maximum tooltip width */

  /* Positioning */
  --easy-tooltip-distance: 16px;             /* Distance from trigger element */
  --easy-tooltip-viewport-padding: 16px;     /* Minimum distance from screen edges */
  --easy-tooltip-arrow-size: 16px;           /* Arrow size (height defaults to width / 2; 0 to disable) */
  --easy-tooltip-arrow-size: 16px 8px;       /* Or specify arrow width and height separately */
  --easy-tooltip-arrow-edge-buffer-x: 12px;  /* Minimum arrow gap from where the border radius starts (for above or below tooltips) */
  --easy-tooltip-arrow-edge-buffer-y: 6px;   /* Minimum arrow gap from where the border radius starts (for left or right tooltips) */
  --easy-tooltip-arrow-radius: 0;            /* Border radius of the arrow tip */

  /* Animation */
  --easy-tooltip-animation-length: 0.15s;    /* Duration of fade animation */
  --easy-tooltip-animation-distance: 4px;    /* Distance the tooltip slides in */
  --easy-tooltip-delay: 0s;                  /* Base delay before the tooltip shows; always added */
  --easy-tooltip-inactive-delay: 0.15s;      /* Extra delay when no tooltip was recently active; drops to 0 once a tooltip is showing */
  --easy-tooltip-cooldown: 0.15s;            /* How long after the last tooltip closes before the inactive-delay applies again */
}

Show delay and quick-switch

Easy-tooltips uses a two-part delay so that the first tooltip waits, but switching between adjacent tooltips feels instant:

  • On the first hover, the tooltip waits delay + inactive-delay (0 + 0.15s by default) before showing. This protects against accidental hovers.
  • Once a tooltip has fully appeared, all subsequent tooltips skip the inactive-delay and show in just delay (0s by default, i.e. instantly).
  • When all tooltips have been closed for cooldown (0.15s by default), behaviour resets to "first hover" again.

Each part is its own variable so you can tune them independently. For example, a slow, deliberate tooltip with a long initial wait but instant skip:

.slow-tooltip {
  --easy-tooltip-inactive-delay: 1s;
}

Or a permanent delay regardless of recent activity (e.g. a 500ms reveal on every tooltip):

.always-slow-tooltip {
  --easy-tooltip-delay: 500ms;
}

Advanced customization

The tooltip body and arrow are drawn as a single SVG path, so anything beyond the variables can be done by targeting the path directly with SVG-flavored CSS. .easy-tooltip-bg is the SVG element; .easy-tooltip-bg path is the path that draws the outline and fill.

Borders

The border is the SVG path's stroke, so any stroke property works:

/* Dashed border */
.dashed-tooltip .easy-tooltip-bg path {
  stroke-dasharray: 5 3;
  stroke-linecap: round;
}

Backgrounds

fill on the SVG path only accepts a <paint> value, so CSS gradients (linear-gradient, etc.) won't apply directly. To use a gradient (or any other SVG paint server), declare it once in the document and reference it by id:

<svg width="0" height="0" style="position:absolute" aria-hidden="true">
  <defs>
    <linearGradient id="brand-gradient" x1="0" y1="0" x2="1" y2="1">
      <stop offset="0%" stop-color="#3498db"/>
      <stop offset="100%" stop-color="#9b59b6"/>
    </linearGradient>
  </defs>
</svg>
.gradient-tooltip .easy-tooltip-bg path {
  fill: url(#brand-gradient);
}

The same approach works for stroke (gradient borders), and for radial, conic, or pattern paint servers.

For a drop shadow that follows the full body + arrow shape, apply a filter to the SVG element:

.shadow-tooltip .easy-tooltip-bg {
  filter: drop-shadow(0 4px 12px rgba(0, 0, 0, 0.25));
}

How it works

Easy-tooltips uses a smart positioning system that:

  1. Picks a side - Shows on the preferred side (above by default, or below/left/right) and flips to the opposite side when there isn't room
  2. Keeps it on screen - Shifts the tooltip along its edge (horizontally for above/below, vertically for left/right) so it stays within the viewport while the arrow keeps pointing at the element
  3. Falls back gracefully - When a tooltip can't fit on either side, it pins inside the viewport instead of overflowing
  4. Manages animations - Queues tooltip updates to prevent conflicts and flicker on rapid hover
  5. Skips the delay when grazing - The first hover waits a short delay to ignore accidental movement, but once any tooltip is showing, switching to adjacent tooltips is instant until you stop hovering for the cooldown period
  6. Stacks newest on top - When multiple tooltips are visible at once, the most recently activated one renders above the others
  7. Cleans up - Removes a tooltip automatically when its trigger element leaves the DOM

License

MIT © Ewan Howell