Home / Snippets / Typography /

Code block with header

Dark-themed code block with a language label bar, decorative dots, line numbers, and token colouring — pure CSS.

CSS
1/* Custom property definition */
2:root {
3 --accent: oklch(0.72 0.19 265);
4 --bg: oklch(0.13 0.02 260);
5}
6
7.card {
8 background: var(--bg);
9 color: var(--accent);
10}
Widely Supported
typographyno-js

Quick implementation

/* HTML:
<div class="cbh-wrap">
  <div class="cbh-header">
    <div class="cbh-dots">
      <span class="cbh-dot"></span>
      <span class="cbh-dot"></span>
      <span class="cbh-dot"></span>
    </div>
    <span class="cbh-lang">CSS</span>
  </div>
  <pre class="cbh-body"><code>...</code></pre>
</div> */

.cbh-wrap {
  border-radius: 0.75rem;
  overflow: hidden;
  border: 1px solid oklch(0.28 0.02 260);
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.82rem;
}

.cbh-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.5rem 1rem;
  background: oklch(0.17 0.02 260);
  border-bottom: 1px solid oklch(0.28 0.02 260);
}

.cbh-lang {
  font-size: 0.75rem;
  font-weight: 500;
  color: oklch(0.72 0.19 265);
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.cbh-dots {
  display: flex;
  gap: 0.375rem;
}

.cbh-dot {
  width: 0.625rem;
  height: 0.625rem;
  border-radius: 50%;
  background: oklch(0.35 0.02 260);
}

.cbh-body {
  background: oklch(0.13 0.02 260);
  padding: 1.25rem 1rem 1.25rem 0;
  overflow-x: auto;
  counter-reset: line;
  margin: 0;
}

.cbh-line {
  display: flex;
  align-items: baseline;
}

.cbh-line-num {
  display: inline-block;
  width: 2.5rem;
  text-align: right;
  padding-right: 1.25rem;
  color: oklch(0.38 0.02 260);
  user-select: none;
  flex-shrink: 0;
}

.cbh-line-text {
  color: oklch(0.88 0.03 260);
  white-space: pre;
}

/* Syntax token colours */
.cbh-kw   { color: oklch(0.72 0.19 265); } /* keywords / selectors */
.cbh-val  { color: oklch(0.78 0.14 160); } /* values / strings */
.cbh-com  { color: oklch(0.48 0.02 260); font-style: italic; } /* comments */
.cbh-prop { color: oklch(0.80 0.08 200); } /* properties */

Prompt this to your LLM

Includes role, constraints, two framework variants, and edge cases to handle.

You are a senior frontend engineer building documentation UI components.

Goal: A styled code block with a header bar showing a language label and decorative traffic-light dots, line numbers column, and syntax token colour classes. Dark theme using oklch() colors. No JavaScript required for display.

Technical constraints:
- Structure: outer wrapper with overflow: hidden and border-radius, a header div, and a pre/code body.
- Header: flex row with space-between — dots on the left, language label on the right.
- Language label: uppercase, letter-spaced, accent-coloured.
- Line numbers: a separate span per line with fixed width, right-aligned, user-select: none so they are excluded from clipboard copies.
- Use display: flex on each line row so line number and code text stay baseline-aligned.
- Token colours must all use oklch() — at least 4 distinct hues for keyword, value, property, comment.
- white-space: pre on line text to preserve indentation without a full pre element per line.
- overflow-x: auto on the body to handle long lines without breaking layout.

Framework variant (pick one):
A) Vanilla HTML + CSS — static markup, suitable for server-rendered documentation.
B) React component — accepts language (string), code (string), and showLineNumbers (boolean) props; splits code by newline and renders line rows automatically.

Edge cases to handle:
- Empty lines: must still render a line number row with consistent height.
- Very long tokens: overflow-x scrolls the code body, not the entire page.
- Copy from code: line numbers must be excluded (user-select: none); code text should be selectable.
- High-contrast mode: ensure token colours pass at least 4.5:1 contrast on the dark background.

Return HTML + CSS.

Why this matters in 2026

Developer-facing products, documentation sites, and technical blogs all need a code block that communicates "this is real code" at a glance. The header bar with a language label sets context before the reader processes a single character. Line numbers let you reference specific lines in prose or discussion. Combined, these details shift a plain <pre> element from utilitarian to intentional — and all of it is achievable with CSS alone, no syntax-highlighting library required for the structural chrome.

The logic

The outer wrapper uses overflow: hidden with border-radius to clip the header and body into a single rounded unit. The header is a flex row with justify-content: space-between, placing dots on one side and the label on the other. Each line of code is its own flex row containing a fixed-width line-number span and a text span with white-space: pre to preserve indentation. Token colouring is achieved with wrapper spans and dedicated colour classes — lightweight and easy to generate server-side or with a syntax tokeniser. The user-select: none on line numbers means copying a code region excludes the gutter numbers.

Accessibility & performance

The code block carries no ARIA roles because <pre><code> already signals pre-formatted computer code to screen readers. Line numbers use user-select: none and aria-hidden where needed to prevent them being announced or included in copied text. All token colours are chosen with at least 4.5:1 contrast against the dark background (oklch(0.13 0.02 260)), meeting WCAG AA for normal text. Horizontal scrolling is scoped to the code body via overflow-x: auto, so the page layout never shifts — wide code snippets cannot break the surrounding grid.