Skip to content
Tippy Logo


View on GitHub
Currently v6.3.0


#What syntax theme is used on this website?

It's a theme I made called Moonlight!

#Nothing is working

Make sure Tippy's scripts are placed before your own scripts, at the very bottom of the page, like so:

<!DOCTYPE html> <html> <head> <title>My page</title> </head> <body> <button>Text</button> <!-- Very end of the body --> <script src=""></script> <script src=""></script> <script> tippy('button', {content: 'tooltip'}); </script> </body> </html>

#My tooltip appears cut off or is not showing at all

When using interactive: true, the tippy may be invisible or appear cut off if your reference element is in a container with:

  • CSS position
  • CSS overflow

There are a couple of solutions.

  1. Specify an appendTo element outside of the clipping container context. This requires a focus management solution usually.
tippy(targets, { // ... appendTo: document.body, });
  1. Use strategy: "fixed" (this has some quirks on some browsers like Safari regarding updating the position on scroll), so avoid it if possible.
tippy(targets, { // ... popperOptions: { strategy: 'fixed', }, });

#I'm getting Uncaught ReferenceError: process is not defined

If you're using the ESM or CJS versions and importing like this:

import tippy from 'tippy.js'; // or const tippy = require('tippy.js').default;

Tippy uses a special expression to distinguish a development and production environment. For you, the developer, there are lots of warnings and error messages to help your development experience. For your end users, all of this needs to get stripped out because it reduces performance and increases bundle size.

Tools like create-react-app and Parcel bundler handle this automatically.


View the following link.


Install the replace plugin.

import replace from '@rollup/plugin-replace'; export default { // ... plugins: [ // Production config replace({ 'process.env.NODE_ENV': JSON.stringify('production'), }), // OR development config replace({ 'process.env.NODE_ENV': JSON.stringify('development'), }), // You can also use process.env.NODE_ENV and set the env variables when // running the rollup command to merge the above into one call ], };

#How do I use the animations or themes stylesheets with the CDN?

For brevity, this documentation uses import syntax and assumes a module bundler environment. If you're using the CDN version, then you'll be using <link> tags to import separate CSS stylesheets.

See the example here.

#What global side effects are there?

There are global listeners to determine the user's current input type (e.g. touch), and other UX helpers.

#I can't click things inside the tooltip

To enable interactivity, set the interactive prop to true.

#My tooltip is hiding instantly after showing

If you're using a focus trigger, for example on an <input>, make sure you also set hideOnClick: false.

#Changing data-tippy-* attributes does not update the tooltip

Updating the data-tippy-* attribute on an element will currently not update the tooltip. You must use the setProps() method on a Tippy instance.

For example, let's say you want to update the theme for tooltips when changing between dark and light mode:

const instance = tippy(element, {theme: 'custom-dark'}); // When clicking the theme toggle button, you can do this: instance.setProps({theme: 'custom-light'});

It's also possible to attach a MutationObserver to the reference elements and observe mutations to attributes if need be, then call .setProps() with the new values.

#Can I use the title attribute?

Yes. The content prop can be a function that receives the reference element as an argument and returns a string or element.

tippy('button', { content(reference) { const title = reference.getAttribute('title'); reference.removeAttribute('title'); return title; }, });

The title attribute should be removed once you have its content so the browser's default tooltip isn't displayed along with the tippy.


You can create a plugin for this to generalize the behavior:

const titleAttribute = { name: 'titleAttribute', defaultValue: true, fn() { return { onCreate(instance) { if (!instance.props.titleAttribute) { return; } const title = instance.reference.getAttribute('title'); if (title) { instance.setContent(title); instance.reference.removeAttribute('title'); } }, }; }, };

Note that the plugin does not take into account dynamic titles. Be cautious of why you might need this in the first place.

#What's the difference between an addon and a plugin?

An addon is an external function that calls the tippy() constructor because it's controlling or creating many different tippy instances.

A plugin is a plain object that hooks into, and adds functionality, to a single tippy instance that has already created.


© 2021 — MIT License

Icons made by Freepik from