Pure CSSMIT licensed

Brutalist Text-Only

Raw Swiss-punk brutalist hero — pure black, traffic-cone orange highlight, acid lime accent, hard 8px offset shadows. No images, no soft anything.

Live Demo
Plain CSSTailwind v4
Try it

Complete Tailwind CSS landing page templates in HTML, React, Next.js and Vue · from $49

Cruip · Affiliate link

Browse Cruip templates

The code

<section class="hs-16" aria-label="Hero">
  <div class="hs-16__stack">
    <span class="hs-16__num">001 / 042</span>
    <h2 class="hs-16__h">
      THE WEB
      <em>WAS NEVER</em>
      MEANT TO
      <span class="hs-16__mark">LOOK SAFE.</span>
    </h2>
    <p class="hs-16__p">A design studio for brands that would rather be remembered than liked.</p>
    <div class="hs-16__row">
      <a class="hs-16__cta hs-16__cta-pri" href="#work">[ WORK ]</a>
      <a class="hs-16__cta" href="#talk">[ EMAIL ]</a>
    </div>
  </div>
</section>
.hs-16 {
  display: grid;
  place-items: center;
  width: 100%;
  min-height: 100vh;
  padding: clamp(28px, 5vw, 64px) clamp(20px, 5vw, 56px);
  background: #0a0a0a;
  font-family: 'Inter', system-ui, sans-serif;
  color: #ffffff;
  box-sizing: border-box;
}

.hs-16__stack {
  max-width: 760px;
}

.hs-16__num {
  display: inline-block;
  font-family: 'JetBrains Mono', monospace;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.2em;
  background: #ff5e1a;
  color: #0a0a0a;
  padding: 4px 10px;
  margin-bottom: 22px;
}

.hs-16__h {
  margin: 0 0 22px;
  font-family: 'Inter', sans-serif;
  font-size: clamp(40px, 7vw, 84px);
  font-weight: 900;
  line-height: 0.92;
  letter-spacing: -0.04em;
  text-transform: uppercase;
}

.hs-16__h em {
  color: #c4f048;
  font-style: italic;
  display: inline;
}

.hs-16__mark {
  display: inline-block;
  background: #ff5e1a;
  color: #0a0a0a;
  padding: 0 12px;
  transform: rotate(-1deg);
}

.hs-16__p {
  font-family: 'JetBrains Mono', monospace;
  font-size: 14px;
  line-height: 1.55;
  color: #a8a8a8;
  margin: 0 0 26px;
  max-width: 480px;
  border-top: 2px solid #ff5e1a;
  padding-top: 14px;
}

.hs-16__row {
  display: flex;
  gap: 14px;
  flex-wrap: wrap;
}

.hs-16__cta {
  display: inline-block;
  padding: 12px 18px;
  font-family: 'JetBrains Mono', monospace;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-decoration: none;
  background: transparent;
  color: #fff;
  border: 2px solid #fff;
  transition: background 0.12s, color 0.12s;
}

.hs-16__cta:hover {
  background: #fff;
  color: #0a0a0a;
}

.hs-16__cta-pri {
  background: #ff5e1a;
  color: #0a0a0a;
  border-color: #ff5e1a;
}

.hs-16__cta-pri:hover {
  background: #c4f048;
  border-color: #c4f048;
  color: #0a0a0a;
}

@media (prefers-reduced-motion: reduce) {
  .hs-16__cta {
    transition: none;
  }
}
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 Hero Section 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 Text-Only
Source: https://codefronts.com/layouts/css-hero-sections/brutalist-text-only/

