Back to CSS Buttons Receipt Paper CSS + JS
Share
HTML
<button class="btn-receipt">
  <span class="btn-receipt-perf" aria-hidden="true"></span>
  <span class="btn-receipt-stamp" aria-hidden="true">PAID</span>
  <span class="btn-receipt-row">
    <span class="btn-receipt-text">TOTAL</span>
    <span class="btn-receipt-amt" data-target="142">$0</span>
  </span>
</button>
CSS
.btn-receipt {
  position: relative;
  padding: 28px 26px 16px;
  border: none;
  background: #f4ecd8;
  color: #1a1a1a;
  font-family: ui-monospace, monospace;
  font-size: 12px; font-weight: 800;
  letter-spacing: 0.16em;
  cursor: pointer;
  filter: drop-shadow(0 4px 10px rgba(0,0,0,0.18));
  transition: transform 0.18s ease;
  overflow: hidden;
}
.btn-receipt-perf {
  position: absolute;
  top: 0; left: 0; right: 0; height: 6px;
  background-image:
    radial-gradient(circle 3px at 50% 0, transparent 99%, #f4ecd8 100%);
  background-size: 12px 6px;
  background-repeat: repeat-x;
  background-position: top;
  border-bottom: 1px dashed #8a7d5a;
  pointer-events: none;
}
.btn-receipt-stamp {
  position: absolute;
  top: 14px; left: 8px;
  font-family: ui-serif, Georgia, serif;
  font-size: 10px;
  color: #aa2a2a;
  border: 1.5px solid #aa2a2a;
  padding: 1px 5px;
  transform: rotate(-14deg);
  transform-origin: left center;
  letter-spacing: 0.14em;
  opacity: 0.55;
  pointer-events: none;
}
.btn-receipt-row {
  display: inline-flex; align-items: baseline; gap: 24px;
  padding-left: 38px;
}
.btn-receipt-text { color: #1a1a1a; }
.btn-receipt-amt {
  color: #aa2a2a; font-weight: 800;
  font-size: 18px;
  letter-spacing: 0.04em;
  min-width: 64px;
  display: inline-block;
}
.btn-receipt:hover { transform: translateY(-2px); }
JS
document.querySelectorAll('.btn-receipt').forEach(function(btn) {
  btn.addEventListener('click', function() {
    var amt = btn.querySelector('.btn-receipt-amt');
    if (!amt || amt.dataset.animating === '1') return;
    amt.dataset.animating = '1';
    var target = parseInt(amt.dataset.target, 10) || 0;
    var start = 0;
    var startTime = null;
    var duration = 700;
    function step(ts) {
      if (!startTime) startTime = ts;
      var t = Math.min((ts - startTime) / duration, 1);
      var eased = 1 - Math.pow(1 - t, 3);
      var val = Math.round(start + (target - start) * eased);
      amt.textContent = '$' + val;
      if (t < 1) requestAnimationFrame(step);
      else { setTimeout(function() { amt.textContent = '$0'; amt.dataset.animating = ''; }, 1200); }
    }
    requestAnimationFrame(step);
  });
});