A lightweight, vanilla JavaScript tooltip library

v2 v1


Hover your cursor over the buttons to see Tippy in action!Tap the buttons to see Tippy in action!

important_devices Browser support

Tippy gracefully degrades on older browsers (and with JavaScript disabled) by using the browser's default title tooltip.

Supported browsers

Browsers which support requestAnimationFrame. See caniuse. If your audience has low Opera Mini usage (common in western countries), then support should be >96%.

Touch devices

Tippy works on touch devices almost the same as on desktop/mouse devices. However on iOS devices, in order for tooltips to close when tapping anywhere on the body and to trigger hover events on non-clickable elements, a .tippy-touch { cursor: pointer !important; } class is added to the body.

Dynamic input detection

For certain settings to work reliably depending on the type of user input (such as mouse or touch), dynamic input detection is enabled by default. To disable or enable, use:


You may also access the Browser object settings set internally via:



Tooltips have ARIA labelling to ensure accessibility.

tag_facesGetting started

file_download Download the latest release (.zip)

Alternatively, you can install through npm:

npm install --save tippy.js@1.4.2

or use the unpkg.com CDN:


1. Place the tippy.css stylesheet in your document's head.

<link rel="stylesheet" href="css/tippy.css">

2. Include the tippy.min.js file in your document before your own scripts:

<script src="js/tippy.min.js"></script>

If you installed the npm package, the JS and CSS files are available in the dist folder:


tippy.js comes bundled with popper.js (unminified), and tippy.standalone.js (minified) is Tippy by itself if you want use a different version of Popper.js.

buildCreating a tooltip

First, give an element a title attribute containing what you want the tooltip to say.

<button class="btn" title="I'm a tooltip!">Text</button>

Then, to give it a Tippy tooltip, call the tippy() function by passing in a CSS selector.



For details on the type of CSS selector string you can use, see document.querySelectorAll() for reference.

Additional selector options

You aren't limited to just a CSS selector string as input. You can also directly use a DOM element (or an array of elements):


Or a NodeList: v1.3



For more specialized cases, you can also pass in a custom virtual object instead of a DOM node to act as the positioning reference. v1.4

