Brutalism
Raw, confrontational web design with exposed structure, heavy borders, clashing colors, and intentionally broken conventions.
MCP
Code
/* ============================================================
BRUTALISM โ Raw Web Design Showcase
Hard borders, offset shadows, zero radius, clashing colors
============================================================ */
:root {
--black: #000000;
--white: #ffffff;
--yellow: #ffed00;
--blue: #0000ff;
--red: #ff0000;
/* Hard shadow โ zero blur, black offset */
--shadow-sm: 4px 4px 0 var(--black);
--shadow-md: 6px 6px 0 var(--black);
--shadow-lg: 8px 8px 0 var(--black);
--shadow-xl: 10px 10px 0 var(--black);
/* Typography */
--font-head: "Arial Black", "Impact", "Haettenschweiler", sans-serif;
--font-mono: "Courier New", "Courier", monospace;
--font-body: Arial, Helvetica, sans-serif;
/* Borders */
--border: 3px solid var(--black);
--border-thick: 4px solid var(--black);
}
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
html {
font-size: 16px;
}
body {
font-family: var(--font-body);
background-color: var(--yellow);
color: var(--black);
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
padding: 0 0 60px;
overflow-x: hidden;
}
/* โโ Header โโ */
.brut-header {
width: 100%;
max-width: 560px;
padding-top: 20px;
}
/* Scrolling tape strip */
.header-tape {
width: 100%;
background: var(--black);
color: var(--yellow);
font-family: var(--font-mono);
font-size: 0.72rem;
font-weight: 700;
letter-spacing: 1px;
padding: 6px 0;
white-space: nowrap;
overflow: hidden;
text-overflow: clip;
animation: tape-scroll 18s linear infinite;
}
@keyframes tape-scroll {
from {
text-indent: 0;
}
to {
text-indent: -600px;
}
}
.header-content {
display: flex;
align-items: center;
gap: 20px;
padding: 24px 24px 20px;
}
.header-mark {
width: 64px;
height: 64px;
background: var(--white);
border: var(--border-thick);
box-shadow: var(--shadow-md);
display: flex;
align-items: center;
justify-content: center;
font-family: var(--font-head);
font-size: 2.2rem;
color: var(--black);
flex-shrink: 0;
}
.header-title {
font-family: var(--font-head);
font-size: 3rem;
letter-spacing: -1px;
color: var(--black);
line-height: 1;
text-transform: uppercase;
}
.header-tagline {
font-family: var(--font-mono);
font-size: 0.72rem;
color: var(--black);
opacity: 0.7;
margin-top: 4px;
letter-spacing: 0.3px;
}
/* โโ Main layout โโ */
.page-main {
display: flex;
flex-direction: column;
gap: 28px;
width: 100%;
max-width: 560px;
padding: 0 24px;
}
/* โโ Cards โโ */
.brut-card {
background: var(--white);
border: var(--border-thick);
box-shadow: var(--shadow-lg);
transition: transform 0.12s ease, box-shadow 0.12s ease;
}
/* Slight rotations โ collage feel */
#card-profile {
transform: rotate(-0.8deg);
}
#card-buttons {
transform: rotate(0.5deg);
}
#card-input {
transform: rotate(-0.3deg);
}
#card-badges {
transform: rotate(0.7deg);
}
.brut-card:hover {
transform: rotate(0deg) translate(-3px, -3px) !important;
box-shadow: var(--shadow-xl);
}
.card-header-strip {
background: var(--black);
color: var(--yellow);
font-family: var(--font-mono);
font-size: 0.72rem;
font-weight: 700;
letter-spacing: 2px;
padding: 5px 14px;
text-transform: uppercase;
border-bottom: var(--border-thick);
}
.card-body {
padding: 20px 20px 18px;
}
/* โโ Profile Card โโ */
.profile-row {
display: flex;
align-items: center;
gap: 16px;
margin-bottom: 16px;
}
.avatar {
width: 72px;
height: 72px;
background: var(--yellow);
border: var(--border-thick);
box-shadow: var(--shadow-sm);
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
position: relative;
overflow: hidden;
}
.avatar-initials {
font-family: var(--font-head);
font-size: 1.5rem;
color: var(--black);
position: relative;
z-index: 1;
}
.avatar-noise {
position: absolute;
inset: 0;
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.08'/%3E%3C/svg%3E");
background-size: 100px 100px;
opacity: 0.15;
}
.profile-name {
font-family: var(--font-head);
font-size: 1.35rem;
letter-spacing: 0.5px;
color: var(--black);
line-height: 1.1;
text-transform: uppercase;
}
.profile-role {
font-family: var(--font-mono);
font-size: 0.76rem;
color: var(--black);
opacity: 0.65;
margin-top: 5px;
}
.profile-stats {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 0;
border: var(--border-thick);
}
.stat-box {
display: flex;
flex-direction: column;
align-items: center;
padding: 12px 8px;
border-right: var(--border);
background: var(--white);
}
.stat-box:last-child {
border-right: none;
}
.stat-box-yellow {
background: var(--yellow);
}
.stat-box-blue {
background: var(--blue);
}
.stat-box-blue .stat-value,
.stat-box-blue .stat-label {
color: var(--white);
}
.stat-value {
font-family: var(--font-head);
font-size: 1.5rem;
color: var(--black);
line-height: 1;
}
.stat-label {
font-family: var(--font-mono);
font-size: 0.58rem;
letter-spacing: 1.5px;
text-transform: uppercase;
color: var(--black);
opacity: 0.65;
margin-top: 3px;
}
/* โโ Buttons โโ */
.button-row {
display: flex;
gap: 12px;
flex-wrap: wrap;
}
.btn {
font-family: var(--font-head);
font-size: 0.95rem;
letter-spacing: 1px;
padding: 11px 20px;
border: var(--border-thick);
cursor: pointer;
text-transform: uppercase;
box-shadow: var(--shadow-md);
transition: transform 0.1s ease, box-shadow 0.1s ease;
outline: none;
position: relative;
}
.btn:hover {
transform: translate(-3px, -3px);
box-shadow: var(--shadow-xl);
}
.btn:active {
transform: translate(4px, 4px);
box-shadow: none;
}
.btn-black {
background: var(--black);
color: var(--white);
}
.btn-yellow {
background: var(--yellow);
color: var(--black);
}
.btn-ghost {
background: var(--white);
color: var(--black);
}
.btn:focus-visible {
outline: 3px solid var(--blue);
outline-offset: 2px;
}
/* โโ Input โโ */
.input-group {
display: flex;
flex-direction: column;
gap: 8px;
}
.input-label {
font-family: var(--font-mono);
font-size: 0.8rem;
font-weight: 700;
letter-spacing: 1.5px;
text-transform: uppercase;
color: var(--black);
}
.input-wrap {
display: flex;
align-items: center;
border: var(--border-thick);
box-shadow: var(--shadow-sm);
background: var(--white);
transition: box-shadow 0.12s ease;
}
.input-wrap:focus-within {
box-shadow: var(--shadow-md);
}
.input-prefix {
font-family: var(--font-mono);
font-size: 1.1rem;
font-weight: 700;
color: var(--black);
padding: 0 10px 0 14px;
flex-shrink: 0;
user-select: none;
}
.brut-input {
flex: 1;
background: transparent;
border: none;
padding: 12px 8px 12px 0;
font-family: var(--font-mono);
font-size: 0.9rem;
color: var(--black);
outline: none;
letter-spacing: 0.5px;
}
.brut-input::placeholder {
color: var(--black);
opacity: 0.35;
font-style: italic;
}
.input-cursor {
font-family: var(--font-mono);
font-size: 1rem;
font-weight: 700;
color: var(--black);
padding: 0 12px 0 4px;
animation: cursor-blink 1s step-end infinite;
flex-shrink: 0;
}
@keyframes cursor-blink {
0%,
100% {
opacity: 1;
}
50% {
opacity: 0;
}
}
/* Hide cursor when input has focus (text cursor is already there) */
.input-wrap:focus-within .input-cursor {
display: none;
}
/* โโ Badges โโ */
.badge-row {
display: flex;
flex-wrap: wrap;
gap: 8px;
}
.badge {
display: inline-flex;
align-items: center;
padding: 5px 10px;
border: var(--border);
font-family: var(--font-mono);
font-size: 0.68rem;
font-weight: 700;
letter-spacing: 1.5px;
text-transform: uppercase;
background: var(--white);
color: var(--black);
cursor: default;
user-select: none;
box-shadow: 2px 2px 0 var(--black);
transition: transform 0.1s ease, box-shadow 0.1s ease;
}
.badge:hover {
transform: translate(-2px, -2px);
box-shadow: 4px 4px 0 var(--black);
}
.badge-invert {
background: var(--black);
color: var(--white);
}
.badge-yellow {
background: var(--yellow);
color: var(--black);
}
.badge-blue {
background: var(--blue);
color: var(--white);
border-color: var(--blue);
}
/* โโ Responsive โโ */
@media (max-width: 520px) {
.brut-header {
max-width: 100%;
}
.page-main {
padding: 0 16px;
max-width: 100%;
}
.header-content {
padding: 16px 16px 14px;
gap: 12px;
}
.header-mark {
width: 48px;
height: 48px;
font-size: 1.6rem;
}
.header-title {
font-size: clamp(1.6rem, 8vw, 2.4rem);
word-break: break-all;
}
.header-tagline {
font-size: 0.65rem;
}
.button-row {
flex-direction: column;
}
.btn {
font-size: 0.85rem;
padding: 10px 16px;
}
.card-body {
padding: 14px 14px 12px;
}
.profile-row {
gap: 12px;
}
.avatar {
width: 56px;
height: 56px;
}
.avatar-initials {
font-size: 1.2rem;
}
.profile-name {
font-size: 1.1rem;
}
.stat-value {
font-size: 1.2rem;
}
.stat-label {
font-size: 0.52rem;
}
.stat-box {
padding: 10px 4px;
}
.badge {
font-size: 0.6rem;
padding: 4px 8px;
}
#card-profile,
#card-buttons,
#card-input,
#card-badges {
transform: rotate(0deg);
}
}
@media (max-width: 360px) {
.header-content {
flex-direction: column;
text-align: center;
gap: 8px;
}
.profile-stats {
grid-template-columns: 1fr 1fr 1fr;
}
}/* ============================================================
Brutalism โ Interactive Effects
Button shadow lift, badge color flip, tape glitch, cursor blink
============================================================ */
(function () {
"use strict";
// โโ Button: amplified hard-shadow lift on hover โโโโโโโโโโโโโ
// CSS handles hover already, but JS adds a satisfying "thud" on click
const buttons = document.querySelectorAll(".btn");
buttons.forEach((btn) => {
btn.addEventListener("click", function (e) {
// Flash white border briefly
btn.style.outline = "3px solid #0000FF";
btn.style.outlineOffset = "0px";
setTimeout(() => {
btn.style.outline = "";
btn.style.outlineOffset = "";
}, 250);
// Spawn a small "โ" confirmation text
const confirm = document.createElement("span");
confirm.textContent = "OK";
confirm.style.cssText = `
position: fixed;
left: ${e.clientX + 10}px;
top: ${e.clientY - 20}px;
font-family: 'Courier New', monospace;
font-size: 0.75rem;
font-weight: 700;
color: #000;
background: #FFED00;
border: 2px solid #000;
padding: 2px 6px;
pointer-events: none;
z-index: 9999;
animation: brut-pop 0.5s ease-out forwards;
`;
document.body.appendChild(confirm);
confirm.addEventListener("animationend", () => confirm.remove());
});
});
// Inject pop animation
const style = document.createElement("style");
style.textContent = `
@keyframes brut-pop {
0% { opacity: 1; transform: translateY(0) scale(1); }
100% { opacity: 0; transform: translateY(-20px) scale(0.8); }
}
`;
document.head.appendChild(style);
// โโ Badge: click to cycle through states โโโโโโโโโโโโโโโโโโโ
const badges = document.querySelectorAll(".badge");
const badgeCycles = [null, "badge-invert", "badge-yellow", "badge-blue"];
badges.forEach((badge) => {
let idx = badgeCycles.findIndex((cls) => cls && badge.classList.contains(cls));
if (idx === -1) idx = 0;
badge.addEventListener("click", () => {
badgeCycles.forEach((cls) => {
if (cls) badge.classList.remove(cls);
});
idx = (idx + 1) % badgeCycles.length;
if (badgeCycles[idx]) badge.classList.add(badgeCycles[idx]);
});
});
// โโ Header tape: pause on hover โโโโโโโโโโโโโโโโโโโโโโโโโโโโ
const tape = document.querySelector(".header-tape");
if (tape) {
tape.addEventListener("mouseenter", () => {
tape.style.animationPlayState = "paused";
tape.style.background = "#0000FF";
});
tape.addEventListener("mouseleave", () => {
tape.style.animationPlayState = "running";
tape.style.background = "#000";
});
}
// โโ Input: glitch effect on focus โโโโโโโโโโโโโโโโโโโโโโโโโโ
const input = document.getElementById("brut-input");
if (input) {
input.addEventListener("focus", () => {
const wrap = input.closest(".input-wrap");
if (!wrap) return;
let glitchCount = 0;
const colors = ["#FFED00", "#0000FF", "#FF0000", "#000"];
const interval = setInterval(() => {
wrap.style.boxShadow = `${4 + glitchCount}px ${4 + glitchCount}px 0 ${colors[glitchCount % colors.length]}`;
glitchCount++;
if (glitchCount >= colors.length) {
clearInterval(interval);
wrap.style.boxShadow = "";
}
}, 60);
});
}
// โโ Card: drag-to-wobble on mousedown โโโโโโโโโโโโโโโโโโโโโโ
const cards = document.querySelectorAll(".brut-card");
cards.forEach((card) => {
card.addEventListener("mousedown", (e) => {
const rect = card.getBoundingClientRect();
const cx = rect.left + rect.width / 2;
const isLeft = e.clientX < cx;
const deg = isLeft ? -2 : 2;
card.style.transition = "transform 0.08s ease";
card.style.transform = `rotate(${deg}deg) translate(-2px, -2px)`;
card.style.boxShadow = "10px 10px 0 #000";
});
card.addEventListener("mouseup", () => {
card.style.transition = "transform 0.2s ease, box-shadow 0.2s ease";
card.style.transform = "";
card.style.boxShadow = "";
});
card.addEventListener("mouseleave", () => {
card.style.transition = "transform 0.2s ease, box-shadow 0.2s ease";
card.style.transform = "";
card.style.boxShadow = "";
});
});
})();<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>BRUTALISM โ Raw Web Design</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<!-- Header -->
<header class="brut-header">
<div class="header-tape" aria-hidden="true">โ
RAW โ
EXPOSED โ
UNFILTERED โ
RAW โ
EXPOSED โ
UNFILTERED โ
RAW โ
EXPOSED โ
UNFILTERED โ
RAW โ
</div>
<div class="header-content">
<div class="header-mark" aria-hidden="true">B</div>
<div>
<h1 class="header-title">BRUTALISM</h1>
<p class="header-tagline">// Raw, confrontational web design โ since forever //</p>
</div>
</div>
</header>
<!-- Main -->
<main class="page-main">
<!-- Profile Card -->
<div class="brut-card profile-card" id="card-profile">
<div class="card-header-strip">PROFILE.EXE</div>
<div class="card-body">
<div class="profile-row">
<div class="avatar">
<span class="avatar-initials">JD</span>
<div class="avatar-noise" aria-hidden="true"></div>
</div>
<div class="profile-info">
<h2 class="profile-name">JAKE DรRNER</h2>
<p class="profile-role">/* LEAD DISRUPTOR */</p>
</div>
</div>
<div class="profile-stats">
<div class="stat-box stat-box-yellow">
<span class="stat-value">248</span>
<span class="stat-label">PROJECTS</span>
</div>
<div class="stat-box">
<span class="stat-value">14K</span>
<span class="stat-label">FOLLOWERS</span>
</div>
<div class="stat-box stat-box-blue">
<span class="stat-value">96%</span>
<span class="stat-label">RATING</span>
</div>
</div>
</div>
</div>
<!-- Buttons -->
<div class="brut-card buttons-card" id="card-buttons">
<div class="card-header-strip">CONTROLS.EXE</div>
<div class="card-body">
<div class="button-row">
<button class="btn btn-black" id="btn-primary">
โถ EXECUTE
</button>
<button class="btn btn-yellow" id="btn-secondary">
โก ACTIVATE
</button>
<button class="btn btn-ghost" id="btn-ghost">
โก INSPECT
</button>
</div>
</div>
</div>
<!-- Input -->
<div class="brut-card input-card" id="card-input">
<div class="card-header-strip">INPUT.EXE</div>
<div class="card-body">
<div class="input-group">
<label class="input-label" for="brut-input">QUERY_STRING:</label>
<div class="input-wrap">
<span class="input-prefix">></span>
<input class="brut-input" id="brut-input" type="text" placeholder="type something rawโฆ" />
<span class="input-cursor" aria-hidden="true">_</span>
</div>
</div>
</div>
</div>
<!-- Badges -->
<div class="brut-card badges-card" id="card-badges">
<div class="card-header-strip">TAGS.EXE</div>
<div class="card-body">
<div class="badge-row">
<span class="badge badge-invert">ANTI-DESIGN</span>
<span class="badge badge-yellow">BOLD</span>
<span class="badge">RAW</span>
<span class="badge badge-blue">EXPOSED</span>
<span class="badge">MONOSPACE</span>
<span class="badge badge-invert">BORDERS</span>
</div>
</div>
</div>
</main>
<script src="script.js"></script>
</body>
</html>Brutalism
Web brutalism draws its name from the architectural movement of the 1950sโ70s โ raw concrete, exposed structure, nothing hidden. Applied to digital design, brutalism is a deliberate rejection of the smooth, polished, user-friendly conventions that have come to dominate web aesthetics. Where most modern UI softens every edge and apologizes for every interaction, brutalism confronts the user directly: thick black borders, hard offset shadows, unrounded corners, clashing high-contrast colors, and type that shouts rather than whispers.
The aesthetic began as a protest against sterile corporate design systems but has become its own genre โ embraced by artists, magazines, music labels, and tech companies that want to communicate irreverence and confidence. A brutalist site declares: this is a tool, this is real, this is not trying to seduce you.
The technical signature is the โhard shadowโ โ a box-shadow with zero blur and a direct pixel offset in black, creating a crisp duplicate border that gives the illusion of a stacked physical object. Combined with zero border-radius, this produces the defining brutalist card. Hover animations amplify the effect: the object โliftsโ by translating up-left while the shadow grows larger, like a label peeling off a surface.
Key characteristics
- Zero border-radius everywhere โ perfectly rectangular forms only
- Hard offset shadows:
box-shadow: 6px 6px 0 #000โ zero blur, pure black - Thick borders:
border: 3px solid #000or4px - Palette: black, white, shocking yellow (
#FFED00), electric blue (#0000FF) - Typography mixes monospace,
Arial Black, andImpactfor maximum rawness - Slight CSS rotations on cards create a collage / pin-board aesthetic
- Hover lifts element while shadow grows (translate + shadow expansion)
When to use
- Music labels, zines, and arts organizations that want an anti-establishment feel
- Developer tools and CLI-adjacent products that embrace the โrawโ aesthetic
- Portfolios that aim to be memorable and polarizing rather than safe
- Protest sites, independent media, and countercultural brands