Themes

Tippies can have any custom styling via CSS.

Base Style

import 'tippy.js/dist/tippy.css'

Included themes

The package comes with themes for you to use:

  • light
  • light-border
  • material
  • translucent

They need to be imported separately.

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

Pass the theme name as the theme prop:

useTippy(target, {
  theme: 'light',
})

Tippy elements

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

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

  • [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:

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

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

To apply the theme:

useTippy(target, {
  theme: 'tomato',
})

Or using scoped style

<template>
  <div>
    <button
      v-tippy="{ 
         content: 'Hi!', 
         appendTo: 'parent', 
         theme: 'tomato',
         arrow: false
      }"
    >
      Hello!
    </button>
  </div>
</template>

<script>
  export default {}
</script>

<style scoped>
  * >>> .tippy-box[data-theme~='tomato'] {
    background-color: tomato;
    color: yellow;
  }
</style>
What is ~= ?

Since theme can have multiple names, it allows you to target a single theme inside the space-separated list. Visit MDN 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 placement prop and apply it to the .tippy-arrow element's ::before pseudo-element:

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

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

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

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

import { roundArrow } from 'vue-tippy'

useTippy(target, {
  arrow: roundArrow,
})

Changing the arrow size

Option 1: transform: scale()

This is the easiest technique and works for most cases:

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

Arrow border

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

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

/* 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:

import { roundArrow } from 'vue-tippy'

useTippy(target, {
  arrow: roundArrow + roundArrow,
})
/* 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.

Edit this page on GitHub Updated at Tue, Oct 15, 2024