const refObject = {
  attributes: {
    title: 'Tooltip text'
  getBoundingClientRect() {
    return {
      top:  5 + window.pageYOffset,
      left: 5 + window.pageXOffset,
      right: 5 + window.pageXOffset,
      bottom: 220 + window.pageYOffset,
      width: 1,
      height: 1
  get clientWidth() {
    return 30
  get clientHeight() {
    return 30


Elements without a title attribute (or an empty title) and without an HTML template will not receive a tooltip.

settingsCustomizing tooltips

tippy() takes an object as a second argument for you to customize the tooltips being instantiated. Here's an example:

tippy('.tippy', {
  position: 'right',
  animation: 'scale',
  duration: 1000,
  arrow: true


Data attributes

You can also specify settings on the element itself by adding data-* attributes. This overrides any global settings specified in the instance.

  class="btn tippy"
  title="I'm a tooltip!"
  data-duration="[400, 0]"


This is helpful if you want to globally define settings, but make a few tooltips different without having to call tippy() again with different settings.

settings_applicationsAll settings

Note: settings with camelCase are lowercase in HTML. For example, animateFill is data-animatefill in HTML.

Settingsettings Defaultremove Optionssettings_input_component Rolebuild
position 'top' 'top' 'bottom' 'left' 'right' Specifies which direction to position the tooltip on the element. Add the suffix -start or -end to shift the position. 'top-end' is an example.
trigger 'mouseenter focus' 'mouseenter' 'focus' 'click' 'manual' {custom} Specifies which type of events will trigger a tooltip to show. Separate each by a space. mouseenter is for hovering and touch on mobile, and focus is for keyboard navigation. Use manual if you want to show/hide the tooltip manually (see the Methods section below). {custom} refers to the fact that you can have any event listener, but it won't have the opposite "hide" event.
interactive false Boolean Makes a tooltip interactive, i.e. will not close when the user hovers over or clicks on the tooltip. This lets you create a popover (similar to Bootstrap) when used in conjunction with a click trigger.
interactiveBorder 2 Number (pixels) Specifies the size of the invisible border around an interactive tooltip that will prevent it from closing. Only applies to mouseenter triggered tooltips.
delay 0 Number | Array (milliseconds) Specifies how long it takes after a show or hide event is fired for a tooltip to begin showing or hiding. Use an array to specify a different show and hide delay, such as [300, 100].
animation 'shift' 'shift' 'perspective' 'fade' 'scale' Specifies the type of transition animation a tooltip has.
arrow false Boolean Adds an arrow pointing to the tooltipped element. Setting this to true disables animateFill.
arrowSize 'regular' 'small' 'regular' 'big' Specifies how big the tooltip's arrow is. The sizes are 5px, 7px and 10px respectively.
animateFill true Boolean Adds a material design-esque filling animation. This is disabled if you have arrow set to true.
duration 350 Number | Array (milliseconds) Specifies how long the transition animation takes to complete when showing a tooltip. Use an array to specify a different show and hide duration, such as [300, 100].
html false false | template id | Element Allows you to add HTML to a tooltip. See Creating HTML templates.
size 'regular' 'small' 'regular' 'big' Specifies how big the tooltip is.
distance 10 Number (pixels) Specifies how far away the tooltip is from its element.
theme 'dark' 'dark' 'light' 'transparent' The CSS styling theme. You can add your own easily. See Creating themes.
offset 0 Number String (pixels) Offsets a tooltip on a certain axis. Use a string such as '25, 10' to offset it on both the x and y axes.
hideOnClick true true false 'persistent' Specifies whether to hide a tooltip upon clicking its element after hovering over and when clicking elsewhere on the document. For click-triggered tooltips when using false, toggle functionality remains unless you use 'persistent'.
multiple false Boolean Specifies whether to allow multiple tooltips open on the page (click trigger only).
followCursor false Boolean Specifies whether to follow the user's mouse cursor (mouse devices only).
inertia false Boolean Modifies the transition-timing-function with a cubic bezier to create a "slingshot" intertial effect.
flipDuration 300 Number (milliseconds) Specifies the transition duration between flips and when updating a tooltip's position on window resize.
sticky false Boolean Specifies whether the tooltip should stick to its element reference when it's showing (for example, if the element is animated/moves).
stickyDuration 200 Number (milliseconds) Specifies the 'smoothing' transition when the popper's position updates as its element moves.
appendTo document.body Element Specifies which element the tooltip popper is appended to.
zIndex 9999 Number Specifies the z-index of the tooltip popper.
touchHold false Boolean Changes the trigger behavior on touch devices. It will change it from a tap to show and tap off to hide, to a tap and hold to show, and a release to hide.
performance false Boolean Disables data-* attribute settings to make initial instantiation time faster.
dynamicTitle false Boolean Whenever the title attribute on the reference element changes, the tooltip will automatically be updated.
popperOptions {} Object Allows more control over tooltip positioning and behavior. See right below.

Finer control over tooltips

You can define a popperOptions setting with Popper.js settings. View the Popper.js documentation to see the settings you can specify.

Here's an example of how to integrate Popper.js settings into Tippy, so that a tooltip will flip to the bottom from the right if there's not enough room in the viewport.

tippy('.mySelector', {
  position: 'right',
  popperOptions: {
    modifiers: {
      flip: {
        behavior: ['right', 'bottom']


By default, tooltips will flip on their opposite axis if there is not enough room in the viewport. If you want to force no flip, then use:

tippy('.mySelector', {
  popperOptions: {
    modifiers: {
      flip: {
        enabled: false

Tooltips inside a scrollable container

You may encounter issues with tooltip positioning when it's given to an element within a scrollable container. Firstly, when the element is no longer visible, the tooltip will stay stuck within the viewport. Secondly, it transitions between position updates. To solve this, simply specify a flipDuration of 0 and add the following popperOptions:

tippy('.mySelector', {
  flipDuration: 0,
  popperOptions: {
    modifiers: {
      preventOverflow: {
        enabled: false


If you want things to happen at certain times during a tooltip's show/hide events, you can add callback functions in the settings object. There are 5 to use:

Note: Callback functions prior to v1.1 should not have the on prefix; simply use show, hide, etc. However, starting from v1.1 they are deprecated in favor of the more semantic on* names which better indicate a callback function.

tippy('.tippy', {
  onShow: function () {
    // When the tooltip has been triggered and has started to transition in
  onShown: function () {
    // When the tooltip has fully transitioned in and is showing
  onHide: function () {
    // When the tooltip has begun to transition out
  onHidden: function () {
    // When the tooltip has fully transitioned out and is hidden
  wait: function (show, event) {
    // See below for an explanation

this inside the callbacks refers to the popper being shown or hidden.

wait is a special callback that allows you to control the show method for easier integration into UI libraries like React when using HTML tooltips with components. The function itself takes a callback as a parameter, which is just the show method for the tooltip.

Example usage (ES6 syntax):

tippy('.tippy', {
  wait(show, event) {
    // Change your app model to be rendered by the UI library/framework

    // Queue show to run once rendering is complete
    setTimeout(() => {
      // update(popper) content
      // event.type to see what trigger fired the event

    }, 0)

See here for reference.

Modify the default settings

You can change the default settings by accessing them via tippy.Defaults.


tippy() returns a new Tippy object with the following methods available:

  • getPopperElement - returns the tooltip popper element
  • getReferenceElement - returns the element that has the tooltip
  • getReferenceData - returns the object containing information about the reference
  • show - shows a tooltip
  • hide - hides a tooltip
  • update - updates a tooltip with new content
  • destroy - destroys an individual tooltip
  • destroyAll - destroys all tooltips created by the instance


The popper is the parent element while the tooltip is the child of the popper.

The element you give the tooltip to is called the reference element.

Showing and hiding tooltips programmatically

<button id="myButton" title="Tooltip">My element</button>

First, save the instance:

const tip = tippy('#myButton')

Next, find the reference element's popper reference by calling the method getPopperElement and passing the element in directly:

const el = document.querySelector('#myButton')
const popper = tip.getPopperElement(el)

Then, call the show() or hide() method by passing in the popper element:


Pass a number in the second argument to specify a transition duration:

tip.show(popper, 500)

Finding the reference element from the popper element

Pass the popper element to find its reference element into this method:

const el = tip.getReferenceElement(popper)

Updating a tooltip with new content

The update() method will check for a new title attribute on the element that has the tooltip.

el.setAttribute('title', 'New content!')

If it's a HTML template instead, it will inject the new HTML of the template.

Destroying tooltips

The destroy() method will destroy an individual tooltip.


The destroyAll() method will destroy every tooltip created by the instance.


Reference data

Retrieve the data object for a particular tooltip reference by passing in either the reference element or the popper element.

const data = tip.getReferenceData(el || popper)

This object contains information about a reference element and its popper element.

In order to optimize performance, the popperInstance property is not created until the tooltip is shown for the first time, so the data object will not contain it until you've shown a tooltip at least once.

AJAX tooltips

Here's an example of dynamic content which on show, fetches a new random image from the Unsplash API. Note: this requires a browser which supports the newer fetch API.

Loading a new image...

Codepen demo

Reactivity v1.1

Tooltips react to content changes. For example, if a paragraph element inside the tooltip is removed or changed, the tooltip will automatically update its position.

Note: This isn't supported in IE10 natively (unless polyfilled) because it uses MutationObserver.

codeCreating HTML templates

There are two options you have when creating a template. You can either clone it or use it directly.


Use the template's id selector string.

Option: html: '#myTemplate'

  • Can be re-used multiple times
  • Not removed from the page
  • Will not save event listeners attached to it
  • Not directly modifiable


Use Element directly.

Option: html: document.querySelector('#myTemplate')

  • Can only be used once
  • Removed from the page and appended directly to the tooltip
  • Saves event listeners attached to it
  • Directly modifiable

Example HTML template

<div id="myTemplate">
  <p>Fun <strong>non-interactive HTML</strong> here</p>
  <img alt="cat" height="150" src="img/cat.jpg">
tippy('#myElement', {
  html: document.querySelector('#myTemplate'), // DIRECT ELEMENT option
  arrow: true,
  animation: 'fade'


Dynamically pulling HTML content

You can use a function instead of an element reference as the html setting. The function will be executed with one argument: the element the tooltip is being added to. This is useful for cases in which you have multiple elements, each one having its own unique tooltip.

tippy('.my-elements', {
  html: el => el.querySelector('.popup')

Styling tooltips with HTML content

Use this selector to target your tooltip template. Replace "#myTemplate" with your own template's id, including the leading hash. If you're using a DOM element in the html setting and no id is found, it defaults to tippy-html-template.

.tippy-tooltip[data-template-id="#myTemplate"] {
  /* Your styling here. Example: */
  padding: 2rem;

Interactive elements also receive a class of active upon triggering so that you can still style hover effects when the user has moved the cursor away from the tooltipped element and onto the tooltip itself.

.my-tooltipped-element:hover, .my-tooltipped-element.active {
  /* Your hover styling here. */

brushCreating themes

Tippy allows you to create your own theme for your tooltips easily. If you wanted to make a theme called honeybee, then your CSS would look like:

.tippy-tooltip.honeybee-theme {
  /* Your styling here. Example: */
  background-color: yellow;
  border: 2px solid orange;

Themes need the -theme suffix.

To style the arrow, target the element with an x-arrow attribute:

.tippy-tooltip.honeybee-theme [x-arrow] {
  /* Your arrow styling here. */

Arrows are CSS triangles, read this comment to see how to style arrows properly.

In case you want to target the content directly:

.tippy-tooltip.honeybee-theme .tippy-tooltip-content {
  /* Your styling here. Example: */
  color: black;

To style the animateFill circle, target the element with an x-circle attribute:

.tippy-tooltip.honeybee-theme [x-circle] {
  /* Your styling here. Example: */
  background-color: yellow;

Then, specify a theme setting with your theme's name:

tippy('.tippy', {
  theme: 'honeybee'

...or specify a data-theme attribute on your tooltipped element.

<button class="btn tippy" title="I'm a tooltip" data-theme="honeybee">Honeybee theme</button>

Example custom theme:

Multiple themes

Add multiple themes by separating each by a space.

tippy('.tippy', {
  theme: 'menu light'

This will add the classes .menu-theme and .light-theme to the tooltip's class list.


You can have thousands of tooltipped elements without affecting page performance after the initial instantiation. Tooltips are only appended to the DOM when shown, and removed when hidden. Popper.js only listens to scroll and resize events when a popper (tooltip) is showing, and also updates the position on show.

Note: these tooltips are created with performance mode set to true.


MIT. Also check Popper.js' license.

This is an example of an interactive HTML tooltip created with a template.