---
title: Misc
path: /v5/misc/
index: 15
---

import EventDelegation from '../../components/examples/EventDelegation';
import TriggerTarget from '../../components/examples/TriggerTarget';
import mouseRest from '../../components/examples/mouseRestPlugin';

### Custom position

Use a Popper ReferenceObject:

```js
tippy(targets, {
  // popperInstance will be available onCreate
  lazy: false,
  onCreate(instance) {
    instance.popperInstance.reference = {
      clientWidth: 0,
      clientHeight: 0,
      getBoundingClientRect() {
        return {
          // ...
        };
      },
    };
  },
});
```

### Scrollable containers

While scrolling the container, the reference element can leave the boundary
view, meaning the tippy will appear to be attached to nothing. You can hide the
tippy to prevent it from being seen:

```css
.tippy-tooltip[data-out-of-boundaries] {
  opacity: 0;
}
```

This may not be ideal in all cases. You can include this attribute only on a
theme if necessary.

Other cases:

- If you want the tippy to be clipped by the scrolling container, use the props
  `appendTo: 'parent'` and `boundary: scrollingContainer`.
- Consider the prop `flipOnUpdate: true` if you want the tippy to flip to best
  fit in view while the container is being scrolled.

### Different trigger target

You may want the tippy to appear at a different location from its trigger (event
listeners) target. For example:

<Demo>
  <TriggerTarget />
</Demo>

For this, you can utilize the `triggerTarget` prop:

```js
const innerOrangeSpanElement = document.querySelector('span');
const outerDivElement = document.querySelector('div');

tippy(innerOrangeSpanElement, {
  triggerTarget: outerDivElement,
});
```

### Touch devices

Tippy provides first-class support for touch devices. Tooltips can be tricky to
get right on touch devices because of the nature of touch input.

#### Buttons

A tooltip on a button is generally used to convey information before the user
decides to click on it. On touch devices, this isn't possible because a tap is
required to show the tooltip, which will fire a click event.

On iOS, a tap will show the tooltip but click events won't fire until a second
tap. This allows the user to see the tooltip before deciding to click the
button. On Android, clicking the button will show the tooltip and also fire a
click event.

Depending on your use case, one of these will be preferred, so user agent
checking may be needed.

If neither behavior is preferred, consider using the `touchHold` prop which
allows the user to see the tooltip while pressing and holding the button, but
won't fire a click event unless the click appears to be intentional.

##### Setup

```js
const button = document.querySelector('button');
const isIOS = /iPhone|iPad|iPod/.test(navigator.platform);
```

##### A: Make iOS behave like Android (single tap to click)

```js
button.addEventListener('click', () => {
  // Your logic
});

tippy(button, {
  onShow() {
    if (isIOS) {
      button.click();
    }
  },
});
```

##### B: Make Android behave like iOS (double tap to click)

Tippy has a useful static property `tippy.currentInput`. This is a mutable
object whose properties change depending on the user's current input. Currently,
it has a single property called `isTouch`, which is a boolean flag determining
if the user is currently using touch input. This is a dynamic value because of
hybrid devices which can use a mix of mouse and touch input.

```js
function emulateIOS(listener) {
  let clicks = 0;

  return function () {
    clicks++;

    if (clicks === 2 || isIOS || !tippy.currentInput.isTouch) {
      clicks = 0;
      listener.apply(this, arguments);
    }
  };
}

const instance = tippy(button);
const onClick = emulateIOS(() => {
  // Your logic
});

button.addEventListener('click', onClick);
```

#### Hold & long press

```js
// Will only show the tippy while the user is pressing the screen (not a tap)
tippy(button, {
  touch: 'hold',
});

// Will only show the tippy on a "long press" hold
tippy(button, {
  touch: ['hold', 500], // 500ms delay
});
```
