Skip to content

Migrate from UnoCSS

Planning to migrate from UnoCSS to WovenUI? This guide maps UnoCSS utilities and features to WovenUI core and the kit.

This page is for teams that generate utilities with UnoCSS, usually with a Tailwind-compatible preset, and want ready-made HTML and CSS components on a token system. Utilities come from WovenUI core, and @wovenui/components has the components. Install the kit from the install page. For the framework-level comparison, read WovenUI vs UnoCSS. The utility names below assume a Tailwind-style preset; presets can rename anything, so check your own configuration.

In core the utility comes first and the modifier follows it: a breakpoint is a suffix (p-4@lg), a state is a prefix on the class (hover:bg-brand-subtle). Flex modifiers apply on a flex element, so write class="flex between x-center". The breakpoint names and sizes (md, lg) are core defaults, set by the $breakpoints setting; see the configuration page.

UnoCSS with a Tailwind-style preset WovenUI core Notes
flex justify-between flex between Main axis, no prefix
items-center x-center x- is the cross axis
flex-col col On a flex element
flex-1 grow On a child of a flex element
shrink-0 no-shrink On a child of a flex element
grid grid-cols-3 grid cols-3
col-span-2 col-span-2 Same name
md:grid-cols-3 cols-3@md Mobile first, from the breakpoint up
lg:p-4 p-4@lg Same suffix for every utility
hover:bg-gray-100 hover:bg-hover State prefix on the class; bg-hover is a theme color
bg-white bg-surface Follows the theme
text-gray-600 text-muted Semantic word, not a shade
ml-4, mr-4 ms-4, me-4 Logical, so they flip in right to left
z-50 z-modal Named levels
w-full, mx-auto w-full, mx-auto Same names
dark:bg-gray-800 bg-surface No dark: class, see below
p-[13px] p(13px) in SCSS Custom values live in SCSS
UnoCSS WovenUI Notes
@apply text-center my-0 font-medium; @include apply(text-center, my(0), font(medium)); One apply() call, with the modifier after the item
@apply 'hover:text-red' @include apply(text-color(danger) hover); State after the item, not in front
@screen sm { ... } @include media-up(sm) { ... } A standalone mixin that takes a block
@screen lt-xs { ... } @include media-down(xs) { ... } Below the breakpoint
Shortcuts in uno.config.ts A semantic class with apply() The shortcut becomes a normal Sass rule
Theme object in the config with() on @use "@wovenui/core" Tokens become --wu-* custom properties
Dynamic rules with a RegExp apply() with any value apply(p(13px)) needs no custom rule
@use "@wovenui/core" as *;
// UnoCSS: @apply flex justify-between items-center p-4 bg-white rounded-lg hover:shadow-md;
.toolbar {
@include apply(flex, between, x-center, p(4), bg(surface), rounded(lg), shadow(md) hover);
}

A unitless number is a scale key (p(4) is 1rem). A value with a unit is used as written (p(13px)). A wrong key stops the compile and the message lists the valid ones. Read more in Utility classes, apply() and Responsive.

There are no dark: classes. Semantic classes such as bg-surface and text-muted read tokens, and the tokens switch with data-theme on any element:

<html data-theme="dark">
<body class="bg-base text-regular">
<aside data-theme="light" class="bg-surface p-4">A light panel in a dark page</aside>
</body>
</html>

Without data-theme the operating system decides. See Theming.

UnoCSS has no components of its own, so the usual starting point is a component layer or hand-written shortcuts. The kit uses a wu- root and bare words for variants, valid only together with the root: wu-btn brand sm. Colors use the core role names. A shortcut is a class name you define in your own config, so the left column stays a class name and not markup.

Common shortcut or component name WovenUI Components Notes
btn <button class="wu-btn"> The plain button is the neutral one
btn-primary <button class="wu-btn brand"> On a <button> or a link
btn-danger <button class="wu-btn danger"> Destructive actions
card <article class="wu-card"> Parts: <header class="wu-card-header">, <div class="wu-card-body">, <footer class="wu-card-footer">; heading in wu-card-title
badge <span class="wu-badge"> Roles such as success; add solid for a filled badge
alert <div class="wu-alert success"> Title in wu-alert-title
modal <dialog class="wu-modal"> Opened with commandfor and command="show-modal", no script
dropdown <div class="wu-dropdown" popover> Items are wu-dropdown-item links or buttons; opened with popovertarget, no script
tabs <div class="wu-tabs"> Parts wu-tabs-list, wu-tabs-tab, wu-tabs-panel; active tab is aria-selected="true"
input <input class="wu-input"> On a text-like <input>
table <table class="wu-table striped"> Also hover, bordered, sm
tooltip data-tooltip Lives in core, see tooltips

Layout around the components still uses core utilities, so a card grid is grid, cols-3 and gap-4 from the first table, not a kit class.

UnoCSS gives you utilities, not a modal or dropdown, so open and close code is yours to write. The kit gives you these without writing any JavaScript: a modal and drawer on <dialog>, a dropdown and popover on the popover attribute, and an accordion on <details>.

  • No scanning and no config file. UnoCSS reads your source files and generates the CSS they use. WovenUI does not scan anything. Utility classes are off by default in the Sass entry, so you ship tokens, base styles and the rules you write, and the kit is compiled CSS. A dynamic class name such as p-${size} is a normal class here, because nothing has to detect it. See WovenUI vs UnoCSS for the details.
  • No attributify and no variant groups. WovenUI writes plain class names. Several utilities with one state become one apply() call: bg(brand-subtle) hover, shadow(md) hover.
  • No opacity slash syntax. There is no bg-red-500/50. Use a subtle role color such as bg-danger-subtle.
  • No icon preset. The kit ships no icons. Markers such as the select arrow and the close cross are drawn in CSS. Bring the icon set you already use.
  • Native elements. Modals are <dialog>, menus and popovers use the popover attribute, and accordions are <details>, so most components need no JavaScript.
  • Right to left. Components use logical properties, so one stylesheet serves both directions. See Right to left.
  1. Install the kit. Load the bundle or per-component entries, not both.
  2. Replace layout and helper classes with core utilities, using the first table.
  3. Swap components one at a time with the component table. Keep the old CSS loaded until the last one is gone.
  4. Move colors and spacing to core tokens, and switch themes with data-theme.
  5. Remove the old framework’s CSS and script.