---
title: FAQ
path: /v5/faq/
index: 16
---

### What syntax theme is used on this website?

It's a theme I made called
[Moonlight](https://github.com/atomiks/moonlight-vscode-theme)!

### Nothing is working

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

```html
<!DOCTYPE html>
<html>
  <head>
    <title>My page</title>
  </head>
  <body>
    <button>Text</button>

    <!-- Very end of the body -->
    <script src="https://unpkg.com/popper.js@1"></script>
    <script src="https://unpkg.com/tippy.js@5"></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:

- `position` (e.g. fixed, absolute, sticky)
- `overflow: hidden`

To fix add the following prop (recommended):

```js
tippy(targets, {
  // ...
  popperOptions: {
    positionFixed: true,
  },
});
```

Or, if the above causes issues:

```js
tippy(targets, {
  // ...
  appendTo: document.body,
});
```

⚠️ For the latter, you need to be employing focus management for accessibility.

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

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

```js
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.

#### Browserify/Grunt/Gulp

[View the following link](https://vuejs.org/v2/guide/deployment.html#With-Build-Tools).

#### Rollup

Install the
[`replace plugin`](https://www.npmjs.com/package/rollup-plugin-replace).

```js
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](../getting-started/#optional-extra-imports).

### What are those "iife", "esm" and "cjs" initialisms?

They represent JavaScript formats. You don't need to know how they work, just
which one you're using:

| Initialism |                Full Name                | Usage                                          | Tree-Shaking?              |
| ---------- | :-------------------------------------: | ---------------------------------------------- | -------------------------- |
| `iife`     | Immediately Invoked Function Expression | Used via script tags in the browser (CDN)      | No                         |
| `esm`      |            ECMAScript Module            | Used via `import` syntax in module bundlers    | Yes                        |
| `cjs`      |             CommonJS Module             | Used via `require()` syntax in module bundlers | Only in `Parcel` currently |

Using `tippy.js` via the `esm` format is the most recommended way, since you get
the benefits of tree-shaking in all bundlers.

### 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](../methods/#setprops) on a Tippy
instance.

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

```js
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.

```js
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.

#### Plugin

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

```js
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 already created.
