A lightweight, pure JavaScript tooltip library


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

important_devices Browser support

Most browsers from 2012 onwards (IE10+). As of early 2017, it should support 95% of users (caniuse.com); depending on your target audience it could be higher or lower. Tippy gracefully degrades on older browsers (and with JavaScript disabled) by using the browser's default title tooltip.

Unsupported browsers

Old IE and Opera Mini should not throw errors but others might

Browsers Year last version released User share
IE <= 9 2011 0.6%
Opera Mini 2015 3%
Firefox <= 15 2012 0.1%
Safari <= 5.1 2011 0.1%
Opera <= 12.1 2011 0.1%
Potentially unsupported/untracked, very old mobile browsers N/A 1-2%

Touch devices

Tippy works on touch devices almost the same as on desktop/mouse devices. However, in order for tooltips to close when tapping anywhere on the body on iOS devices, it adds a .tippy-touch { cursor: pointer !important; } class to the body.


Tooltips in v0.8.1+ should now be properly accessible.

tag_facesGetting started

file_download Download the latest release (.zip)

Alternatively, you can install through npm:

npm install --save tippy.js

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 tippy" title="I'm a tooltip!">Text</button>

Then, to give it a Tippy tooltip, create a new Tippy instance by passing in a CSS selector.

new Tippy('.tippy')


You can also directly pass in a DOM element:

new Tippy(document.querySelector('#myElement'))

Elements without a title attribute or an HTML template will not receive a tooltip. You can pass in any CSS selector to initialize it. See document.querySelectorAll() for reference.

Here's how to create a tooltip for an element with an id of hello:

new Tippy('#hello')

Minimal Working Example, with all files in the same directory:

<!DOCTYPE html>
    <link rel="stylesheet" href="tippy.css">
    <button id="myId" title="Tooltip text">Button text</button>
    <script src="tippy.js"></script>
    new Tippy('#myId')

settingsCustomizing tooltips

Tippy's constructor takes an object as a second parameter for you to customize all tooltips being instantiated. Here's an example:

new 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 Tippy instance.

<button class="btn tippy" title="I'm a tooltip!" data-duration="300" data-arrow="false" data-animation="shift" data-position="bottom">Overridden</button>


This is helpful if you want to globally define settings, but make a few tooltips different without having to make a new Tippy instance.

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/programmatically (see below). {custom} refers to the fact that you can have any event listener, but it won't have the opposite "hide" event.
interactive false true false 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.
delay 0 Any integer >= 0 (milliseconds) Specifies how long it takes after a trigger event is fired for a tooltip to show.
hideDelay 0 Any integer >= 0 (milliseconds) Specifies how long it takes after a leave event is fired for a tooltip to hide. Does not apply when clicking on the document to hide tooltips.
animation 'shift' 'shift' 'perspective' 'fade' 'scale' Specifies the type of transition animation a tooltip has.
arrow false true false 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.
animateFill true true false Adds a material design-esque filling animation. This is disabled if you have arrow set to true.
duration 375 Any integer >= 0 (milliseconds) Specifies how long the transition animation takes to complete when showing a tooltip.
hideDuration duration Any integer >= 0 (milliseconds) Specifies how long the transition animation takes to complete when hiding a tooltip.
html false false or a template id 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 Any 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 Any number (pixels) Offsets the tooltip on its opposite axis. For position top and bottom, it acts as offsetX. For position left and right, it acts as offsetY.
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 true false Specifies whether to allow multiple tooltips open on the page (click trigger only).
followCursor false true false Specifies whether to follow the user's mouse cursor (mouse devices only).
inertia false true false Modifies the transition-timing-function with a cubic bezier to create a "slingshot" intertial effect.
transitionFlip true true false Specifies whether to transition between flips or not. Uses the same transition timing as duration.
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.

new 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. (v0.4.x's new Popper.js version fixed top-positioned tooltips so they will also flip). If you want to force no flip, then use:

// Force no flip for a top-positioned tooltip
new Tippy('.mySelector', {
  popperOptions: {
      modifiers: {
          flip: {
              behavior: ['top']


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:

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

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):

new 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.

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 since v0.9.0 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, give your instance a theme setting with your theme's name:

new 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:

codeCreating HTML templates

It's worth noting that basic HTML can be injected straight into the element's title attribute. Example: title="<strong>text</strong>", so there's no need to create a template if you want something simple like that (though for backwards browser compatibility/fallback it won't look pretty). For more complex scenarios, use a template.

Regarding fallback: HTML template tooltips can't be shown to older browsers (IE <= 9), so you'll need to consider that when using them on your site.

Create an HTML template on the document. Set its style to display: none; so it won't be seen. You don't need to specify a title attribute with a HTML templated tooltip; it will be ignored. You may want to add a title attribute however to notify incompatible users of something.

<div id="my-template-id" style="display: none;">
  <p>Fun <strong>non-interactive HTML</strong> here</p>
  <img alt="cat" height="150" src="img/cat.jpg">

In your instance, specify either the id in the html setting, or the element itself.

new Tippy('#tooltip-with-my-template', {
  html: '#my-template-id', // or document.querySelector('#my-template-id')
  arrow: true,
  animation: 'fade'


Styling tooltips with HTML content

Use this selector to target your tooltip template. Replace "#my-template-id" 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="#my-template-id"] {
  /* 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. */
You should disable animateFill when using HTML content. If the tooltip is tall, the circle element inside that creates the effect won't fill the entire tooltip. Non-textual content also breaks the effect's illusion.

settings_remoteControlling tooltips manually

Save the Tippy instance:

const instance = new Tippy('.tippy')

Find the tooltipped element's popper reference by calling the method getPopperElement and passing it in (the tooltipped element, not the popper) directly:

const popper = instance.getPopperElement(document.querySelector('#myElement'))
It must be a single tooltipped element.

Now you can show, hide, update or destroy it.


The show and hide methods take a transition duration as their second (optional) parameters.

The update method will update the popper's tooltip content by checking if there is a new title attribute on its tooltipped element. If it's a HTML tooltip, it will inject the new HTML of the template.

destroying a popper removes listeners from its tooltipped element reference, destroys its popper instance, and removes it from the global references array.


In this example, we use another button to control the tooltip. Give controllers a data-tippy-controller attribute (doesn't need a value).

First, hover over the two buttons on the right to see their original content. If you click the button on the left, it will update the tooltips with new content.

Finding the reverse reference

In v0.5.x it's now possible to find the reverse reference (i.e., the tooltipped element from a popper element).

const el = instance.getTooltippedElement(popper)

An example of this being useful is clicking inside a popper, and getting the popper by doing event.target.closest('.tippy-popper'). Then, you might want to do something with its element reference.


As of v0.8.x, you can have thousands of tooltipped elements without affecting page performance. 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.

Instantiation time has also decreased 10x over v0.7.x and prior.


MIT. Also check Popper.js' license.