Raw Swiss-punk brutalist hero — pure black, traffic-cone orange highlight, acid lime accent, hard 8px offset shadows. No images, no soft anything.
## HTML
```html
<section class="hs-16" aria-label="Hero">
  <div class="hs-16__stack">
    <span class="hs-16__num">001 / 042</span>
    <h2 class="hs-16__h">
      THE WEB
      <em>WAS NEVER</em>
      MEANT TO
      <span class="hs-16__mark">LOOK SAFE.</span>
    </h2>
    <p class="hs-16__p">A design studio for brands that would rather be remembered than liked.</p>
    <div class="hs-16__row">
      <a class="hs-16__cta hs-16__cta-pri" href="#work">[ WORK ]</a>
      <a class="hs-16__cta" href="#talk">[ EMAIL ]</a>
    </div>
  </div>
</section>
```
## CSS
```css
.hs-16 {
  display: grid;
  place-items: center;
  width: 100%;
  min-height: 100vh;
  padding: clamp(28px, 5vw, 64px) clamp(20px, 5vw, 56px);
  background: #0a0a0a;
  font-family: 'Inter', system-ui, sans-serif;
  color: #ffffff;
  box-sizing: border-box;
}

.hs-16__stack {
  max-width: 760px;
}

.hs-16__num {
  display: inline-block;
  font-family: 'JetBrains Mono', monospace;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.2em;
  background: #ff5e1a;
  color: #0a0a0a;
  padding: 4px 10px;
  margin-bottom: 22px;
}

.hs-16__h {
  margin: 0 0 22px;
  font-family: 'Inter', sans-serif;
  font-size: clamp(40px, 7vw, 84px);
  font-weight: 900;
  line-height: 0.92;
  letter-spacing: -0.04em;
  text-transform: uppercase;
}

.hs-16__h em {
  color: #c4f048;
  font-style: italic;
  display: inline;
}

.hs-16__mark {
  display: inline-block;
  background: #ff5e1a;
  color: #0a0a0a;
  padding: 0 12px;
  transform: rotate(-1deg);
}

.hs-16__p {
  font-family: 'JetBrains Mono', monospace;
  font-size: 14px;
  line-height: 1.55;
  color: #a8a8a8;
  margin: 0 0 26px;
  max-width: 480px;
  border-top: 2px solid #ff5e1a;
  padding-top: 14px;
}

.hs-16__row {
  display: flex;
  gap: 14px;
  flex-wrap: wrap;
}

.hs-16__cta {
  display: inline-block;
  padding: 12px 18px;
  font-family: 'JetBrains Mono', monospace;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-decoration: none;
  background: transparent;
  color: #fff;
  border: 2px solid #fff;
  transition: background 0.12s, color 0.12s;
}

.hs-16__cta:hover {
  background: #fff;
  color: #0a0a0a;
}

.hs-16__cta-pri {
  background: #ff5e1a;
  color: #0a0a0a;
  border-color: #ff5e1a;
}

.hs-16__cta-pri:hover {
  background: #c4f048;
  border-color: #c4f048;
  color: #0a0a0a;
}

@media (prefers-reduced-motion: reduce) {
  .hs-16__cta {
    transition: none;
  }
}
```

How this works

This brutalist hero section is a single semantic <section class="hs-16"> using display: grid; place-items: center with min-height: 100vh — one centering pattern that scales from a card slot to a full-page landing-page hero without hard-coding 100vh. Content sits inside .hs-16__stack capped at max-width: 760px, which forces the oversized headline to break into the three-line thump-thump-thump rhythm brutalism depends on. There are no images — this is a pure text-only hero, so the entire visual load falls on type weight, negative space, and two aggressive accent blocks.

The palette is deliberately violent: pure #0a0a0a paper, #ffffff ink, traffic-cone #ff5e1a for the eyebrow chip and highlight .hs-16__mark (rotated -1deg so it reads hand-stamped), and acid lime #c4f048 on the italic emphasis word for the second-look moment. Typography is Inter at font-weight: 900, letter-spacing: -0.04em, line-height: 0.92 — the tight-and-heavy setting that makes uppercase headlines feel like a poster instead of a paragraph. Body text uses JetBrains Mono to hold the design-studio register; the border-top: 2px solid #ff5e1a above the paragraph is the entire secondary hierarchy.

