v1.0.0  ·  MIT License  ·  ~5 KB gzipped

A CSS reset for
editorial layouts.

Not a framework. Not a component library. One file of honest defaults for type-first, reading-first interfaces.

Box model
Type scale
Design tokens
Headings
Editorial utilities
Lists
Links
Media & figures
Tables
Forms
Code & kbd
Horizontal rules
Print styles

Everything you need.
Nothing you don't.

Hairline covers every element an editorial page actually uses — with sensible, considered defaults that hold up in production.

§ 00 Design tokens CSS custom properties for type scale, spacing, measure, leading, tracking, ink/surface colors, radius, and motion. All overridable.
§ 01 Box model Universal border-box, zeroed margins, and min-width: 0 to prevent size inflation in flex/grid children.
§ 02 Document & body Serif body font stack, antialiasing, text rendering, and full prefers-reduced-motion compliance.
§ 03 Typography text-wrap: balance on headings, text-wrap: pretty on paragraphs. Form fields inherit the document font.
§ 04 Headings Weight-400 h1–h6 with tight leading and negative tracking. Hierarchy through size, not weight. Includes [data-kicker] eyebrow labels.
§ 05 Body copy Lede, dropcap, pullquote, measure constraint. Inline: strong, em, mark, abbr, sub, sup, oldstyle & tabular figures.
§ 06 Lists Disc, decimal, nested lists. [role="list"] bare reset. Definition lists for glossaries.
§ 07 Links Accent color, offset underlines, skip-ink. Auto-appended ↗ for target="_blank". Visited + focus-visible states.
§ 08 Media & figures Block display, aspect-ratio preservation, object-fit. figure + figcaption styled.
§ 09 Tables Collapsed borders, muted small-caps headers, hairline row dividers, zebra striping, tabular-nums.
§ 10 Forms Normalised fields, custom select arrow, smooth focus rings, accessible buttons. Disabled states.
§ 12 Code Inline code, pre blocks, and kbd key lift — JetBrains Mono stack.
§ 13 Horizontal rules Plain hairline, ornament [data-ornament], and labelled [data-label] divider.
§ 14 Utilities .sr-only, .measure, .lede, .pullquote, .capo, .smallcaps, .muted.
§ 15 Print Clean black output, expanded link URLs, orphan/widow control, no page breaks inside blocks.

See it rendered.

Every element below is built from hairline's defaults — the CSS powering this page is hairline.css plus layout-only overrides.

Platform engineering

The seam between
design and code

Notes from a decade of sitting on both sides. Where a senior engineer learns to stay close to the work, and why that matters more than the title.

Structure matters more than syntax. Most arguments about code style are really arguments about structure in disguise — and knowing where to put the energy changes everything about how a system ages over time.

Being senior isn't about volume — of opinions, slides, or output. It's about precision.

Text can carry strong emphasis, editorial italics, highlighted passages, API abbreviations, inline code, keyboard shortcuts like ⌘K, and footnote1 superscripts.

5xl · 3.58rThe seam.
4xl · 2.99rStructure over syntax.
3xl · 2.49rBetween design and engineering.
xl · 1.73rNotes from a decade in the seam.
base · 1rThe interesting work happens where two things don't quite fit.
sm · .83rCaptions, metadata, footnotes — secondary rhythm.
xs · .69rKICKER · LABEL · EYEBROW

Override anything.

Every value is a CSS custom property. Set your brand color in two lines. The cascade handles the rest.

@import "hairline.css";

:root {
  /* override only what you need */
  --color-accent: hsl(340 80% 50%);
  --measure:      70ch;
  --leading-normal: 1.7;
}
--color-inkhsl(220 20% 10%)
--color-ink-mutedhsl(220 12% 42%)
--color-ink-hairlinehsl(220 10% 88%)
--color-surfacehsl(0 0% 99%)
--color-surface-althsl(220 14% 97%)
--color-accenthsl(220 80% 48%)

One file. No build step.

Download and link it. That's the whole install.

curl -O https://raw.githubusercontent.com/nsimona/hairline/main/hairline.css
<link rel="stylesheet" href="hairline.css">

No npm. No PostCSS. No config file.
Download hairline.css · Read the README · Browse examples

Opinionated about
the right things.

The premise

A CSS reset should make your HTML beautiful without a single extra class.

Most resets strip away browser defaults and leave you with nothing. Hairline strips the bad defaults and replaces them with good ones — a considered serif stack, balanced headings, readable measure, and honest typographic hierarchy that works out of the box for any editorial page.

Why serif?

Editorial type belongs in serif.

The stack (Iowan Old Style → Palatino → Georgia) reads beautifully at long-form length. Layer your own font-family on top for product UI — that's two lines of CSS.

Why weight-400 headings?

Bold headings fight the text.

Light headings create hierarchy through size alone — a considered, magazine-like rhythm that doesn't shout.

Why min-width: 0?

The silent cause of a hundred layout bugs.

Without it, flex and grid children overflow when content is wide. This one line prevents it on every element, globally.

Why 65ch measure?

Research-backed reading width.

Comfortable reading sits between 45–75 characters. 65ch is the sweet spot. Change it via --measure in a single line.