Reusable patterns
Build once, use across projects with consistent spacing.
Read more →Production-ready patterns built with emilyCSS utility classes. Copy the HTML directly into your project — no imports, no runtime.
Success, warning, error, and info variants. All use accessible colour pairings from generated OKLCH token scales. Add role="alert" for live announcements.
Changes saved
Your configuration has been updated.
Review needed
Check your scan paths before publishing.
Build failed
Something went wrong during the build step.
Info
emilyCSS works best when config is kept simple.
<div class="flex gap-3 rounded border-l-4 border-success-80 bg-success-10 p-4"
role="alert">
<p class="text-sm font-semibold text-success-90">Changes saved</p>
<p class="text-sm text-success-70">Your configuration has been updated.</p>
</div>Compact status indicators using tinted colour scales. Works with any token colour — brand, accent, success, warning, error, or neutral.
<span class="inline-flex items-center rounded-full
bg-brand-10 px-3 py-1
text-xs font-semibold text-brand-90">
Brand
</span>Label, input, hint, and error state. Works with any input type. Error uses aria-invalid and aria-describedby for screen reader compatibility.
We'll only use this for account notifications.
<!-- Text input with hint -->
<div class="flex flex-col gap-1.5">
<label for="email" class="text-sm font-medium text-neutral-80">
Email address
</label>
<p class="text-xs text-neutral-50">We'll only use this for notifications.</p>
<input id="email" type="email" placeholder="andy@example.com"
class="rounded border border-neutral-30 px-4 py-2.5 text-sm
focus-visible:ring-2 w-full" />
</div>
<!-- Error state -->
<div class="flex flex-col gap-1.5">
<label for="postcode" class="text-sm font-medium text-neutral-80">Postcode</label>
<input id="postcode" type="text" aria-invalid="true"
aria-describedby="postcode-error"
class="rounded border-2 border-error-80 px-4 py-2.5 text-sm
focus-visible:ring-2 w-full" />
<span id="postcode-error" class="text-xs font-medium text-error-80">
Enter a real postcode
</span>
</div>Flexible container with border, padding, shadow, and optional badge. Works as article, div, or section.
Build once, use across projects with consistent spacing.
Read more →Focus states and contrast built into every generated class.
Learn more →Works wherever CSS loads. No runtime, no build lock-in.
See setup →<article class="rounded-lg border border-neutral-20 p-6 shadow-sm">
<span class="inline-flex items-center rounded-full
bg-brand-10 px-3 py-1 text-xs font-semibold text-brand-90 mb-4">
New
</span>
<h3 class="mb-2 text-base font-semibold text-neutral-90">Card title</h3>
<p class="text-sm text-neutral-60 mb-4">Supporting description text.</p>
<a href="#" class="text-sm font-semibold text-brand-80">Read more →</a>
</article>Responsive data table with striped header, row borders, and badge status cells. Wrap in overflow-x-auto for mobile.
| Component | Classes | Status |
|---|---|---|
| Button | bg, text, px, py, hover | Pass |
| Alert | border-l-4, bg, text | Pass |
| Form | border, ring, focus-visible | Check |
<div class="overflow-x-auto rounded-lg border border-neutral-20">
<table class="w-full border-collapse text-sm">
<thead>
<tr class="bg-neutral-10 border-b border-neutral-20">
<th class="text-left px-4 py-3 font-semibold text-neutral-80">Column</th>
<th class="text-left px-4 py-3 font-semibold text-neutral-80">Column</th>
</tr>
</thead>
<tbody>
<tr class="border-b border-neutral-10">
<td class="px-4 py-3 text-neutral-80">Cell</td>
<td class="px-4 py-3 text-neutral-60">Cell</td>
</tr>
</tbody>
</table>
</div>Previous/next links and numbered pages. Active page uses brand colour. Add aria-current="page" to the current item.
<nav aria-label="Pagination" class="flex gap-2">
<a href="#" class="inline-flex items-center justify-center rounded
border border-neutral-30 px-3 py-2 text-sm
hover:bg-neutral-10">
Previous
</a>
<a href="#" aria-current="page"
class="inline-flex items-center justify-center rounded
bg-brand-80 px-3 py-2 text-sm font-semibold text-white">
1
</a>
<a href="#" class="inline-flex items-center justify-center rounded
border border-neutral-30 px-3 py-2 text-sm
hover:bg-neutral-10">
Next
</a>
</nav>Tab bar with active underline indicator. Use role="tablist" and role="tab" for full keyboard and screen reader support.
<div role="tablist" aria-label="Section tabs" class="flex gap-1 border-b border-neutral-20">
<!-- Active tab -->
<button role="tab" aria-selected="true"
class="px-4 py-2.5 text-sm font-semibold text-brand-80
border-b-2 border-brand-80 -mb-px
focus-visible:ring-2">
Overview
</button>
<!-- Inactive tab -->
<button role="tab" aria-selected="false"
class="px-4 py-2.5 text-sm text-neutral-60 hover:text-neutral-80
border-b-2 border-transparent -mb-px
focus-visible:ring-2">
Usage
</button>
</div>Collapsible section using native HTML details/summary. No JavaScript required. Screen readers announce open/closed state automatically.
A config-driven CSS utility system. Define tokens once, generate utilities, ship anywhere CSS loads.
No. You run the build once locally. The output is a static CSS file you link with a tag — no runtime required.
Yes. Link the generated CSS in your Nuxt config or import it in your app entry. The utility classes work identically in any framework.
<details class="rounded-lg border border-neutral-20 overflow-hidden">
<summary class="cursor-pointer px-5 py-4 text-sm font-semibold text-neutral-80
hover:bg-neutral-10 list-none flex items-center justify-between">
Accordion heading
<span aria-hidden="true" class="text-neutral-40">+</span>
</summary>
<p class="border-t border-neutral-10 px-5 py-4 text-sm text-neutral-60">
Accordion body content.
</p>
</details>Visual progress indicator. Use the native progress element for proper accessibility, or provide role="progressbar" with aria-valuenow/min/max.
<div class="flex items-center justify-between mb-2">
<span class="text-sm font-medium text-neutral-80">Label</span>
<span class="text-sm font-semibold text-brand-80">75%</span>
</div>
<div class="h-3 rounded-full bg-neutral-20 overflow-hidden"
role="progressbar"
aria-valuenow="75" aria-valuemin="0" aria-valuemax="100"
aria-label="Progress label">
<div class="h-full rounded-full bg-brand-80 transition"
style="width: 75%">
</div>
</div>