Skip to content

Hold to Confirm

A copy-paste buttons component in pure HTML, CSS & vanilla JS. Zero dependencies, framework-agnostic, MIT-licensed.

ButtonsHTMLJavaScriptCSSany framework

Copy into your project

HTML
<button class="nuda-hold">
  <span class="nuda-hold__fill"></span>
  <span class="nuda-hold__text">Hold to delete</span>
</button>
JavaScript
const btn = document.querySelector('.nuda-hold');
let timer = null;

const start = () => {
  btn.classList.add('is-holding');
  timer = setTimeout(() => {
    btn.classList.add('is-confirmed');
    btn.dispatchEvent(new CustomEvent('confirm'));
  }, 1400);
};

const cancel = () => {
  btn.classList.remove('is-holding');
  clearTimeout(timer);
};

btn.addEventListener('pointerdown', start);
btn.addEventListener('pointerup', cancel);
btn.addEventListener('pointerleave', cancel);
CSS
.nuda-hold__fill {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 0;
  background: #ff5e7a;
  transition: width 1.4s linear, opacity 0.3s;
}

.nuda-hold.is-holding .nuda-hold__fill { width: 100%; }
.nuda-hold.is-confirmed .nuda-hold__fill { opacity: 0; }

.nuda-hold__text {
  position: relative;
  z-index: 1;
  mix-blend-mode: difference;
  color: #fafafa;
}

How to use Hold to Confirm

Paste the HTML where you need it and the CSS into a global stylesheet (or a <style> tag). Every class is prefixed nuda- so it never collides with Tailwind or your own styles. Tweak the CSS custom properties to match your design system.

Works in React, Vue, Svelte, Astro, Next.js, Nuxt, Laravel Blade, Django, Rails — or a single .html file. No npm install, no build step.

More buttons components

← Browse all NudaUI components