Press
Press calls the chosen method when the touch event on the element lasts longer than 250 milliseconds.

Hold the button to remove the mask from the image
<div
class="relative mb-3 max-w-xl overflow-hidden bg-cover bg-[50%] bg-no-repeat">
<img
src="https://tecdn.b-cdn.net/img/new/standard/city/053.webp"
class="h-[auto]" />
<div
id="remove-bg"
class="absolute bottom-0 left-0 right-0 top-0 h-full w-full overflow-hidden bg-fixed"
style="background-color: hsla(0, 0%, 0%, 0.6)">
<div class="flex h-full items-center justify-center">
<p id="press-text" class="text-white opacity-100">
Hold the button to remove the mask from the image
</p>
</div>
</div>
</div>
<button
id="btn-press"
data-te-touch-init
data-te-event="press"
data-te-time="2000"
data-te-ripple-init
data-te-ripple-color="light"
type="button"
class="inline-block select-none rounded bg-primary px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white shadow-[0_4px_9px_-4px_#3b71ca] transition duration-150 ease-in-out hover:bg-primary-600 hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:bg-primary-600 focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:outline-none focus:ring-0 active:bg-primary-700 active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] dark:shadow-[0_4px_9px_-4px_rgba(59,113,202,0.5)] dark:hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)]">
Tap & hold to show image
</button>
// Initialization for ES Users
import {
Ripple,
Touch,
initTE,
} from "tw-elements";
initTE({ Ripple, Touch });
const btnPress = document.querySelector("#btn-press");
const removeBg = document.querySelector("#remove-bg");
const pressText = document.querySelector("#press-text");
btnPress.addEventListener("press", (e) => {
removeBg.style.backgroundColor = "rgba(0,0,0,0)";
pressText.innerText = "";
});
const btnPress = document.querySelector("#btn-press");
const removeBg = document.querySelector("#remove-bg");
const pressText = document.querySelector("#press-text");
btnPress.addEventListener("press", (e) => {
removeBg.style.backgroundColor = "rgba(0,0,0,0)";
pressText.innerText = "";
});
Hey there 👋 we want to make TW elements a community-driven project. It's open source and free, and we would like it to stay that way. If you enjoy it, help the project grow by sharing it with your peers. Every share counts, thank you!
Press duration
Touch event press with custom duration.

Hold the button to remove the mask from the image with 5 seconds
<div
class="relative mb-3 max-w-xl overflow-hidden bg-cover bg-[50%] bg-no-repeat">
<img
src="https://tecdn.b-cdn.net/img/new/standard/city/053.webp"
class="h-[auto]" />
<div
id="bg-press-duration"
class="absolute bottom-0 left-0 right-0 top-0 h-full w-full overflow-hidden bg-fixed"
style="background-color: hsla(0, 0%, 0%, 0.6)">
<div class="flex h-full items-center justify-center">
<p id="press-duration-text" class="text-white opacity-100">
Hold the button to remove the mask from the image with 5 seconds
</p>
</div>
</div>
</div>
<button
id="btn-press-duration"
data-te-touch-init
data-te-event="press"
data-te-time="5000"
data-te-ripple-init
data-te-ripple-color="light"
type="button"
class="inline-block select-none rounded bg-primary px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white shadow-[0_4px_9px_-4px_#3b71ca] transition duration-150 ease-in-out hover:bg-primary-600 hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:bg-primary-600 focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:outline-none focus:ring-0 active:bg-primary-700 active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] dark:shadow-[0_4px_9px_-4px_rgba(59,113,202,0.5)] dark:hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)]">
Tap & hold to show image
</button>
// Initialization for ES Users
import {
Ripple,
Touch,
initTE,
} from "tw-elements";
initTE({ Ripple, Touch });
const btnPressDuration = document.querySelector("#btn-press-duration");
const bgPressDuration = document.querySelector("#bg-press-duration");
const pressDurationText = document.querySelector("#press-duration-text");
btnPressDuration.addEventListener("press", () => {
bgPressDuration.style.backgroundColor = "rgba(0,0,0,0)";
pressDurationText.innerText = "";
});
const btnPressDuration = document.querySelector("#btn-press-duration");
const bgPressDuration = document.querySelector("#bg-press-duration");
const pressDurationText = document.querySelector("#press-duration-text");
btnPressDuration.addEventListener("press", () => {
bgPressDuration.style.backgroundColor = "rgba(0,0,0,0)";
pressDurationText.innerText = "";
});
Tap
The callback on tap event is called with an object containing origin field - the x and y cooridinates of the user's touch.

