Neo-Brutalist Button Set with Sizes and Icons

A full set of neo-brutalist buttons in one place. Three sizes, five colours including an inverted black one, a button with a trailing arrow, a square icon button and a disabled one in grey. They all share the same base: a two pixel black border, a four pixel hard shadow, a slight tilt on hover and a press that drops the button onto its shadow.

Code

// Adapted from HyperUI (https://www.hyperui.dev/components/neobrutalism/buttons)
// Copyright (c) Mark Mead. MIT License: https://we.inc/components/licenses
const ring = "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-black focus-visible:ring-offset-2";
const press = "transition-all duration-100 ease-out active:translate-x-1 active:translate-y-1 active:shadow-none motion-reduce:transition-none";
const base = `inline-flex items-center justify-center gap-2 border-2 border-black font-bold text-black shadow-[4px_4px_0_0_#000] hover:-rotate-1 motion-reduce:hover:rotate-0 ${press} ${ring}`;

const Arrow = () => (
  <svg viewBox="0 0 20 20" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true" className="h-4 w-4"><path d="M3 10h13M11 5l5 5-5 5" /></svg>
);

export default function NeoBrutalistButtonSetWithSizesAndIcons() {
  return (
    <div className="bg-white p-6 sm:p-10">
      <div className="mx-auto flex max-w-3xl flex-col gap-8">
        <div className="flex flex-wrap items-center gap-5">
          <button type="button" className={`${base} min-h-[40px] bg-white px-3 py-1.5 text-sm hover:bg-yellow-200`}>Small</button>
          <button type="button" className={`${base} min-h-[44px] bg-white px-5 py-3 hover:bg-yellow-200`}>Click here</button>
          <button type="button" className={`${base} min-h-[56px] bg-white px-7 py-4 text-lg hover:bg-yellow-200`}>Large</button>
        </div>
        <div className="flex flex-wrap items-center gap-5">
          <button type="button" className={`${base} bg-yellow-300 px-5 py-3 hover:bg-yellow-200`}>Primary</button>
          <button type="button" className={`${base} bg-pink-300 px-5 py-3 hover:bg-pink-200`}>Pink</button>
          <button type="button" className={`${base} bg-sky-300 px-5 py-3 hover:bg-sky-200`}>Sky</button>
          <button type="button" className={`${base} bg-lime-300 px-5 py-3 hover:bg-lime-200`}>Lime</button>
          <button type="button" className={`${base} border-black bg-black px-5 py-3 text-white shadow-[4px_4px_0_0_#f472b6] hover:bg-slate-800`}>Inverted</button>
        </div>
        <div className="flex flex-wrap items-center gap-5">
          <button type="button" className={`${base} bg-yellow-300 px-5 py-3 hover:bg-yellow-200`}>Continue <Arrow /></button>
          <button type="button" aria-label="Add item" className={`${base} h-11 w-11 bg-lime-300 p-0 hover:bg-lime-200`}>
            <svg viewBox="0 0 20 20" fill="none" stroke="currentColor" strokeWidth="3" strokeLinecap="round" aria-hidden="true" className="h-5 w-5"><path d="M10 4v12M4 10h12" /></svg>
          </button>
          <button type="button" disabled className="inline-flex min-h-[44px] cursor-not-allowed items-center gap-2 border-2 border-slate-500 bg-slate-100 px-5 py-3 font-bold text-slate-600 shadow-[4px_4px_0_0_#64748b]">Disabled</button>
        </div>
      </div>
    </div>
  );
}

Install with one command: npx shadcn@latest add https://we.inc/r/neo-brutalist-button-set-with-sizes-and-icons.json

When to use it

How to customize it

Accessibility

Questions

What do the three sizes change besides padding?

Small, default and large set `min-h-[40px]`, `min-h-[44px]` and `min-h-[56px]` along with `text-sm`, base and `text-lg`. The minimum heights keep every size a comfortable touch target, and the shadow stays at four pixels so the press distance does not change.

Should the disabled button use the disabled attribute?

Yes, for real buttons. The native attribute removes it from the tab order and blocks clicks. The look here is separate: grey border, grey fill and a `#64748b` shadow, so a disabled button still reads as the same family. Use `aria-disabled` only if it must stay focusable.

Why is the icon-only button square?

The plus button is `h-11 w-11` with `p-0`, so its target is 44 pixels each way, and it has `aria-label="Add item"` because an icon has no name of its own. The SVG inherits `currentColor` so it follows the text colour.

Can these styles be used on a link?

Yes. Copy the `base` string onto an `a` when the click goes to another page. The press and tilt work the same, but keep a visible label and do not use `href="#"` in production for actions that happen on the page.

Adapted from Button 1 in HyperUI, used under its open-source licence. Licences and credits

Related: Neo-Brutalist Hero with Sticker Headline and Shifting Hard Shadows, Nitro Cold Brew Tumbler Loader That Pours, Cascades and Settles Under a Cream Head, Oak Card Index Box FAQ with Tabbed Question Cards That Rise out and Stand Against the Open Lid.

More buttons or all free UI components. Start for free to have a full site built around it.

More in Buttons

We.Inc is an AI-powered website builder you can resell under your own brand. Launch a branded client dashboard, bill on Stripe Connect, and deliver AI-generated websites in minutes. White-label plans start at $99 a month for 25 client sites, with a 7-day free trial and no per-site fees.

Product

Who It's For

Features

Resources

Company

View Sitemap