---
title: Themes
path: /v6/themes/
index: 6
---

Tippies can have any custom styling via CSS.

### Included themes

The package comes with themes for you to use:

- `light`
- `light-border`
- `material`
- `translucent`

They need to be
[imported separately](../getting-started/#optional-extra-imports).

```js
import 'tippy.js/themes/light.css';
```

Pass the theme name as the `theme` prop:

```js
tippy('button', {
  theme: 'light',
});
```

### Tippy elements

To learn how to create a theme, it's helpful to understand the basic structure
of a tippy element:

<!-- prettier-ignore -->
```html
<div data-tippy-root>
  <div class="tippy-box" data-placement="top">
    <div class="tippy-content">
      My content
    </div>
  </div>
</div>
```

A tippy is essentially three nested `div`s.

- `[data-tippy-root]` is the outermost node. It is what Popper uses to position
  the tippy. You don't need to apply any styles to this element.
- `tippy-box` is the actual box node.
- `tippy-content` is the content node.

Depending on the props supplied, there will exist other elements inside it:

<!-- prettier-ignore -->
```html
<div data-tippy-root>
  <div class="tippy-box" data-placement="top">
    <div class="tippy-backdrop"></div> <!-- animateFill: true -->
    <div class="tippy-arrow"></div> <!-- arrow: true -->
    <div class="tippy-content">
      My content
    </div>
  </div>
</div>
```

### Creating a theme

Themes are created by including a class on the `tippy-box` element as part of a
selector in the form `.tippy-box[data-theme~='theme']`. Let's demonstrate this
by creating our own theme called `tomato`:

```css
.tippy-box[data-theme~='tomato'] {
  background-color: tomato;
  color: yellow;
}
```

To apply the theme:

```js
tippy(targets, {
  theme: 'tomato',
});
```

<Demo>
  <Tippy theme="tomato">
    <Button>Tomato theme</Button>
  </Tippy>
</Demo>

> **What is `~=`?**
>
> Since `theme` can have multiple names, it allows you to target a single theme
> inside the space-separated list. Visit
> [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors)
> for more information.

### Styling the arrow

There are two types of arrows:

- CSS arrows (using `border-width`)
- SVG arrows (using an `<svg>` element)

#### CSS arrow

To style the default CSS arrow, target each different base placement using the
`data-placement` attribute and apply it to the `.tippy-arrow` element's
`::before` pseudo-element:

<!-- prettier-ignore -->
```css
.tippy-box[data-theme~='tomato'][data-placement^='top'] > .tippy-arrow::before {
  border-top-color: tomato;
}
.tippy-box[data-theme~='tomato'][data-placement^='bottom'] > .tippy-arrow::before {
  border-bottom-color: tomato;
}
.tippy-box[data-theme~='tomato'][data-placement^='left'] > .tippy-arrow::before {
  border-left-color: tomato;
}
.tippy-box[data-theme~='tomato'][data-placement^='right'] > .tippy-arrow::before {
  border-right-color: tomato;
}
```

#### SVG arrow

First import the `svg-arrow.css` stylesheet for SVG arrow styling:

```js
import 'tippy.js/dist/svg-arrow.css';
```

To color an SVG arrow, specify `fill` and target `.tippy-svg-arrow`:

<!-- prettier-ignore -->
```css
.tippy-box[data-theme~='tomato'] > .tippy-svg-arrow {
  fill: tomato;
}
```

The shape isn't dependent on the placement for styling, which is why it doesn't
require the CSS arrow's more verbose styles.

There is a default round arrow SVG shape exported from the package for you to
use.

#### CDN (`umd`)

```js
tippy(targets, {
  arrow: tippy.roundArrow,
});
```

#### Modules (`esm`)

```js
import {roundArrow} from 'tippy.js';

tippy(targets, {
  arrow: roundArrow,
});
```

<Demo>
  <Tippy theme="tomato">
    <Button>CSS arrow</Button>
  </Tippy>
  <Tippy theme="tomato" arrow="round">
    <Button>SVG arrow</Button>
  </Tippy>
</Demo>

### Changing the arrow size

#### Option 1: `transform: scale()`

This is the easiest technique and works for most cases:

```css
.tippy-box[data-theme~='tomato'] > .tippy-arrow::before {
  transform: scale(1.5);
}
```

#### Option 2: Pixel increase

If your tippy theme has a `border` (e.g. the included `light-border` theme),
then the `transform: scale()` technique distorts the border width of the arrow.
Instead, you will need to change the size of the arrow in pixels directly.

<Demo>
  <Tippy theme="tomato scaled-arrow">
    <Button>Scaled arrow</Button>
  </Tippy>
</Demo>

### Arrow border

There is a stylesheet to aid in adding borders to your tippies:

```js
import 'tippy.js/dist/border.css';
```

This adds color inheritance for borders when using the default CSS arrow, and
aids in creating SVG arrow borders.

#### CSS arrow

```css
/* The border of the arrow will now match the border of the box */
.tippy-box[data-theme~='tomato'] {
  background: tomato;
  border: 1px solid yellow;
}
```

#### SVG arrow

Duplicate the SVG arrow so that there are two of them, like so:

```js
tippy(targets, {
  // concatenates the two SVG strings together
  arrow: roundArrow + roundArrow,
});
```

```css
/* The border */
.tippy-box[data-theme~='tomato'] > .tippy-svg-arrow > svg:first-child {
  fill: yellow;
}

/* The fill */
.tippy-box[data-theme~='tomato'] > .tippy-svg-arrow > svg:last-child {
  fill: tomato;
}
```

### Browser DevTools

It's highly recommended you inspect a tippy element via your browser's DevTools.
An easy way to do this is to give it `hideOnClick: false` and `trigger: 'click'`
props so that it stays visible when focus is switched to the DevTools window.

The tippy element gets appended to the very end of the `<body>`, so you should
scroll down the elements panel. If `interactive: true`, then the tippy is
appended to the reference element's parentNode instead.
