Reseter.css reference
Contents
- Universal border-box and zero spacing
- Root line height and system font
- No mobile text inflation
- Block-level main
- Heading sizes and logical margins
- Balanced heading wraps
- Paragraph spacing
- Anchor scroll offset
- Transparent link backgrounds
- Skip-ink on default links
- Dotted abbreviation underlines
- Monospace sizing
- Subscript and superscript offsets
- Inherited control typography
- Borders on text fields
- Button padding
- Pointer cursor on enabled buttons
- Vertical textarea resize
- Placeholder contrast
- List indentation
- Unstyled semantic lists
- Responsive media
- Icon fill from current color
- Open dialog layout
- Table color and indent
- Hide closed dialogs
- The hidden attribute
- Frameless iframes
- Collapsed table borders
Universal border-box and zero spacing
User agents size boxes from the content edge, and they add margin and padding that differ by element and browser. This rule switches every element, and both pseudos, to border-box, so width and height include padding and border, and it clears that spacing so layout starts from the same empty box. Ships in the full build and in mini.
*,
*::before,
*::after {
box-sizing: border-box;
padding: 0;
margin: 0;
}
Root line height and system font
Body text inherits line height and font from the root, and those defaults differ between engines. The root sets a 1.5 line height and a system UI stack, including color emoji fonts, so unread text matches the platform. Full build only.
:where(:root) {
line-height: 1.5;
font-family: system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
}
No mobile text inflation
Mobile browsers enlarge text they consider too small, which changes a layout that set its own type size. text-size-adjust: none, with the WebKit and Firefox prefixes, keeps the font size you wrote. Full build only.
:where(html) {
-webkit-text-size-adjust: none;
-moz-text-size-adjust: none;
text-size-adjust: none;
}
Block-level main
Older browsers left main as inline, so it sat in the line and its margins did not behave like a section. display: block makes it a normal block container. Full build only.
:where(main) {
display: block;
}
Heading sizes and logical margins
User-agent heading margins use physical margin-top and margin-bottom, so the rhythm breaks in a vertical writing mode. These rules restore the classic size ladder with logical margin-block and zero inline margin. Mini ships this same ladder, and also sets font-weight: normal and line-height: 1.5 on h1–h6.
:where(h1) {
font-size: 2em;
margin-block: 0.67em;
margin-inline: 0;
}
:where(h2) {
font-size: 1.5em;
margin-block: 0.83em;
margin-inline: 0;
}
:where(h3) {
font-size: 1.17em;
margin-block: 1em;
margin-inline: 0;
}
:where(h4) {
margin-block: 1.33em;
margin-inline: 0;
}
:where(h5) {
font-size: 0.83em;
margin-block: 1.67em;
margin-inline: 0;
}
:where(h6) {
font-size: 0.67em;
margin-block: 2.33em;
margin-inline: 0;
}
Balanced heading wraps
A long heading can wrap so the last line holds one short word. text-wrap: balance on h1–h4 evens the line lengths. Ships in the full build and in mini.
:where(h1, h2, h3, h4) {
text-wrap: balance;
}
Paragraph spacing
The universal spacing reset removes the gap between paragraphs. Adjacent paragraphs (p + p) get 1rem of block-start margin, so body copy still separates, and a paragraph after a heading stays tight to that heading. Full build only.
:where(p + p) {
margin-block-start: 1rem;
}
Anchor scroll offset
A fragment link scrolls the :target flush with the top of the viewport, where a sticky header covers it. scroll-margin-block: 5ex leaves room above the target. Full build only.
:where(:target) {
scroll-margin-block: 5ex;
}
Transparent link backgrounds
Some engines paint a background behind links. Clearing background-color keeps the link text on the page background. Full build only.
:where(a) {
background-color: transparent;
}
Skip-ink on default links
Underlines run through descenders such as g, y, and p. text-decoration-skip-ink: auto on links that have no class opens a gap at those letters. Links with a class keep the underline the component draws. Full build only.
:where(a:not([class])) {
text-decoration-skip-ink: auto;
}
Dotted abbreviation underlines
An abbr with a title has an expansion, and engines disagree on whether they show that. A dotted underline is the cue. Full build only.
:where(abbr[title]) {
text-decoration: underline dotted;
}
Monospace sizing
WebKit and others shrink code, kbd, samp, and pre below 1em in some parents. Pinning a monospace family and font-size: 1em keeps inline code the same size as the surrounding text. Full build only.
:where(code, kbd, samp, pre) {
font-family: monospace, monospace;
font-size: 1em;
}
Subscript and superscript offsets
Default sub and sup enlarge the line box. A 75% font size, zero line-height, and a relative offset keep the line height of the parent steady. Full build only.
:where(sub, sup) {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
:where(sub) {
bottom: -0.25em;
}
:where(sup) {
top: -0.5em;
}
Inherited control typography
Form controls use the browser’s own font. font: inherit and line-height: inherit on buttons, inputs, selects, and textareas make them match the surrounding type. Full build only.
:where(button, input, optgroup, select, textarea) {
font: inherit;
line-height: inherit;
}
Borders on text fields
Browsers give text fields different default borders. Text-like inputs and textareas get a consistent 1px border in currentColor. Button, checkbox, color, file, hidden, image, radio, range, reset, and submit inputs are excluded so native chrome is unchanged. Full build only.
:where(
input:not([type="button"]):not([type="checkbox"]):not([type="color"]):not(
[type="file"]
):not([type="hidden"]):not([type="image"]):not([type="radio"]):not(
[type="range"]
):not([type="reset"]):not([type="submit"]),
textarea
) {
border: 1px solid currentColor;
}
Vertical textarea resize
The default resize handle lets a textarea grow sideways and overflow the layout. resize: vertical keeps the handle and limits growth to the vertical direction. Full build only.
:where(textarea) {
overflow: auto;
resize: vertical;
vertical-align: top;
}
Placeholder contrast
Placeholder text is often a fixed gray that disappears on a dark field. Inheriting the field color at opacity: 0.5 keeps the hint visible and tied to the text color. The selector is ::placeholder itself, so :where() does not lower its specificity. Full build only.
::placeholder {
color: inherit;
opacity: 0.5;
}
List indentation
Clearing padding on every element also removes the space that holds list markers. ul, ol, and menu get padding-inline-start: 40px so markers stay visible in either writing direction (#382). Ships in the full build and in mini.
:where(ul, ol, menu) {
padding-inline-start: 40px;
}
Unstyled semantic lists
Navigation and toolbars often use a list with role="list" and should render the items in a line of controls. Those lists drop the marker and the indent. Ships in the full build and in mini.
:where(ul[role="list"], ol[role="list"]) {
list-style: none;
padding-inline-start: 0;
}
Responsive media
img, picture, video, canvas, and svg are inline by default and can spill out of a narrow parent. They become blocks, cap their inline size at 100%, and the replaced elements keep block-size: auto so the aspect ratio holds (#389). Ships in the full build and in mini.
:where(img, picture, video, canvas, svg) {
display: block;
max-inline-size: 100%;
}
:where(img, video, canvas, svg) {
block-size: auto;
}
Icon fill from current color
An inline SVG ignores the text color when it has no fill. SVGs without a fill attribute use currentColor, so icons follow the surrounding color. Full build only.
:where(svg:not([fill])) {
fill: currentColor;
}
Open dialog layout
An open dialog is sized and colored differently across engines. This rule centers it, paints it with Canvas and CanvasText, and fits the box to its content. A closed dialog is hidden by the unlayered rule below. Full build only.
:where(dialog) {
background-color: Canvas;
border: solid;
color: CanvasText;
display: block;
block-size: fit-content;
inline-size: fit-content;
inset-inline: 0;
margin: auto;
padding: 1em;
}
Table color and indent
A table can inherit a text indent from an ancestor, and its border color may stay on the user-agent default. text-indent: 0 and border-color: inherit follow the surrounding text. Full build only. Mini collapses table borders in its own rule, further down.
:where(table) {
text-indent: 0;
border-color: inherit;
}
Hide closed dialogs
A dialog without the open attribute has to stay off screen. This rule sets display: none on that state. It lives outside @layer reset, so an unlayered author style is what overrides it, and a rule inside the reset layer cannot reveal a closed dialog. Full build only.
:where(dialog):not([open]) {
display: none;
}
Frameless iframes
Browsers draw a border around iframe. Mini removes it. Mini only.
:where(iframe) {
border: 0;
}
Collapsed table borders
Separate table borders leave a gap between cells. Mini collapses the borders and clears the spacing. Mini only.
:where(table) {
border-collapse: collapse;
border-spacing: 0;
}