Base

Styles for native HTML elements, one file per element or element family, all in @layer base.

@layer base styles native HTML elements so that unstyled markup already looks right. There is no class to apply: write <table>, <blockquote> or <input type="date"> and they are styled.

Every value comes from a custom property resolved by @uncinq/design-tokens and @uncinq/component-tokens. This package hardcodes almost nothing, so restyling is a matter of changing a token, not overriding a rule.

css/base.css imports all 23 files below.

Typography and text

FileSelectors
base/body.cssbody: background, text color, font family, size, weight, line-height
base/headings.cssh1 to h6: color, font family, weight, letter-spacing, line-height, margin, plus a per-level size from --font-size-heading-01 to -06
base/typography.cssp: block spacing and --max-width-paragraph
base/link.cssa: color, underline offset, thickness and color, hover transition, focus-visible outline
base/blockquote.cssblockquote, blockquote cite: inline-start border, italic, muted cite block
base/list.cssul, ol, li in prose context, including nested list indentation
base/code.csscode, kbd, samp, pre, and inline code outside pre styled separately from block code
base/address.cssaddress: removes the UA italic and resets inner paragraph spacing
base/abbr.cssabbr[title]: dotted underline with its own offset and thickness
base/sup.csssup: raised without growing the line box, see the note below

Media and embedded content

FileSelectors
base/figure.cssfigure, figcaption, and nested picture, img, .credit. Flex column layout with responsive caption direction
base/picture.csspicture: inline-block
base/video.cssvideo: fluid width, auto height
base/table.csstable, thead, tbody, th, td: collapsed borders, cell padding, header weight, no border on the last row
base/details.cssdetails, summary, details[open], the summary::after marker and the disclosed panel

Forms

Six of these seven files are largely inspired by KNACSS.

FileSelectors
base/form.csslabel, legend, and input excluding button, reset, submit, checkbox, radio and range. Adds per-type handling for search, number, date, time, datetime-local and file, including the ::file-selector-button
base/form-checkbox.css[type='checkbox'] when it is not a switch, plus its adjacent label
base/form-radio.css[type='radio'] plus its adjacent label
base/form-range.css[type='range'], the .range wrapper, .range-value output, and the WebKit and Gecko track and thumb pseudo-elements
base/form-select.cssselect and optgroup, with a token-driven chevron background image
base/form-switch.css[role="switch"], rendered as a track and knob
base/form-textarea.csstextarea, including field-sizing: content and a --textarea-min-height default of 5lh

Text-like controls (input, textarea, select, checkbox, radio) draw their outline with box-shadow: inset and border: 0, so that focus and hover states change color without shifting layout by a pixel. The switch and the range thumb are the exceptions: both need a real border, since their outline is part of a shape that moves.

Every hover style in this layer is guarded by @media (hover: hover) and (pointer: fine), so nothing sticks on touch. Transitions are guarded by @media (prefers-reduced-motion: no-preference).

Accessibility helpers

base/accessibility.css is the only file in this layer that ships classes rather than element selectors.

ClassBehaviour
.visually-hiddenHidden visually, still exposed to assistive technology
.visually-hidden-focusableThe same, but revealed on :focus or :focus-within. Intended for skip links
<button>
  <svg aria-hidden="true">...</svg>
  <span class="visually-hidden">Close</span>
</button>

Do not use these to hide decorative content. Decorative content should be removed from the accessibility tree with aria-hidden="true" instead, which is the opposite trade-off.

Why sup zeroes its line-height

The user agent default, vertical-align: super, raises the glyph inside the line box, so the line box grows. A block containing a <sup> then becomes taller than one without it.

Zeroing line-height takes the superscript out of the line box calculation, and relative positioning raises it without affecting layout. A label carrying a required marker then measures exactly like a label without one, and two fields side by side stay aligned.

Overriding

Redefine the token rather than the rule:

@layer base {
  :root {
    --table-cell-padding-block: 0.5rem;
  }
}

Several files read a component-scoped property with a semantic fallback, for example var(--code-font-family, var(--font-family-code)). That gives you two levels: change the component token to affect only that element, or the semantic token to affect everything that inherits from it.