@sparkstone/css

A lightweight SCSS framework in the spirit of Pico.css, rebuilt on oklch() relative color syntax. Give it one base color and it derives an entire light and dark palette that clears WCAG AA on every pairing the framework uses.

Quickstart · All components · npm · GitHub

Two builds, one source

Every component is defined once, as a class. The classless build emits those same classes and then binds them to plain elements with Sass @extend, which is the native version of Tailwind's @apply: button { @extend .btn; } compiles to .btn, button { ... }. One rule, both builds, no drift. The classless build carries the class names too, so you can mix the two.

BuildImportStyles
Class @sparkstone/css Short, semantic class names. Plain elements are left alone.
Classless @sparkstone/css/classless Semantic HTML, no classes needed. This is the 1.x theme, unchanged.

Every component page below shows both, side by side. Switch the tab on any example to see the other build, and the preview switches stylesheets with it.

The same page, both ways

<div class="prose">
  <h2>Hello</h2>
  <p>Body copy, and <a href="#" class="link">a link</a>.</p>
</div>

<article class="card prose">
  <h3>A card</h3>
  <p>Cards are just articles.</p>
  <footer class="card-actions flex" style="justify-content: end">
    <button class="btn btn-secondary">Cancel</button>
    <button class="btn">Confirm</button>
  </footer>
</article>

Kobalte

Components marked K are covered by an opt-in layer that styles Kobalte's rendered markup as the matching component, so its parts need no class attributes. See All components.

What you get

Theming

Three colors drive everything. Set them anywhere a CSS variable can be set.

:root {
  --color: rebeccapurple;
  --accent-color: oklch(from var(--color) l c calc(h + 180));
  --error-color: maroon;
}

Because they are plain CSS variables, you can rebind --color on a subtree and every descendant recolors itself. See Colors and Customizing.

Light and dark

The scheme follows prefers-color-scheme by default. Force it with an attribute on any element, not just <html>:

<html data-color-scheme="light">
<html data-color-scheme="dark">

Live preview

Change these and every page on this site updates. Values persist for the session.

Browser support

The framework leans on relative color syntax, oklch(from ...). That means Chrome 119+, Safari 16.4+, and Firefox 128+. There is no fallback layer, by design.