Tap button to change a color
<div
class="relative mb-3 max-w-xl overflow-hidden bg-cover bg-[50%] bg-no-repeat">
<img
src="https://tecdn.b-cdn.net/img/new/standard/city/053.webp"
class="h-[auto]" />
<div
id="bg-tap"
class="absolute bottom-0 left-0 right-0 top-0 h-full w-full overflow-hidden bg-fixed"
style="background-color: hsla(0, 0%, 0%, 0.6)">
<div class="flex h-full items-center justify-center">
<p class="text-white opacity-100">Tap button to change a color</p>
</div>
</div>
</div>
<button
id="btn-tap"
data-te-touch-init
data-te-event="tap"
data-te-ripple-init
data-te-ripple-color="light"
type="button"
class="inline-block select-none rounded bg-primary px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white shadow-[0_4px_9px_-4px_#3b71ca] transition duration-150 ease-in-out hover:bg-primary-600 hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:bg-primary-600 focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:outline-none focus:ring-0 active:bg-primary-700 active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] dark:shadow-[0_4px_9px_-4px_rgba(59,113,202,0.5)] dark:hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)]">
Tap to change color
</button>
// Initialization for ES Users
import {
Ripple,
Touch,
initTE,
} from "tw-elements";
initTE({ Ripple, Touch });
const btnTap = document.querySelector("#btn-tap");
const bgTap = document.querySelector("#bg-tap");
const colorGen = () => {
const randomNum = () => {
return Math.floor(Math.random() * 255) + 1;
};
return `rgba(${randomNum()},${randomNum()},${randomNum()},.4)`;
};
btnTap.addEventListener("tap", (e) => {
bgTap.style.backgroundColor = colorGen();
});
const btnTap = document.querySelector("#btn-tap");
const bgTap = document.querySelector("#bg-tap");
const colorGen = () => {
const randomNum = () => {
return Math.floor(Math.random() * 255) + 1;
};
return `rgba(${randomNum()},${randomNum()},${randomNum()},.4)`;
};
btnTap.addEventListener("tap", (e) => {
bgTap.style.backgroundColor = colorGen();
});
Double Tap
Set default taps to touch event.

Change background color with 2 taps
<div
class="relative mb-3 max-w-xl overflow-hidden bg-cover bg-[50%] bg-no-repeat">
<img
src="https://tecdn.b-cdn.net/img/new/standard/city/053.webp"
class="h-[auto]" />
<div
id="bg-double-tap"
class="absolute bottom-0 left-0 right-0 top-0 h-full w-full overflow-hidden bg-fixed"
style="background-color: hsla(0, 0%, 0%, 0.6)">
<div class="flex h-full items-center justify-center">
<p class="text-white opacity-100">
Change background color with 2 taps
</p>
</div>
</div>
</div>
<button
id="btn-double-tap"
data-te-touch-init
data-te-event="tap"
data-te-taps="2"
data-te-ripple-init
data-te-ripple-color="light"
type="button"
class="inline-block select-none rounded bg-primary px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white shadow-[0_4px_9px_-4px_#3b71ca] transition duration-150 ease-in-out hover:bg-primary-600 hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:bg-primary-600 focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:outline-none focus:ring-0 active:bg-primary-700 active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] dark:shadow-[0_4px_9px_-4px_rgba(59,113,202,0.5)] dark:hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)]">
Tap button twice
</button>
// Initialization for ES Users
import {
Ripple,
Touch,
initTE,
} from "tw-elements";
initTE({ Ripple, Touch });
const btnDoubleTap = document.querySelector("#btn-double-tap");
const doubleTapBg = document.querySelector("#bg-double-tap");
const colorGen = () => {
const randomNum = () => {
return Math.floor(Math.random() * 255) + 1;
};
return `rgba(${randomNum()},${randomNum()},${randomNum()},.4)`;
};
btnDoubleTap.addEventListener("tap", (e) => {
doubleTapBg.style.backgroundColor = colorGen();
});
const btnDoubleTap = document.querySelector("#btn-double-tap");
const doubleTapBg = document.querySelector("#bg-double-tap");
const colorGen = () => {
const randomNum = () => {
return Math.floor(Math.random() * 255) + 1;
};
return `rgba(${randomNum()},${randomNum()},${randomNum()},.4)`;
};
btnDoubleTap.addEventListener("tap", (e) => {
doubleTapBg.style.backgroundColor = colorGen();
});
Pan
The pan event is useful for dragging elements - every time the user moves a finger on the element to which the directive is attached to, the given method is being called with an argument consisting of two keys: x and y (the values corresponds to the horizontal and vertical translation).

