
Brutalism is the one look whose specification is already written: it is the browser's own default stylesheet, held on purpose. At a 16px root, the CSS sample stylesheet sets h1 at 2em with 0.67em margins, h2 at 1.5em with 0.83em, h3 at 1.17em, h4 at 1em, h5 at 0.83em and h6 at 0.67em. That resolves to 32, 24, 19, 16, 13 and 11 pixels, which is a modular ladder somebody designed in the nineties and nobody has improved.
Links are #0000EE unvisited and #551A8B visited in Chrome, Firefox and Safari. On white those measure 9.40:1 and 11.01:1. The defaults were never illegible. They were only ever unfashionable.
most AI developed stuff is just so insanely soulless crap I can instantly tell and instinctively close the tab
A developer on Hacker News
Brutalism is the direct answer to that complaint, and it is worth saying why before the values: a page that hides nothing cannot look like it was assembled by something with no opinion. The call, up front: the style is a list of refusals, and refusals have to be stated as rules or a model will quietly override every one. That is what the Thanor library writes down.
What the style refuses, as rules#
Brutalism on the web attached itself to the term through Pascal Deville's brutalistwebsites.com, and it has stayed coherent because the discipline is subtractive. These are prohibitions, and each one has to be named explicitly because each one is a default somewhere:
border-radius: 0on every element. No exceptions for avatars or buttons.- No
filter: blur(), nobackdrop-filter, no frosted anything. - No gradient of any kind, including as an image overlay.
- No blurred
box-shadow. Offset shadows with0blur are permitted. - No web font unless it is the point of the page. System stacks otherwise.
- No
opacitybelow1on text, ever. If it should be quieter, change the colour. - No centred body copy. Everything ranges left, including headings.
- Links are underlined and buttons look like buttons, so that nothing has to be hovered to be discovered.
- Content is readable at
320pxwide with no horizontal scroll.
The last two are the pair that separates brutalism from carelessness. A page can be raw and still be completely navigable, and that combination is the actual craft in the style. A brutalist page is hostile to decoration, not to the reader.
Three type stacks, and you pick exactly one for the whole site:
- Grotesque:
-apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif - Document:
"Times New Roman", Times, serif - Terminal:
ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace
Because none of those load a font file, the whole page can render in one round trip, which is the performance argument the style has always made for itself.
The scale, a perfect fifth#
Ratio 1.5 from 20px. Two steps and the size has more than doubled, which is the point: brutalist hierarchy is a shout followed by a whisper, with nothing in between to soften the transition.
| Step | Size | Line height | Weight | Used for |
|---|---|---|---|---|
| -1 | 13px | 20px | 400 | meta, footnotes, nav |
| 0 | 20px | 32px | 400 | body copy |
| 1 | 30px | 36px | 700 | h3 |
| 2 | 45px | 48px | 700 | h2 |
| 3 | 68px | 68px | 700 | h1 |
| 4 | 101px | 96px | 700 | the one headline per page |
Two weights, 400 and 700, and the jump between them is part of the hierarchy rather than a decoration on top of it. Tracking stays at 0 everywhere, including on the 101px step, because optically corrected letterfit is a refinement and refinement is the thing being refused.
- Line height at step 4 is
96px, which is less than the font size. Negative leading is legitimate here and it is the strongest available signal that a human set the type. - Body copy measure:
min(100% - 32px, 72ch). Wider than editorial on purpose. text-transform: uppercaseon step -1 only, with0.08emtracking, which is the one tracking value in the system.- No step between
0and1. The empty band from20pxto30pxis where a generated page puts four sizes, and removing it is most of the look.
Five colours, four of them defaults#
| Role | Hex | Contrast on white | Where it goes |
|---|---|---|---|
| Ground | #FFFFFF | the page | |
| Ink | #000000 | 21:1 | all type, all borders |
| Link | #0000EE | 9.40:1 | unvisited links |
| Visited | #551A8B | 11.01:1 | visited links, and yes, keep it |
| Alarm | #FF3B00 | 3.57:1 | fills and rules only, never body text |
Four of those five are values the browser already ships, and using them is the single most legible statement the style makes. Keeping the visited colour is the test of whether you mean it. Almost every site in the last fifteen years has removed it, which is why a page that keeps it feels like a document rather than a product.
The alarm colour sits at 3.57:1, which fails the 4.5:1 threshold for body text and clears 3:1 for large text and graphical objects. So it is a fill behind black type, a 2px rule, or type at step 3 and above. Write that restriction into the spec, because an unguided model will happily set a caption in it and the caption will be the one thing on the page nobody can read.

