WovenUI vs Pico CSS
The Sass framework that styles plain HTML and grows into your design system. WovenUI's base layer styles headings, links, buttons and form fields from theme tokens; readable utility classes and apply() mixins take any custom value from there. Light, dark, inverse and high contrast come from one configuration, and mistakes stop the build with the fix in the message. Pico is archived, with v2.1.1 as its final release [12], so this page compares the Pico 2 line.
Side by side
| Topic | WovenUI | Pico CSS |
|---|---|---|
| Plain HTML | Plain HTML is styled from the start, and the same system scales to a design system. The base layer styles body, headings, paragraphs, links, buttons, form fields, code, images, figures, blockquote and hr from theme tokens. Readable utility classes (flex col gap-3 p-6 bg-surface) and your own BEM classes built with apply() take it from there. | Styles HTML tags directly and uses fewer than 10 classes overall [1][2], with a class-less build available [3]. A bare <article> is a card and a <button> is a button [4][5]. |
| Custom values | Any value, right in your component CSS: apply(p(13px), bg(#bada55), rounded(lg)). A unitless number is a scale key; a value with a unit is used as written. Every utility class is also a mixin, so one vocabulary covers your HTML and your SCSS. | Override a CSS variable on :root or on any selector, such as --pico-border-radius: 2rem [6]. |
| Themes and dark mode | One configuration covers light, dark, inverse and high contrast. Override maps ($light-theme, $dark-theme) hold only the tokens you change, and the dark blocks are generated. data-theme="light", "dark" or "inverse" works on any element; without it the operating system decides. data-contrast="high" applies your high contrast maps, and text on a brand or status fill (text-on-brand) is picked for contrast at compile time, with a warning below 4.5:1. | Light and dark schemes follow prefers-color-scheme, and data-theme="light" or "dark" sets the scheme for the whole document or one element [8]. Custom color variables are written in three places: the light block, the automatic dark media query and the forced [data-theme="dark"] block [6]. |
| Project status | Maintained and published on npm as @wovenui/core, with a changelog in the repository. | Archived: no new issues, pull requests or releases, and v2.1.1 is the final release. The npm package, CDN and website stay online [12][2]. |
| Catching mistakes | Mistakes stop the build with the fix in the message. An unknown key, color, token or modifier in a mixin, the configuration or token() fails the compile and lists the valid options: apply(p(7)) gives p: 7 is not a configured key. Valid keys: 0, 1, 2, 3, 4, 5, 6, 8, 10, 12, 16, 20, 24, 32, 40, 48, 56, 64. Write a unit for a custom value (7px, 7rem). | Not documented. |
| Design tokens | Semantic roles out of the box: --wu-* custom properties for surfaces, text, borders, focus, brand and status roles, plus the palette and every scale. Classes and mixins output var(--wu-*), and token(name) raises an error for an unknown name, so a typo never reaches the browser. | CSS custom properties prefixed with pico-. Style variables (font, spacing, radius) stay fixed; color variables change with the scheme [6]. The prefix can be changed by recompiling with Sass [6]. |
| Component styles | Made for component stylesheets. @wovenui/core/mixins has the full API and outputs no CSS, so each CSS module or <style lang="scss"> block compiles to its own rules only. Base styles live in a cascade layer and your CSS is unlayered, so it wins without !important; $parent-selector scopes every generated class under a selector. | The default build applies Pico styles to every HTML element. A conditional build, with $parent-selector: ".pico", limits them to elements inside a .pico container [10]. |
| Ready-made patterns | Free, step-by-step recipes for a card, navbar, form field, dark mode toggle, dashboard layout and pricing table. Core styles plain HTML buttons and form fields, includes CSS-only tooltips, ships no JavaScript, and works with any component library you already use. | Documented components include accordion, card and modal, alongside forms, typography and a grid [1][9]. |
| RTL | Direction-aware by default: px, mx and space-x are logical, alongside ms, me, ps, pe, start-*, end-*, border-s, rounded-s-* and text-start. Physical classes stay for sides that must not flip. | Set dir="rtl" on the <html> element, or on a single element [13]. |
| Configuration | One @use ... with (...) block: $brand, scale maps, theme override maps and feature flags. Everything is validated at compile time, and a wrong key raises an error that names the valid options. | Sass settings passed with @use "pico" with (...): $theme-color (20 color options), $css-var-prefix, $enable-classes, $enable-transitions, $parent-selector and a $modules map that switches parts on or off [7]. |
| Setup | Link the prebuilt wovenui.min.css, or install Sass (Dart Sass 1.79 or later, below 2.0) and @use "@wovenui/core" for apply() and your own configuration. Vite, Next.js (Turbopack and webpack) and Astro resolve it with no extra configuration; Svelte adds vitePreprocess(). No framework plugin, no PostCSS plugin and no runtime JavaScript. Setup guides for React, Next.js, Vue, Svelte, Astro and plain HTML, plus a playground to try it in the browser. | Link the compiled CSS from a CDN or a download [1][11]. Sass is needed to customize [7]. |
| CSS you ship | Only what you use. By default you ship only the rules you write: tokens and base styles are 5.8 KB gzipped, and each component adds only its own rules, with no purge step. Feature flags switch whole groups off. Using the prebuilt file with every class? See Ship only the classes you use. | The $modules map and $enable-classes: false give a lighter build; the docs say a trimmed example reduces the weight of Pico by about 50% [7]. |
| Editor support | The WovenUI extension for VS Code: completion, hover docs, color swatches and one-click fixes for apply(), classes and tokens. | Not documented. |
| AI assistants | A complete guide ships in the package at docs/llms-full.txt and on this site at /llms-full.txt, with a short index at /llms.txt, so an assistant writes valid WovenUI code. | Not documented. |
| Browsers | Modern browsers, with cascade layers and @property in the output and @scope for the dark-mode mixin. | Designed and tested for the latest stable Chrome, Firefox, Edge and Safari; no version of Internet Explorer is supported [2]. |
| License | MIT. | MIT. |
The same component in both
A card from the Pico documentation, and the same card in WovenUI, once as utility classes and once as BEM classes built with apply(). Every WovenUI value reads a theme token and stays yours to tune, so the same markup follows the theme: it is rendered below in a light and a dark section.
<div class="flex col gap-3 p-6 bg-surface border rounded-lg hover:shadow-md">
<h3 class="text-lg font-semibold">Card title</h3>
<p class="text-muted">Some quick example text to build on the card title.</p>
<a href="#" class="self-start px-4 py-2 rounded-md bg-brand text-on-brand">Go somewhere</a>
</div><article>
<header>Card title</header>
Some quick example text to build on the card title.
<footer>
<button>Go somewhere</button>
</footer>
</article>@use "@wovenui/core" as * with (
$brand: #4361ee,
$light-theme: ("bg-surface": gray 50),
$dark-theme: ("bg-surface": #202020)
);
.card {
@include apply(
flex, col, gap(3), p(6),
bg(surface), rounded(lg), border(1),
shadow(md) hover
);
}
.card__action {
@include apply(
self-start, px(4), py(2), rounded(md),
bg(brand), text-color(on-brand), bg(brand-hover) hover
);
}@use "pico" with (
$theme-color: "jade"
);
:root {
--pico-border-radius: 2rem;
}Moving from Pico CSS
- Start from plain HTML: the WovenUI base layer styles headings, links, buttons, form fields,
code,blockquoteandhrfrom theme tokens. See Installation. - Turn each element Pico styled for you, such as the
<article>card, into your own class withapply(), or into utility markup. See apply() and the card recipe. - Replace
$theme-colorand the other Sass settings with one@use "@wovenui/core" with (...)block, starting with$brand. See Configuration. - Replace the three-block color overrides with
$light-themeand$dark-thememaps, and--pico-*variables with--wu-*tokens. See Theming and Tokens. - Keep
data-themeon the root or on a section: the attribute carries over, and WovenUI addsinverse. See Theming. - Build patterns such as the accordion and modal as your own components with
apply(), starting from the recipes. Tooltips are built in and CSS only: see Tooltips. - Install the WovenUI extension for VS Code for completion and hover docs while you move. See Editor support.
Sources
Every statement about Pico CSS on this page comes from its official documentation or repository. Statements about WovenUI come from the core source, its changelog and the core documentation.
- [1] Pico CSS: homepage
- [2] Pico CSS: repository and README
- [3] Pico CSS: Class-less version
- [4] Pico CSS: Card
- [5] Pico CSS: Button
- [6] Pico CSS: CSS variables
- [7] Pico CSS: Sass
- [8] Pico CSS: Color schemes
- [9] Pico CSS: Container
- [10] Pico CSS: Conditional styling
- [11] Pico CSS: Quick start
- [12] Pico CSS: Maintenance
- [13] Pico CSS: RTL