28 Tailwind Hamburger Menus
27 / 28

All 28 in 28 Tailwind Hamburger Menus

  1. 01Tailwind Hamburger Menu with Clip-Path Circle Expansion
  2. 02Tailwind Keyboard Navigable Hamburger Menu with ARIA Attributes
  3. 03Tailwind Animated 3-Line to X Hamburger Icon Toggle
  4. 04Tailwind Slide-In Off-Canvas Drawer with Dimmed Backdrop Overlay
  5. 05Pure Tailwind Checkbox Hack Hamburger Navigation (No JavaScript)
  6. 06Tailwind Responsive Hamburger Menu with Integrated Search Bar & Social Links
  7. 07Tailwind Glassmorphism Backdrop Blur Hamburger Navigation
  8. 08Tailwind Push Page Navigation Menu (Off-Canvas Content Shift)
  9. 09Pure Tailwind Hamburger Menu Without JavaScript
  10. 10Tailwind Hamburger Menu Morphing to Close Icon Animation
  11. 11Tailwind Full Screen Mobile Navigation Overlay
  12. 12Tailwind Slide Out Sidebar Navigation / Off Canvas Menu
  13. 13Tailwind Responsive Navbar Mobile Hamburger Toggle Breakpoints
  14. 14Tailwind Minimalist Floating Hamburger Button
  15. 15Tailwind CSS Responsive Hamburger Menu Component
  16. 16Tailwind Rebuild of the Bootstrap 5 Navbar Hamburger Toggle
  17. 17Tailwind WCAG Accessible Hamburger Menu Example
  18. 18Pure Tailwind Dropdown Slide Down Mobile Hamburger Menu
  19. 19Simple 3-Line Tailwind Hamburger Icon Hover Effect
  20. 20Tailwind Full Screen Blur Overlay Hamburger Menu
  21. 21Tailwind Mobile Bottom Navigation Bar with Floating Hamburger Toggle
  22. 22Pure Tailwind Multi-Level Accordion Hamburger Dropdown Menu
  23. 23Flexbox Navbar Right-Aligned Tailwind Hamburger Icon
  24. 24Radial Ripple Expand Tailwind Hamburger Menu
  25. 25Sticky Tailwind Navbar Shrinking Hamburger Icon on Scroll
  26. 26Neumorphic Tailwind Hamburger Toggle Button
  27. 27Brutalist Design Bordered Tailwind Hamburger Menu
  28. 28Tailwind 3D Flip Canvas Mobile Hamburger Navigation
Pure TailwindMIT licensed

Brutalist Design Bordered Tailwind Hamburger Menu

Neo-brutalism with its rules intact: 3px black borders on everything, hard offset shadows that do not blur, one shrieking yellow, uppercase mono type — and motion that CUTS instead of eases, because in this dialect a transition curve is a lie. The press is the port's neatest line: the plate travels exactly its shadow's offset and lands flat, which is two utilities sitting next to each other.

Live Demo
Plain CSSTailwind v4
Try it

Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time

Untitled UI React · Affiliate link

Get Untitled UI Pro

The code