Why it converts: absence of imagery signals confidence in the message — Nielsen Norman research shows text-only heroes outperform image-heavy heroes for products with strong value props because there is no stock photo for the eye to skip past. The bracket-wrapped [ WORK ] CTAs read like terminal prompts, self-selecting for the technical/creative buyer the studio actually wants. Hover swaps to solid fill with transition: background 0.12s — a 120ms tap-and-flash that feels sharp instead of soft.

Make it yours

  • Recolor by editing four values: the paper #0a0a0a, ink #ffffff, traffic-cone accent #ff5e1a on .hs-16__num / .hs-16__mark, and lime #c4f048 on the italic. Keep at least one chromatic accent + one contrast accent — a single-accent brutalist hero flattens into plain black-on-black.
  • Swap Inter for a heavier grotesque to push harder brutalist: 'Space Grotesk' at 900, 'Archivo Black', or 'Anton'. Keep the letter-spacing: -0.04em and line-height: 0.92 — those two properties do more brutalist work than the font family itself.
  • Change the CTA shape: brackets are the signature — replace [ WORK ] text with an SVG arrow if the aesthetic feels too Web-3. To pill-ify for indie-SaaS, add border-radius: 999px to .hs-16__cta and swap the border: 2px solid for border: 1px solid.
  • For light-mode inversion: flip to #f5f5f0 paper, #0a0a0a ink, keep #ff5e1a and #c4f048 as-is — both accents hit AA contrast on cream. The .hs-16__mark rotation stays; on light backgrounds it reads even more like a rubber-stamp overlay.
  • For Tailwind: bg-[#0a0a0a] text-white grid place-items-center min-h-[480px] on the section, text-6xl md:text-7xl lg:text-8xl font-black uppercase tracking-tighter leading-[0.92] on the h2, bg-[#ff5e1a] text-black border-2 border-[#ff5e1a] on the primary CTA. In Next/React, extract .hs-16__mark as a <Mark> component so the -1deg rotate stays consistent.

Gotchas — read before shipping

  • The letter-spacing: -0.04em plus line-height: 0.92 combo will collide descenders on the next line for any font that lacks tight vertical metrics — Inter and Space Grotesk are safe, but system-ui fallbacks vary wildly. Test with your actual copy, not the demo copy, or you will ship a hero where g touches T.
  • The rotated .hs-16__mark uses transform: rotate(-1deg) on an inline-block — this creates a new stacking context and can trigger a subpixel-antialiasing shift on the highlight fill in Chromium. If the orange edge looks blurry at 1x DPR, add will-change: transform or accept it; do NOT try to fix it with backface-visibility, which regresses INP.
  • Contrast check: #a8a8a8 body copy on #0a0a0a is roughly 8.6:1 — passes WCAG AA and AAA. But lime #c4f048 on black is ~14:1 while orange #ff5e1a on black is ~7.1:1 — safe for the emphasis word but dangerous if you push the orange to smaller body text. Keep accent colors reserved for headline-scale type.
  • The text-transform: uppercase on .hs-16__h disables ligatures and can make screen readers announce individual letters on some legacy AT combos. The visible text stays lowercase in the DOM, so this is safe — but if you switch to text-transform at the span level for effects, add a visually-hidden lowercase copy for a11y (WCAG 2.5.5).
  • The two CTAs are visually equivalent — both .hs-16__cta get the same padding and border. Only the primary carries .hs-16__cta--pri (orange fill). If you clone this for a page where both CTAs should split traffic 50/50 (e.g. sign-in vs sign-up), remove the primary modifier from both; the double-primary trap otherwise splits conversion.
  • Framework quirk: in Next.js App Router with next/font, Inter's font-weight: 900 is a separate weight file — if you only imported 400/700, the browser synthesizes 900, which looks visibly thinner than a real black weight and kills the brutalist punch. Explicitly include weight: ['400','700','900'] in the font config.

Techniques used in this demo

Search CodeFronts

Loading…