sveltelean Primitives
Versionv0.2.0 GitHub

Example

Subscription
Plan
Team
Seats
12 of 20
Renews
Billing contacts
Ada Byron
Grace Murray
Region
Frankfurt
<dl data-slean="descriptions" data-slean-columns="3">
	<div>
		<dt>Plan</dt>
		<dd>Team</dd>
	</div>
	<div>
		<dt>Seats</dt>
		<dd>12 of 20</dd>
	</div>
	<div>
		<dt>Renews</dt>
		<dd><time datetime="2026-10-28">28 October 2026</time></dd>
	</div>
	<div>
		<dt>Billing contacts</dt>
		<dd>Ada Byron</dd>
		<dd>Grace Murray</dd>
	</div>
	<div>
		<dt>Region</dt>
		<dd>Frankfurt</dd>
	</div>
</dl>
Tier 0: at most three columns, each at least 14rem wide, so a narrow window shows one. Resize the window to see the columns change; no media query is involved. Everything here works with page JavaScript disabled.

Why this implementation exists

A page of settings, an order summary or a profile is a set of names and values. HTML has an element for exactly that: <dl> with <dt> for the name and <dd> for the value, which screen readers announce as terms and definitions. HTML also allows a <div> around each pair, which gives the stylesheet one grid cell per pair.

descriptions.css lays the pairs out with repeat(auto-fill, minmax(…)): as many columns as fit, each at least 14rem wide, capped by data-slean-columns. The cap is arithmetic on the width, so the layout responds to the width of the list itself, not of the window, without a media or container query.

The browser owns

  • the description list and its term and definition roles
  • grouping a term with its values, several values per term
  • the grid tracks that fill the width

Svelte Lean owns

  • descriptions.css: the responsive grid, the column cap, the inline layout, the outline cells
  • the contract: one <div> per pair, values as phrasing content
  • documentation

Usage

The markup needs no package. Install @svelte-lean/styles for the stylesheet; @svelte-lean/primitives adds the typed contract and nothing at runtime.

npm install @svelte-lean/styles
stylesheets
import '@svelte-lean/styles/descriptions.css';

Wrap every <dt> and its <dd> in a <div>. A term with several values has several <dd> in the same group.

Set data-slean-columns to the most columns the content reads well in; leave it out to fill the width. data-slean-layout="inline" suits a single column of short values, such as a settings summary.

Values are text or phrasing content: a <time datetime>, a link, a badge. An editable form is not a description list; use fields.

Anatomy

PartElementdata-slean-partRequiredNotes
root<dl data-slean="descriptions">–yesdata-slean-columns="1|2|3|4", data-slean-layout="stacked|inline", data-variant="outline".
group<div>–yesOne per pair: a <dt> followed by one or more <dd>. One grid cell.
term<dt>–yesThe label, in the muted color and the small text size.
definition<dd>–yesThe value: text, a <time>, a link, a badge. Several stack in order.

Runtime profile

Tier 0: the descriptions have no behavior module, the Vite plugin maps descriptions to no module, and the page ships no Svelte Lean JavaScript for them.

Accessibility contract

  • A <dl>: screen readers announce the list and each term with its values.
  • The <div> groups are allowed inside <dl> and are ignored by the accessibility tree.
  • The grid follows reading order, row by row, so the visual order and the reading order agree.
  • Name the list with a heading before it, or aria-labelledby on the <dl>, when a page has several.

Keyboard

KeyWhenResult
Tablinks inside valuesMoves between them (native); the list is not focusable

Platform features

FeatureBaselineOutside the target
<dl> with <div> groupsWidely availableNot applicable
Grid with min() and max() tracksBaseline 2020Not applicable

Without JavaScript

Fully functional: the list and its layout are markup and CSS.

Server rendering

Static markup; the server renders the values.

Before hydration

Nothing is attached; the list reads the same before and after hydration.

Styling

descriptions.css sets the responsive grid, the column cap, the inline layout, the label and value text and the outline cells. The tokens it reads:

TokenDefault (light)Applies to
--slean-space-41remgap, column-gap, padding-inline
--slean-space-61.5remgap, grid-template-columns
--slean-fgvar(--slean-neutral-12)color
--slean-text-md1remfont-size
--slean-leading1.5line-height
--slean-fg-mutedvar(--slean-neutral-11)color
--slean-text-sm0.875remfont-size
--slean-space-30.75rempadding-block
--slean-bordervar(--slean-neutral-6)border

Variant attributes: data-slean-columns (1, 2, 3, 4); data-slean-layout (inline); data-variant (outline).

Compatibility notes

Grid tracks with min() and max() are Baseline 2020, widely available, and <div> groups inside <dl> are valid HTML in every current browser.

Examples

Inline layout and outline cells

data-slean-layout="inline" puts each label beside its value, two fifths and three fifths of the cell, so labels line up down a column. data-variant="outline" draws every group as a cell whose borders overlap its neighbours'. With data-slean-columns="1" the result reads like a two-column table while staying a description list.

Repository
svelte-lean
Default branch
main
Last deploy
inline, outline
<dl
	data-slean="descriptions"
	data-slean-columns="1"
	data-slean-layout="inline"
	data-variant="outline"
>
	<div>
		<dt>Repository</dt>
		<dd><a href="/primitives/descriptions">svelte-lean</a></dd>
	</div>
	<div>
		<dt>Default branch</dt>
		<dd>main</dd>
	</div>
	<div>
		<dt>Last deploy</dt>
		<dd><time datetime="2026-09-28T09:12">28 September, 09:12</time></dd>
	</div>
</dl>

Testing

Source