<div
id="pan"
class="relative mb-3 max-w-xl overflow-hidden bg-cover bg-[50%] bg-no-repeat">
<img
id="img-pan"
data-te-touch-init
data-te-event="pan"
src="https://tecdn.b-cdn.net/img/new/standard/city/053.webp"
class="h-[auto]" />
</div>
// Initialization for ES Users
import {
Touch,
initTE,
} from "tw-elements";
initTE({ Touch });
const panEl = document.querySelector("#pan");
const imgPan = document.querySelector("#img-pan");
let moveElement = {
x: null,
y: null,
};
panEl.addEventListener("pan", (e) => {
moveElement = {
x: moveElement.x + e.x,
y: moveElement.y + e.y,
};
imgPan.style.transform = `translate(${moveElement.x}px, ${moveElement.y}px)`;
});
const panEl = document.querySelector("#pan");
const imgPan = document.querySelector("#img-pan");
let moveElement = {
x: null,
y: null,
};
panEl.addEventListener("pan", (e) => {
moveElement = {
x: moveElement.x + e.x,
y: moveElement.y + e.y,
};
imgPan.style.transform = `translate(${moveElement.x}px, ${moveElement.y}px)`;
});
Pan Left
Pan with only left direction.

<div
id="pan-left"
class="relative mb-3 max-w-xl overflow-hidden bg-cover bg-[50%] bg-no-repeat">
<img
id="img-pan-left"
data-te-touch-init
data-te-event="pan"
data-te-direction="left"
src="https://tecdn.b-cdn.net/img/new/standard/city/053.webp"
class="h-[auto]" />
</div>
// Initialization for ES Users
import {
Touch,
initTE,
} from "tw-elements";
initTE({ Touch });
const panLeftEl = document.querySelector("#pan-left");
const imgPanLeft = document.querySelector("#img-pan-left");
let moveElementLeft = {
x: null,
};
panLeftEl.addEventListener("panleft", (e) => {
moveElementLeft = {
x: moveElementLeft.x + e.x,
};
imgPanLeft.style.transform = `translate(${moveElementLeft.x}px, 0px)`;
});
const panLeftEl = document.querySelector("#pan-left");
const imgPanLeft = document.querySelector("#img-pan-left");
let moveElementLeft = {
x: null,
};
panLeftEl.addEventListener("panleft", (e) => {
moveElementLeft = {
x: moveElementLeft.x + e.x,
};
imgPanLeft.style.transform = `translate(${moveElementLeft.x}px, 0px)`;
});
Pan Right
Pan with only right direction.

<div
id="pan-right"
class="relative mb-3 max-w-xl overflow-hidden bg-cover bg-[50%] bg-no-repeat">
<img
id="img-pan-right"
data-te-touch-init
data-te-event="pan"
data-te-direction="right"
src="https://tecdn.b-cdn.net/img/new/standard/city/053.webp"
class="h-[auto]" />
</div>
// Initialization for ES Users
import {
Touch,
initTE,
} from "tw-elements";
initTE({ Touch });
const panRightEl = document.querySelector("#pan-right");
const imgPanRight = document.querySelector("#img-pan-right");
let moveElementRight = {
x: null,
};
panRightEl.addEventListener("panright", (e) => {
moveElementRight = {
x: moveElementRight.x + e.x,
};
imgPanRight.style.transform = `translate(${moveElementRight.x}px, 0px)`;
});
const panRightEl = document.querySelector("#pan-right");
const imgPanRight = document.querySelector("#img-pan-right");
let moveElementRight = {
x: null,
};
panRightEl.addEventListener("panright", (e) => {
moveElementRight = {
x: moveElementRight.x + e.x,
};
imgPanRight.style.transform = `translate(${moveElementRight.x}px, 0px)`;
});
Pan Up/Down
Pan with only up/down direction.

