Button Library · Signature
Rubber Stamp
Tilted, inky, and it slams down when clicked.
States
Default
Hover
Active
Focus
Code
sig-stamp.html
<button class="btn-sig-stamp" type="button"> <span>Approved</span> </button>
sig-stamp.css
.btn-sig-stamp {
--btn-bg: #ff5a5f;
--btn-font: inherit;
--btn-size: 15px;
--btn-px: 22px;
--btn-py: 11px;
--btn-w: auto;
--btn-h: auto;
--btn-radius: 6px;
--btn-shadow: none;
--btn-speed: 180ms;
}
.btn-sig-stamp {
position: relative;
display: inline-flex;
align-items: center;
justify-content: center;
gap: 0.5em;
box-sizing: border-box;
width: var(--btn-w);
height: var(--btn-h);
padding: var(--btn-py) var(--btn-px);
font-family: var(--btn-font);
font-size: var(--btn-size);
font-weight: 800;
line-height: 1.2;
color: var(--btn-bg);
background: transparent;
border: 3px solid currentColor;
border-radius: var(--btn-radius);
box-shadow: var(--btn-shadow);
cursor: pointer;
text-decoration: none;
white-space: nowrap;
transition: all var(--btn-speed) ease;
letter-spacing: 0.14em;
text-transform: uppercase;
transform: rotate(-4deg);
mask: radial-gradient(circle at 30% 40%, transparent 0.6px, #000 1.1px) 0 0 / 9px 7px, radial-gradient(circle at 70% 60%, transparent 0.5px, #000 1px) 0 0 / 13px 11px;
mask-composite: intersect;
}
.btn-sig-stamp:focus-visible {
outline: none;
outline-offset: 2px;
color: #101014;
background: var(--btn-bg);
}
.btn-sig-stamp:disabled {
opacity: 0.5;
pointer-events: none;
}
.btn-sig-stamp__icon {
width: 1.15em;
height: 1.15em;
flex-shrink: 0;
}
.btn-sig-stamp::before {
content: "";
position: absolute;
inset: 2px;
border: 1px solid currentColor;
border-radius: 3px;
}
.btn-sig-stamp:hover {
transform: rotate(-4deg) scale(1.05);
}
.btn-sig-stamp[data-state=stamped] {
animation: btn-stamp 340ms cubic-bezier(.2,.8,.3,1);
}
@keyframes btn-stamp {
0% { transform: rotate(-4deg) scale(1.7); opacity: 0; }
60% { transform: rotate(-4deg) scale(0.93); opacity: 1; }
100% { transform: rotate(-4deg) scale(1); }
}
@media (prefers-reduced-motion: reduce) {
.btn-sig-stamp {
animation: none !important;
transition: none !important;
}
}
sig-stamp.js
document.querySelectorAll(".btn-sig-stamp").forEach((el) => {
const land = () => {
el.removeAttribute("data-state");
void el.offsetWidth;
el.dataset.state = "stamped";
};
const clear = () => el.removeAttribute("data-state");
el.addEventListener("click", land);
el.addEventListener("animationend", clear);
return () => {
el.removeEventListener("click", land);
el.removeEventListener("animationend", clear);
};
});
sig-stamp.tsx
import { useEffect, useRef } from "react";
import type React from "react";
import "./sig-stamp.css"; // the CSS tab
function attach(el: HTMLElement) {
const land = () => {
el.removeAttribute("data-state");
void el.offsetWidth;
el.dataset.state = "stamped";
};
const clear = () => el.removeAttribute("data-state");
el.addEventListener("click", land);
el.addEventListener("animationend", clear);
return () => {
el.removeEventListener("click", land);
el.removeEventListener("animationend", clear);
};
}
export function BtnSigStamp({ children = "Approved", ...props }: React.ComponentProps<"button">) {
const ref = useRef<HTMLButtonElement>(null);
useEffect(() => attach(ref.current!), []);
return (
<button className="btn-sig-stamp" type="button" ref={ref} {...props}>
<span>{children}</span>
</button>
);
}
sig-stamp.html
<button class="btn-sig-stamp relative inline-flex items-center justify-center gap-[0.5em] [box-sizing:border-box] [padding:11px_22px] [font-family:inherit] text-[15px] font-[800] [line-height:1.2] text-[#ff5a5f] [background:transparent] [border:3px_solid_currentColor] rounded-[6px] [box-shadow:none] cursor-pointer no-underline whitespace-nowrap [transition:all_180ms_ease] [letter-spacing:0.14em] [text-transform:uppercase] [transform:rotate(-4deg)] [mask:radial-gradient(circle_at_30%_40%,_transparent_0.6px,_#000_1.1px)_0_0_/_9px_7px,_radial-gradient(circle_at_70%_60%,_transparent_0.5px,_#000_1px)_0_0_/_13px_11px] [mask-composite:intersect] focus-visible:[outline:none] focus-visible:[outline-offset:2px] focus-visible:text-[#101014] focus-visible:bg-[#ff5a5f] disabled:[opacity:0.5] disabled:[pointer-events:none] before:content-[''] before:absolute before:[inset:2px] before:[border:1px_solid_currentColor] before:rounded-[3px] hover:[transform:rotate(-4deg)_scale(1.05)] [&[data-state=stamped]]:[animation:btn-stamp_340ms_cubic-bezier(.2,.8,.3,1)] motion-reduce:[animation:none!important] motion-reduce:[transition:none!important]" type="button">
<span>Approved</span>
</button>
<!-- A class cannot hold keyframes: keep this in your CSS. -->
<style>
@keyframes btn-stamp {
0% { transform: rotate(-4deg) scale(1.7); opacity: 0; }
60% { transform: rotate(-4deg) scale(0.93); opacity: 1; }
100% { transform: rotate(-4deg) scale(1); }
}
</style>
<!-- Needs the script from the JS tab. -->