Styles
Any block takes any CSS — layout, size, type, fills, borders, effects, transforms — per screen size and per state, with design tokens one click away.
On this page
Select a rendered block and open Design in the inspector. Each section edits real CSS: Layout (block, stack, grid, alignment, gap), Position, Size (fill, fit, fixed, limits, aspect ratio, overflow), Spacing (margin and padding on a box model), Typography, Fill (color, gradient, image, gradient text), Border and radius, Effects (opacity, shadows, blur, backdrop blur, blend modes, cursor), Transform and Transition. CSS at the bottom lists everything set at the current screen size and state, and adds any other property.
Numbers scrub: drag a field's label sideways, or press ↑ ↓ (⇧ for steps of 10). The diamond in a field opens your tokens.
#How styles are stored
A block's style maps a variant to CSS properties in camelCase:
{
"type": "box",
"props": { "tag": "section" },
"style": {
"base": { "display": "grid", "gridTemplateColumns": "repeat(3, 1fr)", "gap": "token:space.8", "paddingBlock": "token:space.section" },
"tablet": { "gridTemplateColumns": "1fr 1fr" },
"mobile": { "gridTemplateColumns": "1fr" },
"hover": { "transform": "translateY(-2px)" },
"mobile:hover": { "transform": "none" }
}
}About 140 properties are allowed — blocks/types lists them with their inspector section. A few shorthands are accepted and stored under their full name: paddingX/paddingY (paddingInline/paddingBlock), marginX, marginY, radius, shadow, bg, direction, justify, align.
#Values
| You write | Becomes |
|---|---|
token:space.8 | var(--space-8) |
token:color.primary/40 | The color at 40% opacity |
0 8px 24px token:color.foreground/15 | Tokens work inside any value |
16 | 16px — except unitless properties like opacity, zIndex, fontWeight, lineHeight, flexGrow, scale, aspectRatio |
gridTemplateColumns: 3 | Three equal columns |
gridColumn: 2 | Span two columns |
backgroundImage: "media:01jc…" | The uploaded image's URL |
clamp(2rem, 6vw, 5rem), linear-gradient(…) | As written |
Anything that could break out of a declaration — braces, semicolons, url() written by hand, comments — is refused.
#Screen sizes
Styles are desktop-first, like you design:
| Variant | Applies |
|---|---|
base | Every screen |
tablet | Below the lg breakpoint (1024px) |
mobile | Below the md breakpoint (768px) |
sm, md, lg, xl | At that breakpoint and up, for mobile-first styles |
Choose Desktop, Tablet or Phone above the block inspector to edit that screen size. A field's label is blue when its value is set here and amber when it is inherited from a larger screen or the default state; click a blue label to reset it.
#States
The chips above the inspector choose the state you style: Default, Hover, Pressed, Focus, and with +:
| State | Matches |
|---|---|
hover, active, focus, focus-visible, focus-within, disabled, checked | The element itself (hover only on devices that can hover) |
before, after, placeholder, marker, selection | Pseudo-elements (before/after get content: "" automatically) |
first, last, odd, even, empty | Position among siblings — handy inside a Repeat |
open, current | An open <details>, a link to the current page (aria-current) |
group-hover, group-focus | An ancestor with the Hover group behavior is hovered or focused |
dark | Dark mode |
is-<name> | The element has a custom state |
in-<name> | An ancestor has it — “while the menu is open” |
Combine a screen size and a state with a colon: mobile:hover, tablet:is-open.
#Custom states
Custom states connect styling to everything else:
- Interactions set them:
logic.states: { "open": "open" }addsis-openwhile theopenvariable is true. - Behaviors set them: Scroll states adds
is-scrolled, Scroll spy addsis-current. - Data sets them:
bind: { "state:active": "item.active" }addsis-activeto the current menu link.
Style is-open on the element and in-open on its children, add a Transition, and the change animates — no script needed.
#How it reaches the page
Each declaration becomes one short class (.s4k2j9{gap:var(--space-8)}), shared by every block with the same declaration, and only the classes a page uses are written into it. The live editing surface and public site use the same renderer and style data.