Blanksheet: A Principled CSS Reset
Blanksheet is a CSS reset built on five explicit principles; every rule traces back to one. Five principles classify every UA default on every element into exactly one category: reset it, keep it, skip it, set it, or normalize it. No property falls through the cracks, and no two principles compete for the same decision. The result is a reset you can audit against its own rules, and argue with on precise terms.
The five principles
Principle 1: Eliminate implicit layout
Zero every non-zero spatial property (margin, padding, vertical-align) so that all spacing in the final layout is fully under your control.
Media elements (<img>, <svg>, <video>, etc.) get vertical-align: bottom rather than display: block to close the baseline gap. Both work, but display: block breaks inline <svg> icons inside buttons and links.
Principle 2: Preserve text semantics
The test is scoped to a specific property on a specific element: does it carry semantic meaning that would be lost if reset? Remove font-weight: bold from <strong> and it looks identical to plain text. That’s semantic, so it stays. Same logic keeps font-style: italic on <em>, text-decoration on <a> and <del>, font-family: monospace on <code>, background-color on <mark>, and so on.
Heading font-size is the key exclusion. The semantic hierarchy lives in the HTML tag (<h1> through <h6>), not in the UA’s 2em–0.67em scale. Every project defines its own type scale, so the UA value is universally replaced (→ P3). Heading font-weight: bold, by contrast, visually signals importance and stays.
Principle 3: Skip what developers always override
If no realistic production scenario keeps the UA default, resetting it is dead code; developers will override the reset anyway. Blanksheet simply skips it.
Property-level. Heading font-size, border on form controls / <fieldset> / <hr> / <iframe> / <dialog>, background on form controls and <dialog>, ::backdrop background. None of these UA values survive into production.
Element-level. <meter>, <progress>, and specialized inputs (date, time, datetime-local, month, week, color, range). In practice, projects always replace these entirely with custom design systems. Resetting properties on elements that won’t ship in their native form is dead code at a larger scale.
Worth noting: border is classified as a visual property (P3, not P1). border-width does occupy space, but developers override border for visual reasons, not spatial ones. Treating it as spatial would blur P1’s scope without meaningful benefit.
Principle 4: Apply real-world universal defaults
Conventions so broadly shared that omitting them creates universal boilerplate. The bar is high: must be correct for the vast majority of production projects, not merely convenient.
box-sizing: border-boxvia*,*::before,*::afterlist-style: noneon<ul>,<ol>,<menu>border-collapse: collapseon<table>font: inherit; color: inheriton form controls, fixing the UA inheritance breakappearance: textfieldon<input type="number">(spinners virtually always replaced)list-style: noneon<summary>(disclosure triangle virtually always replaced)
P4 actively sets a value to a convention that real-world projects have collectively settled on.
Principle 5: Normalize cross-browser inconsistencies
P5 is the catch-all for browser disagreements, applied only when browsers diverge on rendering the same element.
<sub>/<sup>: normalize positioning to prevent line-height disruption across engines[type="search"]: WebKit’s non-standardappearancenormalized totextfieldbutton::-moz-focus-inner: Firefox’s extra innerpadding/borderremovedtext-size-adjust: 100%: prevents mobile Safari text inflation::placeholderopacity: Firefox’s reduced opacity normalized to1:-moz-ui-invalid: Firefox’s redbox-shadowon invalid elements removed
P4 and P5 differ in scope: P4 applies when all browsers agree on a default that developers universally replace. P5 applies when browsers disagree on how to render the same element.
Where principles meet
One element, three principles
<h1>: margin is implicit layout, P1 resets it. font-weight: bold conveys importance, P2 preserves it. font-size: 2em is universally overridden, P3 skips it.
One declaration, two reasons
[type="search"] and [type="number"] share appearance: textfield for different reasons. [type="search"] is P5: WebKit’s non-standard appearance. [type="number"] is P4: all browsers agree on spinners, but they’re virtually always replaced. The principle system operates at the property-on-element level, not the declaration level.
What Blanksheet never does
No opinions: no cursor: pointer, no font-smoothing, no scroll-behavior: smooth. A reset subtracts UA defaults; it never adds behavior. And no !important — Blanksheet ships inside @layer reset, so any unlayered style wins automatically.
Every line has a reason
The source is annotated with [Principle N] references on every section, so every decision is traceable. If you think a rule doesn’t match its principle, or if you disagree with the principle itself, I’d genuinely love to hear about it. That’s the whole point of making the reasoning explicit.