GODRICH

Neobrutalism UI Kit: 9 Landing Sections, No Blur

A neobrutalism UI kit trades soft, blurred drop shadows for thick black borders and flat right-angle corners — and the shadows never blur, they only sit offset

This look keeps landing on Dribbble shots and Pinterest boards that other designers save, and a full one-page build comes first — scroll it from the top nav down to the last footer line before the nine pieces below get taken apart individually. That missing blur is the first detail worth noticing.

Open the full page

The nine pieces that page is built from sit below as their own grid, arranged in the order a first-time visitor actually meets them on the page — get their attention, look around, check the price, find a reason to trust it, feel pushed toward the button, then sign up — rather than by which pattern is trendiest. Four of the nine (hero, number badges, pricing card, and button) carry an actual gesture instead of sitting still: a rotation, a shadow that travels, a state that reacts to a click.

Auto-plays · click a tile to jump to its section · all nine in one zip

01Offset-shadow hero

A solid yellow duplicate of the headline sits behind the real text and drifts in and out of register, the way a badly aligned print run doubles up. The corner sticker badge rests at a tilt and snaps flat for a beat before tilting back again.

오프셋 텍스트섀도우배지 회전→0radius 0
<div class="relative border-[3px] border-ink bg-cream p-8 shadow-brutal">
  <span class="absolute -right-3 -top-3 border-[3px] border-ink
               bg-orange px-3 py-1 text-xs font-black text-cream">NEW</span>
  <h1 class="relative font-display text-4xl font-black leading-tight">
    <span class="absolute -left-1 -top-1 -z-10 text-yellow"
          aria-hidden="true">Nothing hidden, right from the start</span>
    Nothing hidden, right from the start
  </h1>
  <button class="mt-3 rounded-full border-[3px] border-ink bg-ink
                 px-6 py-3 text-sm font-black text-cream
                 shadow-[4px_4px_0_#ffd23f]">Start now</button>
</div>

02Stamp nav

The active menu item snaps from small past full size and back, overshooting once before it settles, the way a rubber stamp comes down and bounces. Every label keeps to a single line under width pressure — nothing wraps, nothing gets cut off.

scale 오버슈트radius 0white-space: nowrap
<nav class="flex items-center gap-4 border-[3px] border-ink bg-ink
            px-4 py-3">
  <span class="shrink-0 whitespace-nowrap font-black text-cream">SLABKIT</span>
  <div class="flex min-w-0 flex-1 gap-2 overflow-x-auto">
    <span class="shrink-0 whitespace-nowrap border-[3px] border-cream
                 bg-orange px-3 py-1.5 text-xs font-bold text-cream">Home</span>
    <span class="shrink-0 whitespace-nowrap px-3 py-1.5 text-xs
                 font-bold text-cream/70">Features</span>
  </div>
  <button class="shrink-0 whitespace-nowrap rounded-full border-[3px]
                 border-cream bg-yellow px-4 py-2 text-xs
                 font-black text-ink">Get started</button>
</nav>

03Shadow-detach cards

Each card's hard shadow stays fixed in place while the card body itself slides up and to the left, so the gap between the two visibly opens and closes. Four cards start on a stagger, so the set breathes like a wave instead of moving as one block.

그림자 고정카드만 이동radius 0
<div class="relative">
  <div class="absolute inset-0 translate-x-2 translate-y-2 bg-ink"></div>
  <div class="relative flex flex-col gap-2 border-[3px] border-ink
              bg-cream p-4">
    <span class="block h-6 w-6 bg-blue"></span>
    <p class="text-sm font-bold">Fast search</p>
  </div>
</div>

04Crooked number badges

Each square number badge rests at its own tilt, no two angles matching, and one by one straightens out for a beat before tilting back. Because every angle differs, the set never lines up all at once, which is what keeps it reading as alive instead of repeating.

회전 랜덤순차 정렬radius 0
<li class="flex items-center gap-3 border-[3px] border-ink bg-cream
           p-2 pr-5 shadow-brutal-sm">
  <span class="grid h-9 w-9 flex-none -rotate-6 place-items-center
               border-[3px] border-ink bg-blue text-xs font-black
               text-cream">01</span>
  <span class="text-sm font-bold">Quick start</span>
</li>

05Sticky-note pricing card

Only the recommended plan sits tilted, stuck on top of the tier beside it like a pasted note, while every other card stays dead level. It also breathes — a slow scale pulse while holding that tilt — so the pick reads as chosen without a comparison table doing any of the work.

rotate 고정radius 0레이어 겹침
<div class="relative -ml-2 flex-[1.1] -rotate-3 border-[3px]
            border-ink bg-yellow p-6 shadow-brutal">
  <span class="absolute -top-3 left-3 border-[3px] border-ink
               bg-blue px-3 py-1 text-xs font-black text-cream">Recommended</span>
  <p class="font-black">Pro</p>
  <p class="mt-1 text-sm text-ink/70">$9/mo</p>
</div>

06Block quote-mark testimonial

A quotation mark rendered as a solid color block, not a glyph, slides in and out inside its own narrow lane to the left of the quote text, so it never crosses into the words themselves. The avatar sits in a thick-bordered square frame instead of a circle, keeping the same square vocabulary as the rest of the card.

블록 따옴표정사각 아바타radius 0
<div class="relative flex-1 overflow-hidden border-[3px] border-ink
            bg-cream py-4 pl-8 pr-4 shadow-brutal-sm">
  <span class="absolute inset-y-0 left-0 w-6 bg-blue"></span>
  <p class="relative text-sm font-bold">"It feels like it wraps around your fingertip."</p>
  <p class="relative mt-2 text-xs text-ink/60">Oh Ha-neul · Product Designer</p>
</div>

07Marching-stripe CTA band

Hard-edged diagonal stripes cover the whole band, and only the background-position shifts, so the pattern marches forever with no visible seam. The button sits on a fully opaque fill, so its label stays legible no matter where the stripes land underneath it.

사선 스트라이프background-position 루프radius 0
<div class="relative overflow-hidden border-[3px] border-ink bg-ink
            px-10 py-12 shadow-brutal">
  <span class="absolute inset-0" aria-hidden="true"
        style="background-image:repeating-linear-gradient(45deg,
               #17141a 0 24px,#ffd23f 24px 48px)"></span>
  <h3 class="relative font-display text-3xl font-black
             text-cream">Bring your team in today</h3>
</div>

08Ruler-drawn divider footer

The thick rule between footer columns draws itself from top to bottom once, like a ruler line, then holds before retracting for the next pass. Only the top border carries any weight — every other corner in the footer stays a hard right angle.

scaleY 드로잉상단 테두리만radius 0
<footer class="flex items-stretch border-t-[6px] border-ink
               bg-cream px-4 pb-6 pt-8">
  <div class="flex-1 px-2">
    <p class="mb-2 text-xs font-black text-blue">Product</p>
    <p class="text-sm font-bold">Features</p>
  </div>
  <span class="w-[3px] flex-none bg-ink"></span>
  <div class="flex-1 px-2">
    <p class="mb-2 text-xs font-black text-ink/50">Company</p>
    <p class="text-sm font-bold">About</p>
  </div>
</footer>

09Press-into-shadow button

Press the button and its body travels exactly as far as its own shadow offset while the shadow shrinks to zero at the same instant, so it looks like it sinks into the spot its shadow used to occupy. The input's shadow pops in from nothing on focus, arriving together with the border color change instead of before it.

press 오프셋 이동radius pill(버튼만)focus 그림자 팝
<form class="flex gap-3 border-[3px] border-ink bg-cream p-6
            shadow-brutal">
  <input class="flex-1 border-[3px] border-ink bg-paper px-4 py-3
                text-sm" type="email" placeholder="Email address">
  <button class="rounded-full border-[3px] border-ink bg-blue
                 px-5 py-3 text-sm font-black text-cream">Sign up</button>
</form>

Custom tailwind.config

Two values cover every radius used across this kit — zero, or a full pill — and both hard shadows get one name each (shadow-brutal, shadow-brutal-sm) so nine section files and the one-pager never redeclare them by hand. Four colors total, three primaries plus the cream base, keep the whole kit inside one small palette.

theme: {
  extend: {
    colors: {
      cream: "#fff7e6",
      ink: "#17141a",
      blue: "#2f6df6",
      yellow: "#ffd23f",
      orange: "#ff4d1f",
    },
    boxShadow: {
      brutal: "8px 8px 0 #17141a",
      "brutal-sm": "4px 4px 0 #17141a",
    },
  },
},

Vibe-coding prompt

Carry that config into a fresh project, then give Claude Code or Cursor a handful of constraints instead of a full design brief — something close to what's below does the job, and the version actually typed into the zip's own prompt.md goes further than this excerpt.

Every card, nav bar, button, and input gets border-radius: 0 — no exceptions.
The one exception is anything actually pressable (a real button element),
which stays a full pill instead.
Borders are always 3px or thicker, one ink color, no border gradients.
box-shadow never gets a blur radius — offset and color only, third value stays 0.
To make one card stand out from its neighbors, reach for rotation
(around -3deg) before reaching for color or size.

Handing an agent that exact instruction and letting it rebuild page/index.html on its own produced the screenshot below, captured at a full 1280px-wide viewport.

result

Where it breaks (the trap)

320px was where things fell apart first. The number-badge list had its badge size and gaps set close to literal pixel values, and at a narrow viewport the list's actual height reached 232px against a 200px ceiling — 32px over, confirmed by rendering the page and reading the container's own scrollHeight back. Swapping the badge size and the gaps for a clamp() with a lower floor brought the height back under 200px.

The second trap showed up in the React port. The footer component has to return a divider and a column side by side, and writing import { Fragment } from "react" threw a "no exported member" error under this project's type declarations. import React from "react" followed by React.Fragment works under every configuration this project has hit so far, so that's the safer default going forward.

The marching stripes only avoid a visible seam if background-position shifts by exactly one pattern cycle — twice the stripe width — on every loop; any shorter or longer distance and the stripes visibly jump each time the animation repeats. All three fixes already sit inside the zip that the password sfjr6qe2 unlocks.

Turning on reduced motion doesn't touch these nine demos the same way twice: the duplicated headline, the nav stamp, and the sliding cards all freeze outright, while the recommended pricing card instead follows the split that MDN's prefers-reduced-motion documentation recommends — it keeps the tilt, since that carries information about which plan is picked, and cancels only the breathing scale, since that part is pure decoration.

Accessibility

yellow (#ffd23f) only ever fills a background block here and never sits directly under small text — pale text on bright yellow loses contrast fast, so every label instead sits on ink or cream, whichever the background actually separates from. Every box-shadow declaration in this kit follows MDN's box-shadow documentation and sets offset and color only, holding the blur radius at zero — the shadow-detach cards in section 03 skip box-shadow altogether and paint that same hard edge as a separate solid-color block instead, but either way the edge stays crisp for low-vision readers instead of dissolving into a soft halo. The nav's brand mark and its CTA button both carry shrink-0 whitespace-nowrap, and the link group in the middle carries min-w-0, so nothing clips or wraps mid-word as the viewport narrows.

The rest of this site's trend write-ups are filed under design trends, and the about page covers what the whole project is for.

FAQ

How is neobrutalism different from glassmorphism or neumorphism?

Glassmorphism blurs a translucent glass panel over whatever sits behind it, and neumorphism keeps a card almost the exact color of its background and carves depth out of a soft double shadow. Neobrutalism goes the other way and leaves the borders thick and the color blocks flat and unblurred, which makes it the highest-contrast of the three and, for that reason, often the easiest one to keep accessible.

Is it ever okay to add a little blur to the shadow?

Adding any blur at all softens the exact signal this style depends on. Every box-shadow here keeps its third value — the blur radius — locked at zero and changes only offset and color, and even the card in section 03, which draws its shadow as a separate solid-color block instead of a real box-shadow, keeps that same hard, unblurred edge.

Does neobrutalism hold up in dark mode?

It does, as long as the background flips to ink while the cards keep cream or one of the primary color blocks. If the shadow color also gets lighter along with the background, it stops reading as separate from the border, so the safest move is leaving the shadow on ink (or something darker still) even after the rest of the palette flips.

Enter the archive password

The password is inside this article. You will find it as you read.