ClassName Syntax
Boss CSS parses className strings and turns supported patterns into CSS rules. The syntax is designed to stay as close to real CSS as possible.
Boss uses framework detection to decide whether the prop is className (React/Next/Preact) or class (Solid/Qwik/Stencil).
ClassName parsing is server-side only. In runtime.only mode, className strings are not converted into CSS.
Basic format
- React / Next.js
- Solid / Qwik / Stencil
<div className="display:block color:red font-size:32">
ClassName styles
</div>
<div class="display:block color:red font-size:32">
Class styles
</div>
Each segment is prop:value. Unsupported segments are ignored.
Static strings only
ClassName parsing only supports static strings (string literals or template literals without ${}):
<div className="display:flex gap:12" />
Template literals with expressions are skipped:
<div className={`display:flex ${dynamic}`}/> // skipped by the parser
Use cx to build className strings from conditionals, but keep the Boss tokens static:
<div className={$$.cx("display:flex", isActive && "hover:color:purple")} />
Pseudo chaining
<div className="hover:color:yellow active:color:orange">
Hover and active
</div>
Multiple pseudos can be chained:
<div className="hover:focus:font-size:12">
Hover + focus
</div>
Grouped pseudo values
Use braces to group multiple declarations under one pseudo token:
<div className="hover:{color:red;text-decoration:underline}">
Hover group
</div>
This is matched as a full class token (exact, but less optimized). When using the compiler, grouped selectors with multiple entries are normalized into per-prop tokens (sorted by prop name), for example:
<div className="hover:color:red hover:text-decoration:underline">
Hover group
</div>
You can also chain pseudos or media shorthands:
<div className="hover:focus:{color:red;text-decoration:underline}">
Hover + focus group
</div>
<div className="mobile:hover:{display:block;color:red}">
Mobile hover group
</div>
Arbitrary selectors
Use bracket syntax to target arbitrary selectors:
<div className="[&>div]:color:red">
<div>Nested child</div>
</div>
Inside [...] you can use any CSS selector, relative to the component. Use _ to represent spaces:
<div className="[&_.title]:font-weight:700">
<span className="title">Title</span>
</div>
If the selector contains &, it is replaced with the current selector. If it does not, it is treated as a descendant selector:
<div className="[.title]:color:blue">
<span className="title">Descendant</span>
</div>
<div className="[.title_&]:color:red">
<span className="title">Current inside .title</span>
</div>
Media queries with at
<div className="at:mobile+:display:block">
Responsive display
</div>
You can also chain media and pseudo:
<div className="mobile:hover:display:block">
Mobile hover
</div>
Array values
Use underscores to express arrays:
<div className="margin:20_0 padding:8_16">
margin: 20px 0; padding: 8px 16px;
</div>
!important
End a class token with ! to emit !important:
<div className="color:red! hover:color:blue!">
Important styles
</div>
Content with quotes
<div className="before:content:''">
before content
</div>
Tailwind and other classes
Boss CSS only acts on known CSS props or pseudo keywords. That means Tailwind-like classes are ignored unless you enable Bosswind:
<div className="hover:bg-gray-100">
This remains untouched by Boss CSS
</div>
If you want utility-style generation, stick to prop:value syntax or enable the Bosswind plugin.
ClassName helper
Use cx when you need to compose className strings from arrays, objects, or conditional values. cx wraps css-variants input semantics and then applies Boss conflict resolution, so it is preferred over calling merge directly.
$$.cx("card", { "color:red": true }, ["color:blue"])
// -> "card color:blue"
You can also import it directly if you prefer:
import { cx } from "boss-css/variants"
cx("card", { "color:red": true }, ["color:blue"])
// -> "card color:blue"