12 / 17
All 17 in 17 Tailwind CSS Side Menus
- 01Tailwind Slide-In Side Menu with Animated Hamburger Icon
- 02Tailwind Sidebar Drawer with Blurred Backdrop Overlay
- 03Tailwind Off-Canvas Push Sidebar Menu
- 04Tailwind Collapsible Icon Sidebar That Expands on Hover
- 05Responsive Tailwind Sidebar with Mobile Hamburger Toggle
- 06Tailwind Sticky Sidebar Navigation with Scrolling Content
- 07Tailwind Multi-Level Dropdown Sidebar Menu (Nested Accordion)
- 08Tailwind Full-Height Flexbox Sidebar Layout
- 09Tailwind Neumorphism Sidebar Menu (Dark Mode)
- 10Tailwind Glassmorphism Sidebar with Backdrop Blur
- 11Tailwind Cyberpunk Neon Sidebar (Dark Mode)
- 12Brutalist Sidebar Navigation in Tailwind CSS
- 13Pure CSS Hamburger Menu in Tailwind (Checkbox Hack, No JS)
- 14Tailwind Sidebar Drawer That Opens on Hover
- 15Tailwind Collapsible Sidebar with Toggle Button (No JS)
- 16Tailwind Accordion Sidebar Navigation for Documentation
- 17Tailwind macOS-Style Glass Dock Sidebar with Sliding Highlight
Brutalist Sidebar Navigation in Tailwind CSS
Structure as decoration: a black slab with a 4px red rule, condensed 900-weight uppercase links prefixed by monospace //, and a hover that slams to full yellow with black ink. The active row fills solid red and grows an arrow via aria-[current=page]:after:content-['→']. Zero gradients, zero radii — and every state is now visible to keyboard users, not just the mouse.
Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time
Untitled UI React · Affiliate link
The code
<section class="tsm-12 flex w-full min-h-svh border-[3px] border-tsm12-ink bg-tsm12-paper font-tsm12-head text-tsm12-ink" aria-label="Brutalist sidebar navigation demo">
<nav aria-label="Main" class="flex w-52 shrink-0 flex-col border-r-4 border-tsm12-acc bg-tsm12-ink text-tsm12-paper">
<div class="border-b-[3px] border-tsm12-acc px-4 py-[18px]">
<p class="mb-1 font-tsm12-mono text-[10px] tracking-[0.2em] text-tsm12-navmut">EST. 2024</p>
<p class="text-[28px] leading-none font-black tracking-[-0.02em] uppercase">Brutal</p>
<p class="mt-1.5 inline-block bg-tsm12-acc px-1.5 py-px text-[11px] font-extrabold tracking-[0.1em] text-white uppercase">Studio</p>
</div>
<ul class="flex-1">
<li><a href="#" class="group/l relative flex min-h-12 items-center border-b border-tsm12-line px-4 text-lg font-extrabold tracking-[0.04em] text-tsm12-navmut uppercase transition-colors duration-100 before:mr-2 before:font-tsm12-mono before:text-xs before:text-tsm12-navmut/60 before:content-['//'] hover:bg-tsm12-yel hover:text-black hover:before:text-black/60 focus-visible:bg-tsm12-yel focus-visible:text-black focus-visible:outline-none aria-[current=page]:border-tsm12-acc aria-[current=page]:bg-tsm12-acc aria-[current=page]:text-tsm12-paper aria-[current=page]:before:text-white/60 aria-[current=page]:after:ml-auto aria-[current=page]:after:font-tsm12-mono aria-[current=page]:after:text-base aria-[current=page]:after:content-['→'] motion-reduce:transition-none" aria-current="page">Home</a></li>
<li><a href="#" class="group/l relative flex min-h-12 items-center border-b border-tsm12-line px-4 text-lg font-extrabold tracking-[0.04em] text-tsm12-navmut uppercase transition-colors duration-100 before:mr-2 before:font-tsm12-mono before:text-xs before:text-tsm12-navmut/60 before:content-['//'] hover:bg-tsm12-yel hover:text-black hover:before:text-black/60 focus-visible:bg-tsm12-yel focus-visible:text-black focus-visible:outline-none aria-[current=page]:border-tsm12-acc aria-[current=page]:bg-tsm12-acc aria-[current=page]:text-tsm12-paper aria-[current=page]:before:text-white/60 aria-[current=page]:after:ml-auto aria-[current=page]:after:font-tsm12-mono aria-[current=page]:after:text-base aria-[current=page]:after:content-['→'] motion-reduce:transition-none">Work<span class="ml-auto pl-2 font-tsm12-mono text-[11px] font-normal text-tsm12-yel group-hover/l:text-black">12</span></a></li>
<li><a href="#" class="group/l relative flex min-h-12 items-center border-b border-tsm12-line px-4 text-lg font-extrabold tracking-[0.04em] text-tsm12-navmut uppercase transition-colors duration-100 before:mr-2 before:font-tsm12-mono before:text-xs before:text-tsm12-navmut/60 before:content-['//'] hover:bg-tsm12-yel hover:text-black hover:before:text-black/60 focus-visible:bg-tsm12-yel focus-visible:text-black focus-visible:outline-none aria-[current=page]:border-tsm12-acc aria-[current=page]:bg-tsm12-acc aria-[current=page]:text-tsm12-paper aria-[current=page]:before:text-white/60 aria-[current=page]:after:ml-auto aria-[current=page]:after:font-tsm12-mono aria-[current=page]:after:text-base aria-[current=page]:after:content-['→'] motion-reduce:transition-none">Studio</a></li>
<li><a href="#" class="group/l relative flex min-h-12 items-center border-b border-tsm12-line px-4 text-lg font-extrabold tracking-[0.04em] text-tsm12-navmut uppercase transition-colors duration-100 before:mr-2 before:font-tsm12-mono before:text-xs before:text-tsm12-navmut/60 before:content-['//'] hover:bg-tsm12-yel hover:text-black hover:before:text-black/60 focus-visible:bg-tsm12-yel focus-visible:text-black focus-visible:outline-none aria-[current=page]:border-tsm12-acc aria-[current=page]:bg-tsm12-acc aria-[current=page]:text-tsm12-paper aria-[current=page]:before:text-white/60 aria-[current=page]:after:ml-auto aria-[current=page]:after:font-tsm12-mono aria-[current=page]:after:text-base aria-[current=page]:after:content-['→'] motion-reduce:transition-none">Journal<span class="ml-auto pl-2 font-tsm12-mono text-[11px] font-normal text-tsm12-yel group-hover/l:text-black">05</span></a></li>
<li><a href="#" class="group/l relative flex min-h-12 items-center border-b border-tsm12-line px-4 text-lg font-extrabold tracking-[0.04em] text-tsm12-navmut uppercase transition-colors duration-100 before:mr-2 before:font-tsm12-mono before:text-xs before:text-tsm12-navmut/60 before:content-['//'] hover:bg-tsm12-yel hover:text-black hover:before:text-black/60 focus-visible:bg-tsm12-yel focus-visible:text-black focus-visible:outline-none aria-[current=page]:border-tsm12-acc aria-[current=page]:bg-tsm12-acc aria-[current=page]:text-tsm12-paper aria-[current=page]:before:text-white/60 aria-[current=page]:after:ml-auto aria-[current=page]:after:font-tsm12-mono aria-[current=page]:after:text-base aria-[current=page]:after:content-['→'] motion-reduce:transition-none">Contact</a></li>
</ul>
<div class="border-t-[3px] border-tsm12-acc px-4 py-3">
<p class="mb-1 font-tsm12-mono text-[10px] tracking-[0.15em] text-tsm12-navmut">// USER</p>
<p class="text-sm font-extrabold tracking-[0.05em] uppercase">J. Haas</p>
</div>
</nav>
<div class="min-w-0 flex-1">
<div class="flex items-baseline gap-3 border-b-[3px] border-tsm12-ink px-6 py-4">
<span class="font-tsm12-mono text-xs text-tsm12-acc">[01]</span>
<h1 class="text-[clamp(28px,4vw,40px)] leading-none font-black tracking-[-0.01em] uppercase">Homepage</h1>
</div>
<div class="p-6">
<p class="mb-6 max-w-sm text-base leading-snug font-semibold text-tsm12-mut text-pretty">Raw borders, zero gradients, high-contrast type — and a thick red rule as the only decoration. Hover or Tab the menu.</p>
<div class="grid max-w-md grid-cols-2 border-[3px] border-tsm12-ink">
<div class="border-tsm12-ink p-4 odd:border-r-2 nth-[-n+2]:border-b-2"><p class="text-[clamp(26px,4vw,36px)] leading-none font-black tracking-[-0.03em]">24</p><p class="mt-1.5 font-tsm12-mono text-[11px] tracking-[0.1em] text-tsm12-mut uppercase">Projects</p></div>
<div class="border-tsm12-ink p-4 odd:border-r-2 nth-[-n+2]:border-b-2"><p class="text-[clamp(26px,4vw,36px)] leading-none font-black tracking-[-0.03em]">08</p><p class="mt-1.5 font-tsm12-mono text-[11px] tracking-[0.1em] text-tsm12-mut uppercase">Clients</p></div>
<div class="border-tsm12-ink p-4 odd:border-r-2 nth-[-n+2]:border-b-2"><p class="text-[clamp(26px,4vw,36px)] leading-none font-black tracking-[-0.03em]">6yr</p><p class="mt-1.5 font-tsm12-mono text-[11px] tracking-[0.1em] text-tsm12-mut uppercase">Experience</p></div>
<div class="border-tsm12-ink p-4 odd:border-r-2 nth-[-n+2]:border-b-2"><p class="text-[clamp(26px,4vw,36px)] leading-none font-black tracking-[-0.03em]">100%</p><p class="mt-1.5 font-tsm12-mono text-[11px] tracking-[0.1em] text-tsm12-mut uppercase">Remote</p></div>
</div>
</div>
</div>
</section><section class="tsm-12 flex w-full min-h-svh border-[3px] border-tsm12-ink bg-tsm12-paper font-tsm12-head text-tsm12-ink" aria-label="Brutalist sidebar navigation demo">
<nav aria-label="Main" class="flex w-52 shrink-0 flex-col border-r-4 border-tsm12-acc bg-tsm12-ink text-tsm12-paper">
<div class="border-b-[3px] border-tsm12-acc px-4 py-[18px]">
<p class="mb-1 font-tsm12-mono text-[10px] tracking-[0.2em] text-tsm12-navmut">EST. 2024</p>
<p class="text-[28px] leading-none font-black tracking-[-0.02em] uppercase">Brutal</p>
<p class="mt-1.5 inline-block bg-tsm12-acc px-1.5 py-px text-[11px] font-extrabold tracking-[0.1em] text-white uppercase">Studio</p>
</div>
<ul class="flex-1">
<li><a href="#" class="group/l relative flex min-h-12 items-center border-b border-tsm12-line px-4 text-lg font-extrabold tracking-[0.04em] text-tsm12-navmut uppercase transition-colors duration-100 before:mr-2 before:font-tsm12-mono before:text-xs before:text-tsm12-navmut/60 before:content-['//'] hover:bg-tsm12-yel hover:text-black hover:before:text-black/60 focus-visible:bg-tsm12-yel focus-visible:text-black focus-visible:outline-none aria-[current=page]:border-tsm12-acc aria-[current=page]:bg-tsm12-acc aria-[current=page]:text-tsm12-paper aria-[current=page]:before:text-white/60 aria-[current=page]:after:ml-auto aria-[current=page]:after:font-tsm12-mono aria-[current=page]:after:text-base aria-[current=page]:after:content-['→'] motion-reduce:transition-none" aria-current="page">Home</a></li>
<li><a href="#" class="group/l relative flex min-h-12 items-center border-b border-tsm12-line px-4 text-lg font-extrabold tracking-[0.04em] text-tsm12-navmut uppercase transition-colors duration-100 before:mr-2 before:font-tsm12-mono before:text-xs before:text-tsm12-navmut/60 before:content-['//'] hover:bg-tsm12-yel hover:text-black hover:before:text-black/60 focus-visible:bg-tsm12-yel focus-visible:text-black focus-visible:outline-none aria-[current=page]:border-tsm12-acc aria-[current=page]:bg-tsm12-acc aria-[current=page]:text-tsm12-paper aria-[current=page]:before:text-white/60 aria-[current=page]:after:ml-auto aria-[current=page]:after:font-tsm12-mono aria-[current=page]:after:text-base aria-[current=page]:after:content-['→'] motion-reduce:transition-none">Work<span class="ml-auto pl-2 font-tsm12-mono text-[11px] font-normal text-tsm12-yel group-hover/l:text-black">12</span></a></li>
<li><a href="#" class="group/l relative flex min-h-12 items-center border-b border-tsm12-line px-4 text-lg font-extrabold tracking-[0.04em] text-tsm12-navmut uppercase transition-colors duration-100 before:mr-2 before:font-tsm12-mono before:text-xs before:text-tsm12-navmut/60 before:content-['//'] hover:bg-tsm12-yel hover:text-black hover:before:text-black/60 focus-visible:bg-tsm12-yel focus-visible:text-black focus-visible:outline-none aria-[current=page]:border-tsm12-acc aria-[current=page]:bg-tsm12-acc aria-[current=page]:text-tsm12-paper aria-[current=page]:before:text-white/60 aria-[current=page]:after:ml-auto aria-[current=page]:after:font-tsm12-mono aria-[current=page]:after:text-base aria-[current=page]:after:content-['→'] motion-reduce:transition-none">Studio</a></li>
<li><a href="#" class="group/l relative flex min-h-12 items-center border-b border-tsm12-line px-4 text-lg font-extrabold tracking-[0.04em] text-tsm12-navmut uppercase transition-colors duration-100 before:mr-2 before:font-tsm12-mono before:text-xs before:text-tsm12-navmut/60 before:content-['//'] hover:bg-tsm12-yel hover:text-black hover:before:text-black/60 focus-visible:bg-tsm12-yel focus-visible:text-black focus-visible:outline-none aria-[current=page]:border-tsm12-acc aria-[current=page]:bg-tsm12-acc aria-[current=page]:text-tsm12-paper aria-[current=page]:before:text-white/60 aria-[current=page]:after:ml-auto aria-[current=page]:after:font-tsm12-mono aria-[current=page]:after:text-base aria-[current=page]:after:content-['→'] motion-reduce:transition-none">Journal<span class="ml-auto pl-2 font-tsm12-mono text-[11px] font-normal text-tsm12-yel group-hover/l:text-black">05</span></a></li>
<li><a href="#" class="group/l relative flex min-h-12 items-center border-b border-tsm12-line px-4 text-lg font-extrabold tracking-[0.04em] text-tsm12-navmut uppercase transition-colors duration-100 before:mr-2 before:font-tsm12-mono before:text-xs before:text-tsm12-navmut/60 before:content-['//'] hover:bg-tsm12-yel hover:text-black hover:before:text-black/60 focus-visible:bg-tsm12-yel focus-visible:text-black focus-visible:outline-none aria-[current=page]:border-tsm12-acc aria-[current=page]:bg-tsm12-acc aria-[current=page]:text-tsm12-paper aria-[current=page]:before:text-white/60 aria-[current=page]:after:ml-auto aria-[current=page]:after:font-tsm12-mono aria-[current=page]:after:text-base aria-[current=page]:after:content-['→'] motion-reduce:transition-none">Contact</a></li>
</ul>
<div class="border-t-[3px] border-tsm12-acc px-4 py-3">
<p class="mb-1 font-tsm12-mono text-[10px] tracking-[0.15em] text-tsm12-navmut">// USER</p>
<p class="text-sm font-extrabold tracking-[0.05em] uppercase">J. Haas</p>
</div>
</nav>
<div class="min-w-0 flex-1">
<div class="flex items-baseline gap-3 border-b-[3px] border-tsm12-ink px-6 py-4">
<span class="font-tsm12-mono text-xs text-tsm12-acc">[01]</span>
<h1 class="text-[clamp(28px,4vw,40px)] leading-none font-black tracking-[-0.01em] uppercase">Homepage</h1>
</div>
<div class="p-6">
<p class="mb-6 max-w-sm text-base leading-snug font-semibold text-tsm12-mut text-pretty">Raw borders, zero gradients, high-contrast type — and a thick red rule as the only decoration. Hover or Tab the menu.</p>
<div class="grid max-w-md grid-cols-2 border-[3px] border-tsm12-ink">
<div class="border-tsm12-ink p-4 odd:border-r-2 nth-[-n+2]:border-b-2"><p class="text-[clamp(26px,4vw,36px)] leading-none font-black tracking-[-0.03em]">24</p><p class="mt-1.5 font-tsm12-mono text-[11px] tracking-[0.1em] text-tsm12-mut uppercase">Projects</p></div>
<div class="border-tsm12-ink p-4 odd:border-r-2 nth-[-n+2]:border-b-2"><p class="text-[clamp(26px,4vw,36px)] leading-none font-black tracking-[-0.03em]">08</p><p class="mt-1.5 font-tsm12-mono text-[11px] tracking-[0.1em] text-tsm12-mut uppercase">Clients</p></div>
<div class="border-tsm12-ink p-4 odd:border-r-2 nth-[-n+2]:border-b-2"><p class="text-[clamp(26px,4vw,36px)] leading-none font-black tracking-[-0.03em]">6yr</p><p class="mt-1.5 font-tsm12-mono text-[11px] tracking-[0.1em] text-tsm12-mut uppercase">Experience</p></div>
<div class="border-tsm12-ink p-4 odd:border-r-2 nth-[-n+2]:border-b-2"><p class="text-[clamp(26px,4vw,36px)] leading-none font-black tracking-[-0.03em]">100%</p><p class="mt-1.5 font-tsm12-mono text-[11px] tracking-[0.1em] text-tsm12-mut uppercase">Remote</p></div>
</div>
</div>
</div>
</section>@import "tailwindcss";
@theme {
--color-tsm12-paper: #f5f0e8;
--color-tsm12-paper: oklch(0.957 0.012 79.8);
--color-tsm12-ink: #0a0a0a;
--color-tsm12-ink: oklch(0.145 0 0);
--color-tsm12-acc: #e63329;
--color-tsm12-acc: oklch(0.604 0.216 28.7);
--color-tsm12-yel: #f7e733;
--color-tsm12-yel: oklch(0.913 0.181 104);
--color-tsm12-line: #262626;
--color-tsm12-line: oklch(0.269 0 0);
--color-tsm12-navmut: #a8a8a8;
--color-tsm12-navmut: oklch(0.732 0 0);
--color-tsm12-mut: #3d3d3d;
--color-tsm12-mut: oklch(0.36 0 0);
--font-tsm12-head: 'Barlow Condensed', 'Arial Narrow', system-ui, sans-serif;
--font-tsm12-mono: 'Space Mono', ui-monospace, monospace;
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's utilities, so the
stage is sized before the browser build compiles. */
.tsm-12 {
width: 100%;
min-height: 100svh;
}@import "tailwindcss";
@theme {
--color-tsm12-paper: #f5f0e8;
--color-tsm12-paper: oklch(0.957 0.012 79.8);
--color-tsm12-ink: #0a0a0a;
--color-tsm12-ink: oklch(0.145 0 0);
--color-tsm12-acc: #e63329;
--color-tsm12-acc: oklch(0.604 0.216 28.7);
--color-tsm12-yel: #f7e733;
--color-tsm12-yel: oklch(0.913 0.181 104);
--color-tsm12-line: #262626;
--color-tsm12-line: oklch(0.269 0 0);
--color-tsm12-navmut: #a8a8a8;
--color-tsm12-navmut: oklch(0.732 0 0);
--color-tsm12-mut: #3d3d3d;
--color-tsm12-mut: oklch(0.36 0 0);
--font-tsm12-head: 'Barlow Condensed', 'Arial Narrow', system-ui, sans-serif;
--font-tsm12-mono: 'Space Mono', ui-monospace, monospace;
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's utilities, so the
stage is sized before the browser build compiles. */
.tsm-12 {
width: 100%;
min-height: 100svh;
}Setup — do this once per project
Skip this if your project already runs Tailwind v4.
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
<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.
npm install tailwindcss @tailwindcss/vite
npm install tailwindcss @tailwindcss/vite// vite.config.js ("type": "module" in package.json)
import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [tailwindcss()],
})// vite.config.js ("type": "module" in package.json)
import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [tailwindcss()],
})Any v4 setup works — Vite, PostCSS or the CLI. Nothing in this demo is bundler-specific.
@import "tailwindcss";
@theme {
--color-tsm12-paper: #f5f0e8;
--color-tsm12-paper: oklch(0.957 0.012 79.8);
--color-tsm12-ink: #0a0a0a;
--color-tsm12-ink: oklch(0.145 0 0);
--color-tsm12-acc: #e63329;
--color-tsm12-acc: oklch(0.604 0.216 28.7);
--color-tsm12-yel: #f7e733;
--color-tsm12-yel: oklch(0.913 0.181 104);
--color-tsm12-line: #262626;
--color-tsm12-line: oklch(0.269 0 0);
--color-tsm12-navmut: #a8a8a8;
--color-tsm12-navmut: oklch(0.732 0 0);
--color-tsm12-mut: #3d3d3d;
--color-tsm12-mut: oklch(0.36 0 0);
--font-tsm12-head: 'Barlow Condensed', 'Arial Narrow', system-ui, sans-serif;
--font-tsm12-mono: 'Space Mono', ui-monospace, monospace;
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's utilities, so the
stage is sized before the browser build compiles. */
.tsm-12 {
width: 100%;
min-height: 100svh;
}@import "tailwindcss";
@theme {
--color-tsm12-paper: #f5f0e8;
--color-tsm12-paper: oklch(0.957 0.012 79.8);
--color-tsm12-ink: #0a0a0a;
--color-tsm12-ink: oklch(0.145 0 0);
--color-tsm12-acc: #e63329;
--color-tsm12-acc: oklch(0.604 0.216 28.7);
--color-tsm12-yel: #f7e733;
--color-tsm12-yel: oklch(0.913 0.181 104);
--color-tsm12-line: #262626;
--color-tsm12-line: oklch(0.269 0 0);
--color-tsm12-navmut: #a8a8a8;
--color-tsm12-navmut: oklch(0.732 0 0);
--color-tsm12-mut: #3d3d3d;
--color-tsm12-mut: oklch(0.36 0 0);
--font-tsm12-head: 'Barlow Condensed', 'Arial Narrow', system-ui, sans-serif;
--font-tsm12-mono: 'Space Mono', ui-monospace, monospace;
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's utilities, so the
stage is sized before the browser build compiles. */
.tsm-12 {
width: 100%;
min-height: 100svh;
}<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=Barlow+Condensed:wght@600;700;800;900&family=Space+Mono:wght@400;700&display=swap">
<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=Barlow+Condensed:wght@600;700;800;900&family=Space+Mono:wght@400;700&display=swap">What changed in the port
Which parts became utilities, which stayed CSS, and why.
- The
::before { content:'//' }and active::after { content:'→' }rules becamebefore:content-['//']andaria-[current=page]:after:content-['→']— the arrow is now tied to the page state, not a class. - The
:nth-child(even)/:nth-child(n+3)border-removal rules becameodd:border-r-2 nth-[-n+2]:border-b-2— add-only rules instead of add-then-remove. - UI upgrade from the CSS original: hover now inverts to a solid yellow slab with black ink (the stronger print-brutalist move the original suggested but didn't ship), and
focus-visible:gets the same treatment — the original had no focus style. - UI upgrade: nav text went from
#666on black (3.7:1) to#a8a8a8(8.6:1), counters are flex-aligned instead of absolutely positioned, and the stat numerals scale withclamp().
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 Sidebar Navigation in Tailwind CSS
Source: https://codefronts.com/navigation/tailwind-css-side-menus/brutalist-sidebar-navigation-tailwind-css/
Structure as decoration: a black slab with a 4px red rule, condensed 900-weight uppercase links prefixed by monospace //, and a hover that slams to full yellow with black ink. The active row fills solid red and grows an arrow via aria-[current=page]:after:content-['→']. Zero gradients, zero radii — and every state is now visible to keyboard users, not just the mouse.
## HTML
```html
<section class="tsm-12 flex w-full min-h-svh border-[3px] border-tsm12-ink bg-tsm12-paper font-tsm12-head text-tsm12-ink" aria-label="Brutalist sidebar navigation demo">
<nav aria-label="Main" class="flex w-52 shrink-0 flex-col border-r-4 border-tsm12-acc bg-tsm12-ink text-tsm12-paper">
<div class="border-b-[3px] border-tsm12-acc px-4 py-[18px]">
<p class="mb-1 font-tsm12-mono text-[10px] tracking-[0.2em] text-tsm12-navmut">EST. 2024</p>
<p class="text-[28px] leading-none font-black tracking-[-0.02em] uppercase">Brutal</p>
<p class="mt-1.5 inline-block bg-tsm12-acc px-1.5 py-px text-[11px] font-extrabold tracking-[0.1em] text-white uppercase">Studio</p>
</div>
<ul class="flex-1">
<li><a href="#" class="group/l relative flex min-h-12 items-center border-b border-tsm12-line px-4 text-lg font-extrabold tracking-[0.04em] text-tsm12-navmut uppercase transition-colors duration-100 before:mr-2 before:font-tsm12-mono before:text-xs before:text-tsm12-navmut/60 before:content-['//'] hover:bg-tsm12-yel hover:text-black hover:before:text-black/60 focus-visible:bg-tsm12-yel focus-visible:text-black focus-visible:outline-none aria-[current=page]:border-tsm12-acc aria-[current=page]:bg-tsm12-acc aria-[current=page]:text-tsm12-paper aria-[current=page]:before:text-white/60 aria-[current=page]:after:ml-auto aria-[current=page]:after:font-tsm12-mono aria-[current=page]:after:text-base aria-[current=page]:after:content-['→'] motion-reduce:transition-none" aria-current="page">Home</a></li>
<li><a href="#" class="group/l relative flex min-h-12 items-center border-b border-tsm12-line px-4 text-lg font-extrabold tracking-[0.04em] text-tsm12-navmut uppercase transition-colors duration-100 before:mr-2 before:font-tsm12-mono before:text-xs before:text-tsm12-navmut/60 before:content-['//'] hover:bg-tsm12-yel hover:text-black hover:before:text-black/60 focus-visible:bg-tsm12-yel focus-visible:text-black focus-visible:outline-none aria-[current=page]:border-tsm12-acc aria-[current=page]:bg-tsm12-acc aria-[current=page]:text-tsm12-paper aria-[current=page]:before:text-white/60 aria-[current=page]:after:ml-auto aria-[current=page]:after:font-tsm12-mono aria-[current=page]:after:text-base aria-[current=page]:after:content-['→'] motion-reduce:transition-none">Work<span class="ml-auto pl-2 font-tsm12-mono text-[11px] font-normal text-tsm12-yel group-hover/l:text-black">12</span></a></li>
<li><a href="#" class="group/l relative flex min-h-12 items-center border-b border-tsm12-line px-4 text-lg font-extrabold tracking-[0.04em] text-tsm12-navmut uppercase transition-colors duration-100 before:mr-2 before:font-tsm12-mono before:text-xs before:text-tsm12-navmut/60 before:content-['//'] hover:bg-tsm12-yel hover:text-black hover:before:text-black/60 focus-visible:bg-tsm12-yel focus-visible:text-black focus-visible:outline-none aria-[current=page]:border-tsm12-acc aria-[current=page]:bg-tsm12-acc aria-[current=page]:text-tsm12-paper aria-[current=page]:before:text-white/60 aria-[current=page]:after:ml-auto aria-[current=page]:after:font-tsm12-mono aria-[current=page]:after:text-base aria-[current=page]:after:content-['→'] motion-reduce:transition-none">Studio</a></li>
<li><a href="#" class="group/l relative flex min-h-12 items-center border-b border-tsm12-line px-4 text-lg font-extrabold tracking-[0.04em] text-tsm12-navmut uppercase transition-colors duration-100 before:mr-2 before:font-tsm12-mono before:text-xs before:text-tsm12-navmut/60 before:content-['//'] hover:bg-tsm12-yel hover:text-black hover:before:text-black/60 focus-visible:bg-tsm12-yel focus-visible:text-black focus-visible:outline-none aria-[current=page]:border-tsm12-acc aria-[current=page]:bg-tsm12-acc aria-[current=page]:text-tsm12-paper aria-[current=page]:before:text-white/60 aria-[current=page]:after:ml-auto aria-[current=page]:after:font-tsm12-mono aria-[current=page]:after:text-base aria-[current=page]:after:content-['→'] motion-reduce:transition-none">Journal<span class="ml-auto pl-2 font-tsm12-mono text-[11px] font-normal text-tsm12-yel group-hover/l:text-black">05</span></a></li>
<li><a href="#" class="group/l relative flex min-h-12 items-center border-b border-tsm12-line px-4 text-lg font-extrabold tracking-[0.04em] text-tsm12-navmut uppercase transition-colors duration-100 before:mr-2 before:font-tsm12-mono before:text-xs before:text-tsm12-navmut/60 before:content-['//'] hover:bg-tsm12-yel hover:text-black hover:before:text-black/60 focus-visible:bg-tsm12-yel focus-visible:text-black focus-visible:outline-none aria-[current=page]:border-tsm12-acc aria-[current=page]:bg-tsm12-acc aria-[current=page]:text-tsm12-paper aria-[current=page]:before:text-white/60 aria-[current=page]:after:ml-auto aria-[current=page]:after:font-tsm12-mono aria-[current=page]:after:text-base aria-[current=page]:after:content-['→'] motion-reduce:transition-none">Contact</a></li>
</ul>
<div class="border-t-[3px] border-tsm12-acc px-4 py-3">
<p class="mb-1 font-tsm12-mono text-[10px] tracking-[0.15em] text-tsm12-navmut">// USER</p>
<p class="text-sm font-extrabold tracking-[0.05em] uppercase">J. Haas</p>
</div>
</nav>
<div class="min-w-0 flex-1">
<div class="flex items-baseline gap-3 border-b-[3px] border-tsm12-ink px-6 py-4">
<span class="font-tsm12-mono text-xs text-tsm12-acc">[01]</span>
<h1 class="text-[clamp(28px,4vw,40px)] leading-none font-black tracking-[-0.01em] uppercase">Homepage</h1>
</div>
<div class="p-6">
<p class="mb-6 max-w-sm text-base leading-snug font-semibold text-tsm12-mut text-pretty">Raw borders, zero gradients, high-contrast type — and a thick red rule as the only decoration. Hover or Tab the menu.</p>
<div class="grid max-w-md grid-cols-2 border-[3px] border-tsm12-ink">
<div class="border-tsm12-ink p-4 odd:border-r-2 nth-[-n+2]:border-b-2"><p class="text-[clamp(26px,4vw,36px)] leading-none font-black tracking-[-0.03em]">24</p><p class="mt-1.5 font-tsm12-mono text-[11px] tracking-[0.1em] text-tsm12-mut uppercase">Projects</p></div>
<div class="border-tsm12-ink p-4 odd:border-r-2 nth-[-n+2]:border-b-2"><p class="text-[clamp(26px,4vw,36px)] leading-none font-black tracking-[-0.03em]">08</p><p class="mt-1.5 font-tsm12-mono text-[11px] tracking-[0.1em] text-tsm12-mut uppercase">Clients</p></div>
<div class="border-tsm12-ink p-4 odd:border-r-2 nth-[-n+2]:border-b-2"><p class="text-[clamp(26px,4vw,36px)] leading-none font-black tracking-[-0.03em]">6yr</p><p class="mt-1.5 font-tsm12-mono text-[11px] tracking-[0.1em] text-tsm12-mut uppercase">Experience</p></div>
<div class="border-tsm12-ink p-4 odd:border-r-2 nth-[-n+2]:border-b-2"><p class="text-[clamp(26px,4vw,36px)] leading-none font-black tracking-[-0.03em]">100%</p><p class="mt-1.5 font-tsm12-mono text-[11px] tracking-[0.1em] text-tsm12-mut uppercase">Remote</p></div>
</div>
</div>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tsm12-paper: #f5f0e8;
--color-tsm12-paper: oklch(0.957 0.012 79.8);
--color-tsm12-ink: #0a0a0a;
--color-tsm12-ink: oklch(0.145 0 0);
--color-tsm12-acc: #e63329;
--color-tsm12-acc: oklch(0.604 0.216 28.7);
--color-tsm12-yel: #f7e733;
--color-tsm12-yel: oklch(0.913 0.181 104);
--color-tsm12-line: #262626;
--color-tsm12-line: oklch(0.269 0 0);
--color-tsm12-navmut: #a8a8a8;
--color-tsm12-navmut: oklch(0.732 0 0);
--color-tsm12-mut: #3d3d3d;
--color-tsm12-mut: oklch(0.36 0 0);
--font-tsm12-head: 'Barlow Condensed', 'Arial Narrow', system-ui, sans-serif;
--font-tsm12-mono: 'Space Mono', ui-monospace, monospace;
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's utilities, so the
stage is sized before the browser build compiles. */
.tsm-12 {
width: 100%;
min-height: 100svh;
}
```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 Sidebar Navigation in Tailwind CSS
Source: https://codefronts.com/navigation/tailwind-css-side-menus/brutalist-sidebar-navigation-tailwind-css/
Structure as decoration: a black slab with a 4px red rule, condensed 900-weight uppercase links prefixed by monospace //, and a hover that slams to full yellow with black ink. The active row fills solid red and grows an arrow via aria-[current=page]:after:content-['→']. Zero gradients, zero radii — and every state is now visible to keyboard users, not just the mouse.
## HTML
```html
<section class="tsm-12 flex w-full min-h-svh border-[3px] border-tsm12-ink bg-tsm12-paper font-tsm12-head text-tsm12-ink" aria-label="Brutalist sidebar navigation demo">
<nav aria-label="Main" class="flex w-52 shrink-0 flex-col border-r-4 border-tsm12-acc bg-tsm12-ink text-tsm12-paper">
<div class="border-b-[3px] border-tsm12-acc px-4 py-[18px]">
<p class="mb-1 font-tsm12-mono text-[10px] tracking-[0.2em] text-tsm12-navmut">EST. 2024</p>
<p class="text-[28px] leading-none font-black tracking-[-0.02em] uppercase">Brutal</p>
<p class="mt-1.5 inline-block bg-tsm12-acc px-1.5 py-px text-[11px] font-extrabold tracking-[0.1em] text-white uppercase">Studio</p>
</div>
<ul class="flex-1">
<li><a href="#" class="group/l relative flex min-h-12 items-center border-b border-tsm12-line px-4 text-lg font-extrabold tracking-[0.04em] text-tsm12-navmut uppercase transition-colors duration-100 before:mr-2 before:font-tsm12-mono before:text-xs before:text-tsm12-navmut/60 before:content-['//'] hover:bg-tsm12-yel hover:text-black hover:before:text-black/60 focus-visible:bg-tsm12-yel focus-visible:text-black focus-visible:outline-none aria-[current=page]:border-tsm12-acc aria-[current=page]:bg-tsm12-acc aria-[current=page]:text-tsm12-paper aria-[current=page]:before:text-white/60 aria-[current=page]:after:ml-auto aria-[current=page]:after:font-tsm12-mono aria-[current=page]:after:text-base aria-[current=page]:after:content-['→'] motion-reduce:transition-none" aria-current="page">Home</a></li>
<li><a href="#" class="group/l relative flex min-h-12 items-center border-b border-tsm12-line px-4 text-lg font-extrabold tracking-[0.04em] text-tsm12-navmut uppercase transition-colors duration-100 before:mr-2 before:font-tsm12-mono before:text-xs before:text-tsm12-navmut/60 before:content-['//'] hover:bg-tsm12-yel hover:text-black hover:before:text-black/60 focus-visible:bg-tsm12-yel focus-visible:text-black focus-visible:outline-none aria-[current=page]:border-tsm12-acc aria-[current=page]:bg-tsm12-acc aria-[current=page]:text-tsm12-paper aria-[current=page]:before:text-white/60 aria-[current=page]:after:ml-auto aria-[current=page]:after:font-tsm12-mono aria-[current=page]:after:text-base aria-[current=page]:after:content-['→'] motion-reduce:transition-none">Work<span class="ml-auto pl-2 font-tsm12-mono text-[11px] font-normal text-tsm12-yel group-hover/l:text-black">12</span></a></li>
<li><a href="#" class="group/l relative flex min-h-12 items-center border-b border-tsm12-line px-4 text-lg font-extrabold tracking-[0.04em] text-tsm12-navmut uppercase transition-colors duration-100 before:mr-2 before:font-tsm12-mono before:text-xs before:text-tsm12-navmut/60 before:content-['//'] hover:bg-tsm12-yel hover:text-black hover:before:text-black/60 focus-visible:bg-tsm12-yel focus-visible:text-black focus-visible:outline-none aria-[current=page]:border-tsm12-acc aria-[current=page]:bg-tsm12-acc aria-[current=page]:text-tsm12-paper aria-[current=page]:before:text-white/60 aria-[current=page]:after:ml-auto aria-[current=page]:after:font-tsm12-mono aria-[current=page]:after:text-base aria-[current=page]:after:content-['→'] motion-reduce:transition-none">Studio</a></li>
<li><a href="#" class="group/l relative flex min-h-12 items-center border-b border-tsm12-line px-4 text-lg font-extrabold tracking-[0.04em] text-tsm12-navmut uppercase transition-colors duration-100 before:mr-2 before:font-tsm12-mono before:text-xs before:text-tsm12-navmut/60 before:content-['//'] hover:bg-tsm12-yel hover:text-black hover:before:text-black/60 focus-visible:bg-tsm12-yel focus-visible:text-black focus-visible:outline-none aria-[current=page]:border-tsm12-acc aria-[current=page]:bg-tsm12-acc aria-[current=page]:text-tsm12-paper aria-[current=page]:before:text-white/60 aria-[current=page]:after:ml-auto aria-[current=page]:after:font-tsm12-mono aria-[current=page]:after:text-base aria-[current=page]:after:content-['→'] motion-reduce:transition-none">Journal<span class="ml-auto pl-2 font-tsm12-mono text-[11px] font-normal text-tsm12-yel group-hover/l:text-black">05</span></a></li>
<li><a href="#" class="group/l relative flex min-h-12 items-center border-b border-tsm12-line px-4 text-lg font-extrabold tracking-[0.04em] text-tsm12-navmut uppercase transition-colors duration-100 before:mr-2 before:font-tsm12-mono before:text-xs before:text-tsm12-navmut/60 before:content-['//'] hover:bg-tsm12-yel hover:text-black hover:before:text-black/60 focus-visible:bg-tsm12-yel focus-visible:text-black focus-visible:outline-none aria-[current=page]:border-tsm12-acc aria-[current=page]:bg-tsm12-acc aria-[current=page]:text-tsm12-paper aria-[current=page]:before:text-white/60 aria-[current=page]:after:ml-auto aria-[current=page]:after:font-tsm12-mono aria-[current=page]:after:text-base aria-[current=page]:after:content-['→'] motion-reduce:transition-none">Contact</a></li>
</ul>
<div class="border-t-[3px] border-tsm12-acc px-4 py-3">
<p class="mb-1 font-tsm12-mono text-[10px] tracking-[0.15em] text-tsm12-navmut">// USER</p>
<p class="text-sm font-extrabold tracking-[0.05em] uppercase">J. Haas</p>
</div>
</nav>
<div class="min-w-0 flex-1">
<div class="flex items-baseline gap-3 border-b-[3px] border-tsm12-ink px-6 py-4">
<span class="font-tsm12-mono text-xs text-tsm12-acc">[01]</span>
<h1 class="text-[clamp(28px,4vw,40px)] leading-none font-black tracking-[-0.01em] uppercase">Homepage</h1>
</div>
<div class="p-6">
<p class="mb-6 max-w-sm text-base leading-snug font-semibold text-tsm12-mut text-pretty">Raw borders, zero gradients, high-contrast type — and a thick red rule as the only decoration. Hover or Tab the menu.</p>
<div class="grid max-w-md grid-cols-2 border-[3px] border-tsm12-ink">
<div class="border-tsm12-ink p-4 odd:border-r-2 nth-[-n+2]:border-b-2"><p class="text-[clamp(26px,4vw,36px)] leading-none font-black tracking-[-0.03em]">24</p><p class="mt-1.5 font-tsm12-mono text-[11px] tracking-[0.1em] text-tsm12-mut uppercase">Projects</p></div>
<div class="border-tsm12-ink p-4 odd:border-r-2 nth-[-n+2]:border-b-2"><p class="text-[clamp(26px,4vw,36px)] leading-none font-black tracking-[-0.03em]">08</p><p class="mt-1.5 font-tsm12-mono text-[11px] tracking-[0.1em] text-tsm12-mut uppercase">Clients</p></div>
<div class="border-tsm12-ink p-4 odd:border-r-2 nth-[-n+2]:border-b-2"><p class="text-[clamp(26px,4vw,36px)] leading-none font-black tracking-[-0.03em]">6yr</p><p class="mt-1.5 font-tsm12-mono text-[11px] tracking-[0.1em] text-tsm12-mut uppercase">Experience</p></div>
<div class="border-tsm12-ink p-4 odd:border-r-2 nth-[-n+2]:border-b-2"><p class="text-[clamp(26px,4vw,36px)] leading-none font-black tracking-[-0.03em]">100%</p><p class="mt-1.5 font-tsm12-mono text-[11px] tracking-[0.1em] text-tsm12-mut uppercase">Remote</p></div>
</div>
</div>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tsm12-paper: #f5f0e8;
--color-tsm12-paper: oklch(0.957 0.012 79.8);
--color-tsm12-ink: #0a0a0a;
--color-tsm12-ink: oklch(0.145 0 0);
--color-tsm12-acc: #e63329;
--color-tsm12-acc: oklch(0.604 0.216 28.7);
--color-tsm12-yel: #f7e733;
--color-tsm12-yel: oklch(0.913 0.181 104);
--color-tsm12-line: #262626;
--color-tsm12-line: oklch(0.269 0 0);
--color-tsm12-navmut: #a8a8a8;
--color-tsm12-navmut: oklch(0.732 0 0);
--color-tsm12-mut: #3d3d3d;
--color-tsm12-mut: oklch(0.36 0 0);
--font-tsm12-head: 'Barlow Condensed', 'Arial Narrow', system-ui, sans-serif;
--font-tsm12-mono: 'Space Mono', ui-monospace, monospace;
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's utilities, so the
stage is sized before the browser build compiles. */
.tsm-12 {
width: 100%;
min-height: 100svh;
}
```How this works
Ornament is generated, state is semantic. The // prefix and → suffix are pseudo-elements, so the accessible name of each link is just its word. The arrow is gated on aria-current, not a class:
<a aria-current="page" class="… aria-[current=page]:bg-tsm12-acc
aria-[current=page]:after:ml-auto
aria-[current=page]:after:content-['→']">The stat grid draws its own rules. Inside a 3px-bordered box, odd:border-r-2 rules the left column and nth-[-n+2]:border-b-2 rules the first row — the internal cross appears without touching the outer edge.
Brutal but accessible. Hover and focus share one treatment (yellow slab, black ink), so the keyboard gets the same unmissable signal as the pointer.
Make it yours
- Newspaper brutalism: swap
--color-tsm12-accto yellow and--color-tsm12-yelto red. - Slab serif: replace Barlow Condensed with
Playfair Displayin--font-tsm12-headfor a different sub-genre. - Visible grid: add
bg-[repeating-linear-gradient(90deg,oklch(0_0_0/.05)_0_1px,transparent_1px_40px)]to the main area. - Hard shadow on the stage:
shadow-[8px_8px_0_var(--color-tsm12-ink)].
Gotchas — read before shipping
- Arbitrary
content-[…]values with spaces need underscores:content-['01_/']. - Pure black on pure white causes halation on OLED — the tokens use
#0a0a0aon#f5f0e8. - Condensed display fonts reflow when they load; keep
display=swapand a condensed fallback stack.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 111+ | 16.4+ | 128+ | 111+ |
Deliberately old-school CSS — borders, backgrounds, generated content; the floor is v4's own sheet.