<section class="thb-27 w-full min-h-svh grid justify-center content-start bg-thb27-paper font-thb27-mono text-thb27-ink px-5 py-9" aria-label="Brutalist bordered menu demo">
  <div class="group relative flex flex-col w-[min(400px,88vw)] h-140 overflow-hidden border-[3px] border-thb27-ink bg-thb27-paper shadow-[8px_8px_0_var(--color-thb27-ink)] [background-image:radial-gradient(oklch(0.18_0.01_90/0.14)_1.2px,transparent_1.3px)] [background-size:18px_18px]">
    <input type="checkbox" id="thb27-t" class="peer absolute w-px h-px overflow-hidden whitespace-nowrap [clip-path:inset(50%)]">
    <header class="relative z-2 flex items-center justify-between p-3.5 border-b-[3px] border-thb27-ink bg-thb27-paper">
      <span class="text-base font-bold tracking-[0.04em]">RAW&mdash;GOODS<i class="not-italic align-super text-[10px]" aria-hidden="true">&reg;</i></span>
      <label for="thb27-t" class="flex items-center gap-2.5 min-h-11.5 px-3.5 border-[3px] border-thb27-ink bg-thb27-acc cursor-pointer select-none shadow-[6px_6px_0_var(--color-thb27-ink)] transition-[translate,box-shadow,background] duration-[60ms] ease-linear hover:bg-thb27-acc2 peer-focus-visible:outline-3 peer-focus-visible:outline-thb27-ink peer-focus-visible:outline-offset-3 group-has-checked:translate-x-1.5 group-has-checked:translate-y-1.5 group-has-checked:shadow-[0_0_0_var(--color-thb27-ink)]">
        <span class="relative block w-5 h-3.5" aria-hidden="true">
          <i class="absolute left-0 top-0 w-5 h-[3px] bg-thb27-ink transition-[translate,rotate] duration-[60ms] ease-linear group-has-checked:translate-y-[5.5px] group-has-checked:rotate-45"></i>
          <i class="absolute left-0 top-[5.5px] w-5 h-[3px] bg-thb27-ink transition-[opacity] duration-[60ms] ease-linear group-has-checked:opacity-0"></i>
          <i class="absolute left-0 top-[11px] w-5 h-[3px] bg-thb27-ink transition-[translate,rotate] duration-[60ms] ease-linear group-has-checked:-translate-y-[5.5px] group-has-checked:-rotate-45"></i>
        </span>
        <span class="text-xs font-bold tracking-[0.08em] group-has-checked:hidden" aria-hidden="true">MENU</span>
        <span class="hidden text-xs font-bold tracking-[0.08em] group-has-checked:block" aria-hidden="true">CLOSE</span>
      </label>
    </header>
    <nav aria-label="Site" class="absolute inset-x-0 top-[79px] bottom-10 z-1 hidden flex-col bg-thb27-paper border-b-[3px] border-thb27-ink group-has-checked:flex">
      <div class="border-b-[3px] border-thb27-ink"><a href="#shop" class="group/r flex items-center gap-3.5 min-h-16 px-4.5 text-[15px] font-bold tracking-[0.06em] text-thb27-ink no-underline hover:bg-thb27-ink hover:text-thb27-paper focus-visible:bg-thb27-ink focus-visible:text-thb27-paper focus-visible:outline-3 focus-visible:outline-thb27-acc focus-visible:-outline-offset-6"><b class="px-1.5 py-0.5 border-2 border-thb27-ink text-[11px] group-hover/r:border-thb27-paper group-focus-visible/r:border-thb27-paper">01</b>SHOP ALL<span class="ml-auto text-lg" aria-hidden="true">&rarr;</span></a></div>
      <div class="border-b-[3px] border-thb27-ink"><a href="#drops" class="group/r flex items-center gap-3.5 min-h-16 px-4.5 text-[15px] font-bold tracking-[0.06em] text-thb27-ink no-underline hover:bg-thb27-ink hover:text-thb27-paper focus-visible:bg-thb27-ink focus-visible:text-thb27-paper focus-visible:outline-3 focus-visible:outline-thb27-acc focus-visible:-outline-offset-6"><b class="px-1.5 py-0.5 border-2 border-thb27-ink text-[11px] group-hover/r:border-thb27-paper group-focus-visible/r:border-thb27-paper">02</b>DROPS<span class="ml-auto text-lg" aria-hidden="true">&rarr;</span></a></div>
      <div class="border-b-[3px] border-thb27-ink"><a href="#manifesto" class="group/r flex items-center gap-3.5 min-h-16 px-4.5 text-[15px] font-bold tracking-[0.06em] text-thb27-ink no-underline hover:bg-thb27-ink hover:text-thb27-paper focus-visible:bg-thb27-ink focus-visible:text-thb27-paper focus-visible:outline-3 focus-visible:outline-thb27-acc focus-visible:-outline-offset-6"><b class="px-1.5 py-0.5 border-2 border-thb27-ink text-[11px] group-hover/r:border-thb27-paper group-focus-visible/r:border-thb27-paper">03</b>MANIFESTO<span class="ml-auto text-lg" aria-hidden="true">&rarr;</span></a></div>
      <div class="border-b-[3px] border-thb27-ink"><a href="#faq" class="group/r flex items-center gap-3.5 min-h-16 px-4.5 text-[15px] font-bold tracking-[0.06em] text-thb27-ink no-underline hover:bg-thb27-ink hover:text-thb27-paper focus-visible:bg-thb27-ink focus-visible:text-thb27-paper focus-visible:outline-3 focus-visible:outline-thb27-acc focus-visible:-outline-offset-6"><b class="px-1.5 py-0.5 border-2 border-thb27-ink text-[11px] group-hover/r:border-thb27-paper group-focus-visible/r:border-thb27-paper">04</b>FAQ<span class="ml-auto text-lg" aria-hidden="true">&rarr;</span></a></div>
    </nav>
    <div class="flex-1 grid content-start gap-4.5 p-5.5" aria-hidden="true">
      <div class="w-max -rotate-1.5 px-4 py-3 border-[3px] border-thb27-ink bg-thb27-acc text-xs font-bold leading-[1.7] tracking-[0.06em] shadow-[6px_6px_0_var(--color-thb27-ink)]">EST. 2026<br>NO COOKIES<br>NO TRACKING</div>
      <div class="h-37.5 border-[3px] border-thb27-ink [background:repeating-linear-gradient(-45deg,var(--color-thb27-paper)_0_12px,oklch(0.18_0.01_90/0.12)_12px_24px)]"></div>
    </div>
    <div class="mt-auto overflow-hidden py-2.25 border-t-[3px] border-thb27-ink bg-thb27-ink text-thb27-paper" aria-hidden="true">
      <div class="flex w-max animate-thb27-tape motion-reduce:animate-none">
        <span class="whitespace-nowrap text-[11.5px] font-bold tracking-[0.14em]">FREE SHIPPING OVER $80 &#9733; PRESS THE PLATE &#9733; EVERYTHING HAS A BORDER &#9733;&nbsp;</span>
        <span class="whitespace-nowrap text-[11.5px] font-bold tracking-[0.14em]">FREE SHIPPING OVER $80 &#9733; PRESS THE PLATE &#9733; EVERYTHING HAS A BORDER &#9733;&nbsp;</span>
      </div>
    </div>
  </div>
