Open demo

CSS code

HTML
<div class="demo-row">
  <button class="sz sz-xs" type="button">Extra small</button>
  <button class="sz sz-sm" type="button">Small</button>
  <button class="sz" type="button">Default</button>
  <button class="sz sz-lg" type="button">Large</button>
  <button class="sz sz-xl" type="button">Extra large</button>
</div>
<div class="demo-row">
  <button class="sz sz-icon sz-xs" type="button" aria-label="Add"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M12 5v14M5 12h14"/></svg></button>
  <button class="sz sz-icon sz-sm" type="button" aria-label="Add"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M12 5v14M5 12h14"/></svg></button>
  <button class="sz sz-icon" type="button" aria-label="Add"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M12 5v14M5 12h14"/></svg></button>
  <button class="sz sz-icon sz-lg" type="button" aria-label="Add"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M12 5v14M5 12h14"/></svg></button>
</div>
<button class="sz sz-block" type="button">Full-width block button</button>
CSS
/* Size scale: one .sz rule reads three custom properties; each size class only overrides those three. */
.sz{--pad:13px 24px;--fs:.92rem;--r:11px;
  border:0;border-radius:var(--r);padding:var(--pad);font:inherit;font-size:var(--fs);font-weight:700;line-height:normal;
  background:#4f46e5;color:#fff;cursor:pointer;transition:background-color .18s}
.sz:hover{background:#4338ca}
.sz:focus-visible{outline:2px solid #4f46e5;outline-offset:3px}
.sz-xs{--pad:6px 12px;--fs:.76rem;--r:7px}
.sz-sm{--pad:9px 17px;--fs:.83rem;--r:9px}
.sz-lg{--pad:16px 32px;--fs:1rem;--r:13px}
.sz-xl{--pad:19px 40px;--fs:1.08rem;--r:15px}
/* square icon-only buttons: the side length follows the same scale */
.sz-icon{padding:0;width:var(--sq,44px);height:var(--sq,44px);display:grid;place-items:center}
.sz-icon svg{display:block;width:45%;height:45%;stroke:currentColor;fill:none;stroke-width:2.2}
.sz-icon.sz-xs{--sq:30px}.sz-icon.sz-sm{--sq:37px}.sz-icon.sz-lg{--sq:52px}
.sz-block{display:block;width:340px;max-width:100%}
@media (prefers-reduced-motion:reduce){.sz{transition:none}}

Bootstrap 5 code

Requires: Bootstrap 5.3.8 CSS

HTML
<div class="demo-row">
  <button class="btn sz sz-xs" type="button">Extra small</button>
  <button class="btn sz btn-sm" type="button">Small</button>
  <button class="btn sz" type="button">Default</button>
  <button class="btn sz btn-lg" type="button">Large</button>
  <button class="btn sz sz-xl" type="button">Extra large</button>
</div>
<div class="demo-row">
  <button class="btn sz sz-icon sz-xs" type="button" aria-label="Add"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M12 5v14M5 12h14"/></svg></button>
  <button class="btn sz sz-icon btn-sm" type="button" aria-label="Add"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M12 5v14M5 12h14"/></svg></button>
  <button class="btn sz sz-icon" type="button" aria-label="Add"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M12 5v14M5 12h14"/></svg></button>
  <button class="btn sz sz-icon btn-lg" type="button" aria-label="Add"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M12 5v14M5 12h14"/></svg></button>
</div>
<button class="btn sz d-block sz-block" type="button">Full-width block button</button>
CSS
/* Size scale: .btn reads --bs-btn-padding-*, --bs-btn-font-size and --bs-btn-border-radius; each size class
   (Bootstrap's own .btn-sm and .btn-lg, plus .sz-xs and .sz-xl) only overrides those. */
.sz{--bs-btn-padding-x:24px;--bs-btn-padding-y:13px;--bs-btn-font-size:.92rem;--bs-btn-border-radius:11px;
  --bs-btn-font-weight:700;--bs-btn-line-height:normal;--bs-btn-border-width:0;
  --bs-btn-color:#fff;--bs-btn-bg:#4f46e5;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#4338ca;
  --bs-btn-active-color:#fff;--bs-btn-active-bg:#4338ca;
  --bs-btn-focus-box-shadow:0 0 0 3px #f4f5f9,0 0 0 5px #4f46e5;transition:background-color .18s}
.sz.sz-xs{--bs-btn-padding-x:12px;--bs-btn-padding-y:6px;--bs-btn-font-size:.76rem;--bs-btn-border-radius:7px}
.sz.btn-sm{--bs-btn-padding-x:17px;--bs-btn-padding-y:9px;--bs-btn-font-size:.83rem;--bs-btn-border-radius:9px}
.sz.btn-lg{--bs-btn-padding-x:32px;--bs-btn-padding-y:16px;--bs-btn-font-size:1rem;--bs-btn-border-radius:13px}
.sz.sz-xl{--bs-btn-padding-x:40px;--bs-btn-padding-y:19px;--bs-btn-font-size:1.08rem;--bs-btn-border-radius:15px}
/* square icon-only buttons */
.sz.sz-icon{--bs-btn-padding-x:0;--bs-btn-padding-y:0;width:var(--sq,44px);height:var(--sq,44px);
  display:grid;place-items:center}
.sz-icon svg{width:45%;height:45%;stroke:currentColor;fill:none;stroke-width:2.2}
.sz-icon.sz-xs{--sq:30px}.sz-icon.btn-sm{--sq:37px}.sz-icon.btn-lg{--sq:52px}
.sz-block{width:340px;max-width:100%}
@media (prefers-reduced-motion:reduce){.sz{transition:none}}

Tailwind 4 code

Requires: Tailwind CSS 4

HTML
<div class="flex flex-wrap items-center justify-center gap-3.5">
  <button type="button" class="rounded-[7px] px-3 py-1.5 text-[.76rem] cursor-pointer bg-[#4f46e5] font-bold text-white transition-[background-color] duration-[180ms] hover:bg-[#4338ca] focus-visible:outline-2 focus-visible:outline-offset-[3px] focus-visible:outline-[#4f46e5] motion-reduce:transition-none">Extra small</button>
  <button type="button" class="rounded-[9px] px-[17px] py-[9px] text-[.83rem] cursor-pointer bg-[#4f46e5] font-bold text-white transition-[background-color] duration-[180ms] hover:bg-[#4338ca] focus-visible:outline-2 focus-visible:outline-offset-[3px] focus-visible:outline-[#4f46e5] motion-reduce:transition-none">Small</button>
  <button type="button" class="rounded-[11px] px-6 py-[13px] text-[.92rem] cursor-pointer bg-[#4f46e5] font-bold text-white transition-[background-color] duration-[180ms] hover:bg-[#4338ca] focus-visible:outline-2 focus-visible:outline-offset-[3px] focus-visible:outline-[#4f46e5] motion-reduce:transition-none">Default</button>
  <button type="button" class="rounded-[13px] px-8 py-4 text-[1rem] cursor-pointer bg-[#4f46e5] font-bold text-white transition-[background-color] duration-[180ms] hover:bg-[#4338ca] focus-visible:outline-2 focus-visible:outline-offset-[3px] focus-visible:outline-[#4f46e5] motion-reduce:transition-none">Large</button>
  <button type="button" class="rounded-[15px] px-10 py-[19px] text-[1.08rem] cursor-pointer bg-[#4f46e5] font-bold text-white transition-[background-color] duration-[180ms] hover:bg-[#4338ca] focus-visible:outline-2 focus-visible:outline-offset-[3px] focus-visible:outline-[#4f46e5] motion-reduce:transition-none">Extra large</button>
</div>
<div class="flex flex-wrap items-center justify-center gap-3.5">
  <button type="button" aria-label="Add" class="grid size-[30px] rounded-[7px] place-items-center cursor-pointer bg-[#4f46e5] font-bold text-white transition-[background-color] duration-[180ms] hover:bg-[#4338ca] focus-visible:outline-2 focus-visible:outline-offset-[3px] focus-visible:outline-[#4f46e5] motion-reduce:transition-none"><svg viewBox="0 0 24 24" aria-hidden="true" class="block size-[45%] fill-none stroke-current stroke-[2.2]"><path d="M12 5v14M5 12h14"/></svg></button>
  <button type="button" aria-label="Add" class="grid size-[37px] rounded-[9px] place-items-center cursor-pointer bg-[#4f46e5] font-bold text-white transition-[background-color] duration-[180ms] hover:bg-[#4338ca] focus-visible:outline-2 focus-visible:outline-offset-[3px] focus-visible:outline-[#4f46e5] motion-reduce:transition-none"><svg viewBox="0 0 24 24" aria-hidden="true" class="block size-[45%] fill-none stroke-current stroke-[2.2]"><path d="M12 5v14M5 12h14"/></svg></button>
  <button type="button" aria-label="Add" class="grid size-11 rounded-[11px] place-items-center cursor-pointer bg-[#4f46e5] font-bold text-white transition-[background-color] duration-[180ms] hover:bg-[#4338ca] focus-visible:outline-2 focus-visible:outline-offset-[3px] focus-visible:outline-[#4f46e5] motion-reduce:transition-none"><svg viewBox="0 0 24 24" aria-hidden="true" class="block size-[45%] fill-none stroke-current stroke-[2.2]"><path d="M12 5v14M5 12h14"/></svg></button>
  <button type="button" aria-label="Add" class="grid size-[52px] rounded-[13px] place-items-center cursor-pointer bg-[#4f46e5] font-bold text-white transition-[background-color] duration-[180ms] hover:bg-[#4338ca] focus-visible:outline-2 focus-visible:outline-offset-[3px] focus-visible:outline-[#4f46e5] motion-reduce:transition-none"><svg viewBox="0 0 24 24" aria-hidden="true" class="block size-[45%] fill-none stroke-current stroke-[2.2]"><path d="M12 5v14M5 12h14"/></svg></button>
</div>
<button type="button" class="block w-[340px] max-w-full rounded-[11px] px-6 py-[13px] text-[.92rem] cursor-pointer bg-[#4f46e5] font-bold text-white transition-[background-color] duration-[180ms] hover:bg-[#4338ca] focus-visible:outline-2 focus-visible:outline-offset-[3px] focus-visible:outline-[#4f46e5] motion-reduce:transition-none">Full-width block button</button>

About this set

A five-step button size scale, extra small, small, default, large and extra large, plus square icon-only buttons in four matching sizes and a block button that fills up to 340 pixels. Use extra small and small in dense tables and toolbars, default for forms, large for page-level actions and extra large for a hero. In the plain CSS version one rule draws every button from three custom properties, –pad, –fs and –r, and each size class overrides only those three, so a change to the base colour, weight or focus style reaches every size at once. The icon-only buttons reuse the same classes and add a side length through –sq, and the plus icon scales to 45 percent of the button. In the Bootstrap version the base is .btn with the –bs-btn-padding, –bs-btn-font-size and –bs-btn-border-radius variables set, Bootstrap’s own .btn-sm and .btn-lg are restyled to match, and .sz-xs and .sz-xl add the two extra steps. The Tailwind version swaps only the padding, text size and radius utilities between sizes.

What’s included

  • Five text sizes from 12 to 17 pixel labels
  • Four square icon-only sizes from 30 to 52 pixels
  • Block button that shrinks to fit narrow screens
  • Sizes change three values and nothing else
  • Bootstrap .btn-sm and .btn-lg restyled to the same scale

Accessibility

Every button is a native button element with visible text, and each icon-only button has aria-label="Add" with its SVG hidden from assistive technology. All sizes share a 2px indigo focus outline offset by 3px (a matching ring in Bootstrap). White text on #4f46e5 is 6.3:1. The background colour transition is removed under prefers-reduced-motion.

Customise it

Edit --pad, --fs and --r on .sz and on each .sz-xs to .sz-xl class, and --sq for the icon sizes. In Bootstrap edit the --bs-btn-padding-x, --bs-btn-padding-y, --bs-btn-font-size and --bs-btn-border-radius values on .sz and its size classes; in Tailwind change the px-, py-, text- and rounded- utilities.