Borders, shadows and the sixteen pixel grid#
The spacing unit is 16px, coarse on purpose, and the ladder is 16, 32, 48, 64, 96, 128. There is no 8px and no 4px. A style built on undisguised structure cannot also do fine adjustment, and the coarseness is what makes the alignment visible from across a room.
- Border:
2px solid #000000. One weight for every border on the site, including inputs, cards, images and the page frame. - Shadow:
6px 6px 0 #000000. No blur, no alpha. Applied to buttons and raised blocks only, and the offset does not change on hover. - Grid:
display: grid,gap: 0. Each cell takes a2pxborder, withmargin-right: -2pxandmargin-bottom: -2pxso adjacent borders collapse into one line rather than doubling to4px. - Section padding:
64pxtop and bottom on desktop,48pxon tablet,32pxon a phone, with a2pxrule between sections instead of a colour change. - Page gutter:
16px. Flat, not fluid. The text touching close to the edge is a feature. - Images:
2pxborder, no radius, no shadow, and a visiblealttext fallback rather than a grey placeholder box. - Inputs:
2pxborder,48pxtall,0radius, and a focus state that swaps the border to the alarm colour rather than adding a ring.
The collapsed border is the detail that separates a brutalist grid from a page of divs with borders on them. Double borders at every internal join are the default outcome and they read as a mistake, which in a style with no decoration to distract you is the only thing left to look at.
Motion, and the order of a page#
transition: none. Every state change lands in one frame. Hover on a link inverts it to white on #000000 with no fade, hover on a button moves nothing, and focus draws a 2px solid outline at 2px offset in the alarm colour.
If you want the change to read as deliberately mechanical rather than merely instant, there is one permitted alternative: transition: background-color 80ms steps(2, end). Two discrete frames, so the change is visible without being eased. That is the only easing value in the system and cubic-bezier does not appear anywhere.
The sequence, which is shorter than a marketing page because half the sections a marketing page has are decoration:
- Name and one line, step 4 and step 0, at the top of the document with no hero image and no viewport height trick.
- The thing itself, immediately: the product, the list, the demo. No preamble section.
- Plain facts, as a bordered table. Tables are honest and brutalism likes them.
- Contact, as a real mailto link in
#0000EE, not a form. - A footer that is a list of links, underlined, unstyled, in the default colours, with the page's own byte weight printed at the end of it if you want the performance claim on the record.
Proof and testimonials are omitted entirely. A style whose argument is that nothing is hidden cannot then arrange social pressure, and a brutalist page with a five star review carousel has broken its own premise more thoroughly than a rounded corner ever could.
The verdict on brutalism as a spec#
Brutalism is the cheapest of these looks to specify and the easiest to get wrong, because every single value in it is something a model will overwrite from its defaults. Ask for brutalism unprompted and you get rounded cards, a soft grey background, a blurred shadow, Inter, and a 300ms fade on nine sections, which is the house style wearing a black border.
So the prompt carries prohibitions, not adjectives. Those nine refusals are the specification, and they work because a prohibition is checkable: search the stylesheet for border-radius, blur, gradient and cubic-bezier, and any hit means the brief was not followed. Ten seconds, which is more than can be said for most design feedback.
The set, complete:
1.5from20px, six steps, two weights,0tracking.16pxunit,2pxborders,0radius,6px 6px 0shadows with no blur.#FFFFFF,#000000,#0000EE,#551A8B,#FF3B00, with the alarm colour restricted to fills and large type.transition: none, or80ms steps(2, end), and nothing else.- Five sections, no proof section, links underlined and visited links visible.
Every prompt in the Thanor library carries its refusals as explicit rules rather than hoping the model infers them, which is the difference between a brutalist page and a soft page with a hard font. For the other end of the same discipline, the editorial specification is as strict and far more readable, and the awwwards style recipe spends the decoration budget instead of refusing it. Then browse the Thanor library.
Questions this raises
What actually defines brutalist web design?
Undisguised structure. Visible borders, no rounded corners, no blur, no gradients, system typefaces, default link colours, and interactions that happen instantly rather than easing. Every one of those is a value you can write down.
What are the default browser link colours?
Unvisited links are #0000EE and visited links are #551A8B in Chrome, Firefox and Safari. On white they measure 9.40:1 and 11.01:1, which is why the defaults were never a legibility problem.
What type scale works for brutalism?
A perfect fifth, ratio 1.5, from 20px. That gives 13, 20, 30, 45, 68 and 101 pixels. Two steps and the size has more than doubled, which is the violent hierarchy the look depends on.
What is the brutalist shadow?
A hard offset with no blur and no transparency, 6px 6px 0 #000000. A blurred shadow simulates depth that is not there, and simulating is the one thing the style refuses.
Should a brutalist site have animation?
No easing. Set transition to none and let state changes land in a single frame, or use steps(2, end) at 80ms if you want the change to read as mechanical rather than instant.
Can a model build this without being told the values?
No. Asked for brutalism a model produces rounded cards and a soft gradient, because those are its defaults. The Thanor library is available now and its prompts name the borders, the scale and the zero duration outright.
Part of
The expensive look
What makes a site read as expensive, written as values rather than adjectives: the type scale, the spacing, the curve and its duration, and the order the sections run in.