<div
id="pan-up-down"
class="relative mb-3 max-w-xl overflow-hidden bg-cover bg-[50%] bg-no-repeat">
<img
id="img-pan-up-down"
src="https://tecdn.b-cdn.net/img/new/standard/city/053.webp"
class="h-[auto]" />
</div>
// Initialization for ES Users
import { Touch } from "tw-elements";
const panUpDown = document.querySelector("#pan-up-down");
const imgPanUpDown = document.querySelector("#img-pan-up-down");
const touchDown = new Touch(panUpDown, {
event: "pan",
direction: "down",
});
const touchUp = new Touch(panUpDown, {
event: "pan",
direction: "up",
});
let moveElementUpDown = {
y: null,
};
panUpDown.addEventListener("panup", (e) => {
moveElementUpDown = {
y: moveElementUpDown.y + e.y,
};
imgPanUpDown.style.transform = `translate(0px, ${moveElementUpDown.y}px)`;
});
panUpDown.addEventListener("pandown", (e) => {
moveElementUpDown = {
y: moveElementUpDown.y + e.y,
};
imgPanUpDown.style.transform = `translate(0px, ${moveElementUpDown.y}px)`;
});
const panUpDown = document.querySelector("#pan-up-down");
const imgPanUpDown = document.querySelector("#img-pan-up-down");
const touchDown = new te.Touch(panUpDown, {
event: "pan",
direction: "down",
});
const touchUp = new te.Touch(panUpDown, {
event: "pan",
direction: "up",
});
let moveElementUpDown = {
y: null,
};
panUpDown.addEventListener("panup", (e) => {
moveElementUpDown = {
y: moveElementUpDown.y + e.y,
};
imgPanUpDown.style.transform = `translate(0px, ${moveElementUpDown.y}px)`;
});
panUpDown.addEventListener("pandown", (e) => {
moveElementUpDown = {
y: moveElementUpDown.y + e.y,
};
imgPanUpDown.style.transform = `translate(0px, ${moveElementUpDown.y}px)`;
});
Pinch
The pinch event calls the given method with an object containing two keys - ratio and origin. The first one it the ratio of the distance between user's fingers on touchend to the same distance on touchstart - it's particularly useful for scaling images. The second one, similarly as in doubleTap event, is a pair of coordinates indicating the middle point between the user's fingers.

<div
id="div-pinch"
class="relative mb-3 max-w-xl overflow-hidden bg-cover bg-[50%] bg-no-repeat">
<img
id="pinch"
data-te-touch-init
data-te-event="pinch"
src="https://tecdn.b-cdn.net/img/new/standard/city/053.webp"
class="h-[auto]" />
</div>
// Initialization for ES Users
import {
Touch,
initTE,
} from "tw-elements";
initTE({ Touch });
const pinchEl = document.querySelector("#pinch");
pinchEl.addEventListener("pinch", (e) => {
e.target.style.transform = `scale(${e.ratio})`;
e.target.style.transformOrigin = `translate(${e.origin.x}px, ${e.origin.y}px,)`;
});
const pinchEl = document.querySelector("#pinch");
pinchEl.addEventListener("pinch", (e) => {
e.target.style.transform = `scale(${e.ratio})`;
e.target.style.transformOrigin = `translate(${e.origin.x}px, ${e.origin.y}px,)`;
});
Swipe Left/Right
The swipe event comes with several modifiers (left, right, up, down) - each of them will ensure that event will fire only on swipe in that particular direction. If the directive is used without any modifier, the callback method will be called each time the swiping occurs, and the string indicating the direction will be passed as an argument.
This example shows example with left and right:

Swipe Left-Right to change a color
<div
class="relative mb-3 max-w-xl overflow-hidden bg-cover bg-[50%] bg-no-repeat">
<img
src="https://tecdn.b-cdn.net/img/new/standard/city/053.webp"
class="h-[auto]" />
<div
id="swipe-left-right"
data-te-touch-init
data-te-event="swipe"
data-te-treshold="100"
class="absolute bottom-0 left-0 right-0 top-0 h-full w-full overflow-hidden bg-fixed"
style="background-color: hsla(0, 0%, 0%, 0.6)">
<div class="flex h-full items-center justify-center">
<p class="text-white opacity-100">
Swipe Left-Right to change a color
</p>
</div>
</div>
</div>
// Initialization for ES Users
import {
Touch,
initTE,
} from "tw-elements";
initTE({ Touch });
const swipeLeftRight = document.querySelector("#swipe-left-right");
const colorGen = () => {
const randomNum = () => {
return Math.floor(Math.random() * 255) + 1;
};
return `rgba(${randomNum()},${randomNum()},${randomNum()},.4)`;
};
swipeLeftRight.addEventListener("swipeleft", (e) => {
e.target.style.backgroundColor = colorGen();
});
swipeLeftRight.addEventListener("swiperight", (e) => {
e.target.style.backgroundColor = colorGen();
});
const swipeLeftRight = document.querySelector("#swipe-left-right");
const colorGen = () => {
const randomNum = () => {
return Math.floor(Math.random() * 255) + 1;
};
return `rgba(${randomNum()},${randomNum()},${randomNum()},.4)`;
};
swipeLeftRight.addEventListener("swipeleft", (e) => {
e.target.style.backgroundColor = colorGen();
});
swipeLeftRight.addEventListener("swiperight", (e) => {
e.target.style.backgroundColor = colorGen();
});
Swipe Up/Down
This example shows example with up and down:

Swipe Up-Down to change a color
<div
class="relative mb-3 max-w-xl overflow-hidden bg-cover bg-[50%] bg-no-repeat">
<img
src="https://tecdn.b-cdn.net/img/new/standard/city/053.webp"
class="h-[auto]" />
<div
id="swipe-up-down"
data-te-touch-init
data-te-event="swipe"
data-te-treshold="120"
class="absolute bottom-0 left-0 right-0 top-0 h-full w-full overflow-hidden bg-fixed"
style="background-color: hsla(0, 0%, 0%, 0.6)">
<div class="flex h-full items-center justify-center">
<p class="text-white opacity-100">
Swipe Up-Down to change a color
</p>
</div>
</div>
</div>
// Initialization for ES Users
import {
Touch,
initTE,
} from "tw-elements";
initTE({ Touch });
const swipeUpDown = document.querySelector("#swipe-up-down");
const colorGen = () => {
const randomNum = () => {
return Math.floor(Math.random() * 255) + 1;
};
return `rgba(${randomNum()},${randomNum()},${randomNum()},.4)`;
};
swipeUpDown.addEventListener("swipeup", (e) => {
e.target.style.backgroundColor = colorGen();
});
swipeUpDown.addEventListener("swipedown", (e) => {
e.target.style.backgroundColor = colorGen();
});
const swipeUpDown = document.querySelector("#swipe-up-down");
const colorGen = () => {
const randomNum = () => {
return Math.floor(Math.random() * 255) + 1;
};
return `rgba(${randomNum()},${randomNum()},${randomNum()},.4)`;
};
swipeUpDown.addEventListener("swipeup", (e) => {
e.target.style.backgroundColor = colorGen();
});
swipeUpDown.addEventListener("swipedown", (e) => {
e.target.style.backgroundColor = colorGen();
});
Rotate
This example shows example with rotate:

<div
id="div-rotate"
class="relative mb-3 max-w-xl overflow-hidden bg-cover bg-[50%] bg-no-repeat">
<img
id="rotate"
data-te-touch-init
data-te-event="rotate"
src="https://tecdn.b-cdn.net/img/new/standard/city/053.webp"
class="h-[auto]" />
</div>
// Initialization for ES Users
import {
Touch,
initTE,
} from "tw-elements";
initTE({ Touch });
const rotate = document.querySelector("#rotate");
rotate.addEventListener("rotate", (e) => {
rotate.style.transform = `rotate(${e.currentAngle}turn)`;
});
const rotate = document.querySelector("#rotate");
rotate.addEventListener("rotate", (e) => {
rotate.style.transform = `rotate(${e.currentAngle}turn)`;
});