Fylgja Accordion

An accordion is a set of stacked sections that each expand and collapse. Built on the native <details> and <summary> elements, it is keyboard accessible and toggleable without any JavaScript. Adding a shared name attribute turns the group into an exclusive accordion where opening one section closes the rest.

Preview

What is Fylgja?

A lightweight, classless-friendly CSS library built on modern standards.

Does it require a build step?

No. Fylgja works buildless straight from a CDN, or with your bundler.

Is it accessible?

Yes. It builds on native elements, so semantics and keyboard support come for free.

<div class="divide-y" style="border-color: color-mix(in oklab, var(--root-bg) 75%, var(--root-fg))">
	<details name="demo-accordion" class="flow-none" open>
		<summary class="list-none flex align" style="--py: 0.75rem">
			<span>What is Fylgja?</span>
			<svg class="toggle-rotate transition flex-none" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m6 9 6 6 6-6"/></svg>
		</summary>
		<p style="--py: 0 0.75rem">A lightweight, classless-friendly CSS library built on modern standards.</p>
	</details>
	<details name="demo-accordion" class="flow-none">
		<summary class="list-none flex align" style="--py: 0.75rem">
			<span>Does it require a build step?</span>
			<svg class="toggle-rotate transition flex-none" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m6 9 6 6 6-6"/></svg>
		</summary>
		<p style="--py: 0 0.75rem">No. Fylgja works buildless straight from a CDN, or with your bundler.</p>
	</details>
	<details name="demo-accordion" class="flow-none">
		<summary class="list-none flex align" style="--py: 0.75rem">
			<span>Is it accessible?</span>
			<svg class="toggle-rotate transition flex-none" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m6 9 6 6 6-6"/></svg>
		</summary>
		<p style="--py: 0 0.75rem">Yes. It builds on native elements, so semantics and keyboard support come for free.</p>
	</details>
</div>

Usage

Each section is a <details> with a <summary> as its label, and its content follows the summary. Give every <details> in the group the same name to make it an exclusive accordion, or omit name to let multiple sections stay open at once. Add open to the section that should start expanded.

Fylgja keeps the bare <details> deliberately plain, so the accordion look comes entirely from Fylgja utilities, with no custom CSS:

  • divide-y on the wrapper draws a divider between each section. Give it a theme-aware color from Fylgja tokens, e.g. style="border-color: color-mix(in oklab, var(--root-bg) 75%, var(--root-fg))".
  • flow-none on each <details> clears the default margins from its summary and content so the padding stays even.
  • list-none on the summary hides the default disclosure triangle.
  • flex align on the summary pushes the label and chevron to opposite ends and centers them; flex-none keeps the chevron from shrinking.
  • toggle-rotate transition on the chevron flips it when the section opens.
  • --py sets the vertical padding: style="--py: 0.75rem" on the summary and style="--py: 0 0.75rem" on the content.

Anatomy

Part Responsibility
<details> One collapsible section. Tracks its own open state.
<summary> The always-visible label and toggle. Focusable and keyboard-operable.
name Shared across sections to enforce single-open (exclusive) behavior.
.divide-y + .toggle-rotate Fylgja utilities that add the dividers and the rotating chevron.

Accessibility

  • <summary> is focusable and toggles on Enter or Space by default.
  • Open state is exposed to assistive technology natively; no aria-expanded wiring is required.
  • Keep the summary text meaningful on its own, since it acts as the section label.

FAQ

How do I make only one section open at a time?

Give every <details> in the group the same name attribute. The browser then treats them as an exclusive accordion and closes the others when one opens, with no JavaScript.

Do I need JavaScript for the open and close animation?

No. Modern browsers can animate the disclosure with CSS using interpolate-size and transitions on the details element, so the toggle stays entirely native.