</section>
@import "tailwindcss";

@theme {
  --color-thb27-paper: #f7f4e9;
  --color-thb27-paper: oklch(0.96 0.01 95);
  --color-thb27-ink: #1f1c14;
  --color-thb27-ink: oklch(0.18 0.01 90);
  --color-thb27-acc: #f2d43c;
  --color-thb27-acc: oklch(0.86 0.17 95);
  --color-thb27-acc2: #ffe23f;
  --color-thb27-acc2: oklch(0.9 0.19 95);
  --font-thb27-mono: 'JetBrains Mono', ui-monospace, 'Cascadia Mono', Menlo, monospace;
  --animate-thb27-tape: thb27-tape 14s linear infinite;
}
/* Keyframes are a rule, not a value — the @theme --animate-* entry only names this. */

@keyframes thb27-tape {
  to {
    translate: -50% 0;
  }
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's
   w-full min-h-svh. It scopes the demo, and it holds the stage at full height in the
   moment before the browser build has compiled its utilities. */

.thb-27 {
  width: 100%;
  min-height: 100svh;
}

Setup — do this once per project

Skip this if your project already runs Tailwind v4.

1Load Tailwind
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>

Compiles in the browser — perfect for a CodePen or a quick test, not for production.

2Add the stylesheetRequiredthe @theme block is what makes the custom utilities exist
@import "tailwindcss";

@theme {
  --color-thb27-paper: #f7f4e9;
  --color-thb27-paper: oklch(0.96 0.01 95);
  --color-thb27-ink: #1f1c14;
  --color-thb27-ink: oklch(0.18 0.01 90);
  --color-thb27-acc: #f2d43c;
  --color-thb27-acc: oklch(0.86 0.17 95);
  --color-thb27-acc2: #ffe23f;
  --color-thb27-acc2: oklch(0.9 0.19 95);
  --font-thb27-mono: 'JetBrains Mono', ui-monospace, 'Cascadia Mono', Menlo, monospace;
  --animate-thb27-tape: thb27-tape 14s linear infinite;
}
/* Keyframes are a rule, not a value — the @theme --animate-* entry only names this. */

@keyframes thb27-tape {
  to {
    translate: -50% 0;
  }
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's
   w-full min-h-svh. It scopes the demo, and it holds the stage at full height in the
   moment before the browser build has compiled its utilities. */

.thb-27 {
  width: 100%;
  min-height: 100svh;
}
3Fonts used by this demooptional — skip if you have your own type stack
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700;800&display=swap">

What changed in the port

Which parts became utilities, which stayed CSS, and why.

  • The press is the port's best moment: the 6px travel and the 6px shadow it lands on sit one class list apart (translate-x-1.5 translate-y-1.5 next to shadow-[0_0_0_…]), where the CSS version keeps them in two rules that must be kept equal by hand.
  • :checked ~ header .plate and its six relatives become group-has-checked: utilities, including the MENU/CLOSE word swap as a hidden/block pair.
  • duration-[60ms] ease-linear is now stated on each element, so the style's thesis (cuts, not curves) is legible in the markup rather than buried in a shared transition rule.
  • The row inversion uses a named group (group/r) so the number badge's border can flip in the same cut as the row's background.
  • The marquee becomes an --animate-* token plus w-max and flex; the @keyframes block is the only motion left in the stylesheet.
  • The dot grid and the diagonal hatch both stay arbitrary background values — neither is a design-scale value, and both belong on the element that shows them.
Paste this into ChatGPT, Claude, Cursor, or any coding assistant. The block below is pre-framed with everything the AI needs to integrate this demo into your project — markup, styles, scoping notes, and the source URL. Hit Copy and paste straight into your chat.
Here's a working CSS demo from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Brutalist Design Bordered Tailwind Hamburger Menu
Source: https://codefronts.com/navigation/tailwind-hamburger-menus/brutalist-design-bordered-tailwind-hamburger-menu/

Neo-brutalism with its rules intact: 3px black borders on everything, hard offset shadows that do not blur, one shrieking yellow, uppercase mono type &mdash; and motion that CUTS instead of eases, because in this dialect a transition curve is a lie. The press is the port's neatest line: the plate travels exactly its shadow's offset and lands flat, which is two utilities sitting next to each other.
## HTML
```html
<section class="thb-27 w-full min-h-svh grid justify-center content-start bg-thb27-paper font-thb27-mono text-thb27-ink px-5 py-9" aria-label="Brutalist bordered menu demo">
  <div class="group relative flex flex-col w-[min(400px,88vw)] h-140 overflow-hidden border-[3px] border-thb27-ink bg-thb27-paper shadow-[8px_8px_0_var(--color-thb27-ink)] [background-image:radial-gradient(oklch(0.18_0.01_90/0.14)_1.2px,transparent_1.3px)] [background-size:18px_18px]">
    <input type="checkbox" id="thb27-t" class="peer absolute w-px h-px overflow-hidden whitespace-nowrap [clip-path:inset(50%)]">
    <header class="relative z-2 flex items-center justify-between p-3.5 border-b-[3px] border-thb27-ink bg-thb27-paper">
      <span class="text-base font-bold tracking-[0.04em]">RAW&mdash;GOODS<i class="not-italic align-super text-[10px]" aria-hidden="true">&reg;</i></span>
      <label for="thb27-t" class="flex items-center gap-2.5 min-h-11.5 px-3.5 border-[3px] border-thb27-ink bg-thb27-acc cursor-pointer select-none shadow-[6px_6px_0_var(--color-thb27-ink)] transition-[translate,box-shadow,background] duration-[60ms] ease-linear hover:bg-thb27-acc2 peer-focus-visible:outline-3 peer-focus-visible:outline-thb27-ink peer-focus-visible:outline-offset-3 group-has-checked:translate-x-1.5 group-has-checked:translate-y-1.5 group-has-checked:shadow-[0_0_0_var(--color-thb27-ink)]">
        <span class="relative block w-5 h-3.5" aria-hidden="true">
          <i class="absolute left-0 top-0 w-5 h-[3px] bg-thb27-ink transition-[translate,rotate] duration-[60ms] ease-linear group-has-checked:translate-y-[5.5px] group-has-checked:rotate-45"></i>
          <i class="absolute left-0 top-[5.5px] w-5 h-[3px] bg-thb27-ink transition-[opacity] duration-[60ms] ease-linear group-has-checked:opacity-0"></i>
          <i class="absolute left-0 top-[11px] w-5 h-[3px] bg-thb27-ink transition-[translate,rotate] duration-[60ms] ease-linear group-has-checked:-translate-y-[5.5px] group-has-checked:-rotate-45"></i>
        </span>
        <span class="text-xs font-bold tracking-[0.08em] group-has-checked:hidden" aria-hidden="true">MENU</span>
        <span class="hidden text-xs font-bold tracking-[0.08em] group-has-checked:block" aria-hidden="true">CLOSE</span>
      </label>
    </header>
    <nav aria-label="Site" class="absolute inset-x-0 top-[79px] bottom-10 z-1 hidden flex-col bg-thb27-paper border-b-[3px] border-thb27-ink group-has-checked:flex">
      <div class="border-b-[3px] border-thb27-ink"><a href="#shop" class="group/r flex items-center gap-3.5 min-h-16 px-4.5 text-[15px] font-bold tracking-[0.06em] text-thb27-ink no-underline hover:bg-thb27-ink hover:text-thb27-paper focus-visible:bg-thb27-ink focus-visible:text-thb27-paper focus-visible:outline-3 focus-visible:outline-thb27-acc focus-visible:-outline-offset-6"><b class="px-1.5 py-0.5 border-2 border-thb27-ink text-[11px] group-hover/r:border-thb27-paper group-focus-visible/r:border-thb27-paper">01</b>SHOP ALL<span class="ml-auto text-lg" aria-hidden="true">&rarr;</span></a></div>
      <div class="border-b-[3px] border-thb27-ink"><a href="#drops" class="group/r flex items-center gap-3.5 min-h-16 px-4.5 text-[15px] font-bold tracking-[0.06em] text-thb27-ink no-underline hover:bg-thb27-ink hover:text-thb27-paper focus-visible:bg-thb27-ink focus-visible:text-thb27-paper focus-visible:outline-3 focus-visible:outline-thb27-acc focus-visible:-outline-offset-6"><b class="px-1.5 py-0.5 border-2 border-thb27-ink text-[11px] group-hover/r:border-thb27-paper group-focus-visible/r:border-thb27-paper">02</b>DROPS<span class="ml-auto text-lg" aria-hidden="true">&rarr;</span></a></div>
      <div class="border-b-[3px] border-thb27-ink"><a href="#manifesto" class="group/r flex items-center gap-3.5 min-h-16 px-4.5 text-[15px] font-bold tracking-[0.06em] text-thb27-ink no-underline hover:bg-thb27-ink hover:text-thb27-paper focus-visible:bg-thb27-ink focus-visible:text-thb27-paper focus-visible:outline-3 focus-visible:outline-thb27-acc focus-visible:-outline-offset-6"><b class="px-1.5 py-0.5 border-2 border-thb27-ink text-[11px] group-hover/r:border-thb27-paper group-focus-visible/r:border-thb27-paper">03</b>MANIFESTO<span class="ml-auto text-lg" aria-hidden="true">&rarr;</span></a></div>
      <div class="border-b-[3px] border-thb27-ink"><a href="#faq" class="group/r flex items-center gap-3.5 min-h-16 px-4.5 text-[15px] font-bold tracking-[0.06em] text-thb27-ink no-underline hover:bg-thb27-ink hover:text-thb27-paper focus-visible:bg-thb27-ink focus-visible:text-thb27-paper focus-visible:outline-3 focus-visible:outline-thb27-acc focus-visible:-outline-offset-6"><b class="px-1.5 py-0.5 border-2 border-thb27-ink text-[11px] group-hover/r:border-thb27-paper group-focus-visible/r:border-thb27-paper">04</b>FAQ<span class="ml-auto text-lg" aria-hidden="true">&rarr;</span></a></div>
    </nav>
    <div class="flex-1 grid content-start gap-4.5 p-5.5" aria-hidden="true">
      <div class="w-max -rotate-1.5 px-4 py-3 border-[3px] border-thb27-ink bg-thb27-acc text-xs font-bold leading-[1.7] tracking-[0.06em] shadow-[6px_6px_0_var(--color-thb27-ink)]">EST. 2026<br>NO COOKIES<br>NO TRACKING</div>
      <div class="h-37.5 border-[3px] border-thb27-ink [background:repeating-linear-gradient(-45deg,var(--color-thb27-paper)_0_12px,oklch(0.18_0.01_90/0.12)_12px_24px)]"></div>
    </div>
    <div class="mt-auto overflow-hidden py-2.25 border-t-[3px] border-thb27-ink bg-thb27-ink text-thb27-paper" aria-hidden="true">
      <div class="flex w-max animate-thb27-tape motion-reduce:animate-none">
        <span class="whitespace-nowrap text-[11.5px] font-bold tracking-[0.14em]">FREE SHIPPING OVER $80 &#9733; PRESS THE PLATE &#9733; EVERYTHING HAS A BORDER &#9733;&nbsp;</span>
        <span class="whitespace-nowrap text-[11.5px] font-bold tracking-[0.14em]">FREE SHIPPING OVER $80 &#9733; PRESS THE PLATE &#9733; EVERYTHING HAS A BORDER &#9733;&nbsp;</span>
      </div>
    </div>
  </div>
</section>
```
## CSS
```css
@import "tailwindcss";

@theme {
  --color-thb27-paper: #f7f4e9;
  --color-thb27-paper: oklch(0.96 0.01 95);
  --color-thb27-ink: #1f1c14;
  --color-thb27-ink: oklch(0.18 0.01 90);
  --color-thb27-acc: #f2d43c;
  --color-thb27-acc: oklch(0.86 0.17 95);
  --color-thb27-acc2: #ffe23f;
  --color-thb27-acc2: oklch(0.9 0.19 95);
  --font-thb27-mono: 'JetBrains Mono', ui-monospace, 'Cascadia Mono', Menlo, monospace;
  --animate-thb27-tape: thb27-tape 14s linear infinite;
}
/* Keyframes are a rule, not a value — the @theme --animate-* entry only names this. */

@keyframes thb27-tape {
  to {
    translate: -50% 0;
  }
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's
   w-full min-h-svh. It scopes the demo, and it holds the stage at full height in the
   moment before the browser build has compiled its utilities. */

.thb-27 {
  width: 100%;
  min-height: 100svh;
}
```

How this works

Brutalist depth is the shadow that admits it is fake: zero blur, pure offset, and interaction means physically closing the gap.

<label class="border-[3px] border-thb27-ink bg-thb27-acc
  shadow-[6px_6px_0_var(--color-thb27-ink)]
  transition-[translate,box-shadow] duration-[60ms] ease-linear
  group-has-checked:translate-x-1.5 group-has-checked:translate-y-1.5
  group-has-checked:shadow-[0_0_0_var(--color-thb27-ink)]">

The element travels exactly its shadow's offset and lands flat on the surface. In a stylesheet the 6px in the shadow and the 6px in the translate live in two rules; here they are one class list apart, which is the difference between a fragile trick and an obvious one.

Inversion, not tinting. Rows flip completely on hover and focus — no 8%-alpha wash — and the number badge swaps its border colour in the same 60ms cut through a named group.

The ticker is kitsch on any other site and native vocabulary here: two identical copies of the text in a w-max flex track, translated -50% by one keyframe. Both copies must match exactly or the loop jumps.

The engine is demo 05's, verbatim: a clipped, still-focusable checkbox read through group-has-checked:. The style is loud; the accessibility is not optional. The focus ring sits 3px outside the shadow zone so it never disappears against a black border.

Make it yours

  • The palette is paper, ink and ONE accent. Swap --color-thb27-acc for hot pink or acid green; never add a fourth colour, the tension IS the restraint.
  • Border weight and shadow offset are a token pair (3px / 6px). Scale to 4px/8px for poster weight, and keep offset at roughly 2× border or the physics reads wrong.
  • Rotate at most two elements &plusmn;1.5°. More and it becomes a parody of itself.
  • The marquee text is one string repeated twice in the markup — edit both copies together.
  • Speed: the 14s in the --animate-thb27-tape token. Under 8s it reads as panic.

Gotchas — read before shipping

  • Hard shadows must be shadow-[…_0_…] with zero blur, never drop-shadow-* — a filter antialiases the edge soft, and crisp is the whole brand.
  • The press moves the element 6px. Keep 6px of breathing room in the layout, and do not attach anything that must stay put mid-press.
  • Uppercase mono tanks readability below about 13px. The rows here are 15px, and body copy on a brutalist site still stays sentence-case.
  • Black on yellow is 13:1 and fine, but a black focus ring vanishes against black borders — offset it OUTSIDE the shadow zone, as here.
  • duration-[60ms] is deliberate, not a mistake. Do not &ldquo;fix&rdquo; it to 200ms with an ease curve; that reverses the style's entire thesis.
  • motion-reduce: still applies: 60ms cuts are already calm, but the marquee must stop dead.

Browser support

ChromeSafariFirefoxEdge
111+16.4+128+111+

Borders, hard shadows, checkbox state and keyframe marquees are 2012-era CSS; :has() behind has-checked: needs Firefox 121. Ironically the most avant-garde-looking demo is the most backwards-compatible.

Techniques used in this demo

Utilitiesfirst-class utility or variant

Arbitraryneeds bracket syntax

Plain CSSno Tailwind surface

Search CodeFronts

Loading…