Skip to content

Styling

Studio writes this format for you. The Design inspector and Project Styles produce everything below. This page documents the style model for hand-editing and reference.

Styles are JSON objects. Property names are the CSS ones in camelCase, the same spelling the CSSOM uses, so background-color is written backgroundColor .

Inline styles

The style property accepts a JSON object:

{
  "tagName": "div",
  "style": {
    "backgroundColor": "blue",
    "marginTop": "10px",
    "fontSize": "16px",
    "display": "flex"
  }
}

Nested CSS selectors

Keys beginning with : , . , & , or [ are treated as nested selectors:

{
  "style": {
    "backgroundColor": "blue",
    ":hover": {
      "backgroundColor": "darkblue",
      "cursor": "pointer"
    },
    ".child": { "color": "white" },
    "&.active": { "outline": "2px solid white" }
  }
}

Inline properties apply directly to the element. Nested rules are emitted as a scoped <style> block keyed on a generated class , .<tagName>-<n> , which the build also puts on the element:

<div class="sty-card-0">…</div>
.sty-card-0:hover {
  padding: 8px;
}

(You'll also see data-jx-static and data-jx-prerendered in compiled output. Those mark hydration state and are never used as CSS selectors.)

Named media breakpoints

Declare breakpoints at root level with $media :

{
  "$media": {
    "--sm": "(min-width: 640px)",
    "--md": "(min-width: 768px)",
    "--lg": "(min-width: 1024px)",
    "--dark": "(prefers-color-scheme: dark)"
  }
}

Use @--name keys in any style object:

{
  "style": {
    "fontSize": "14px",
    "@--md": { "fontSize": "16px" },
    "@--dark": { "color": "#ccc" },
    "@(min-width: 1280px)": { "fontSize": "18px" }
  }
}

@--name references named breakpoints. @(condition) is a literal inline media query, and the parentheses are the query's own: a feature query keeps them ( @(min-width: 1280px) ), while a bare media type does not, so @(print) emits @media print .

Color-scheme variants

A $media entry whose value is exactly a prefers-color-scheme query (like --dark above) is a scheme query : its @--dark blocks respond both to the OS preference and to a visitor-forced scheme, and the compiler wires up color-scheme and no-flash persistence automatically. See Color schemes for the full contract and how to build a switcher.

Static style extraction

The compiler extracts every static style definition into a single <style> block in the document <head> , so a page carries one stylesheet rather than a rule per element.

Design tokens as CSS custom properties

Define tokens in your project.json style block and use them everywhere:

{
  "style": {
    ":root": {
      "--color-primary": "#3b82f6",
      "--color-surface": "#ffffff",
      "--font-sans": "Inter, system-ui, sans-serif"
    }
  }
}

Components reference tokens with standard var() :

{
  "style": {
    "color": "var(--color-primary)",
    "fontFamily": "var(--font-sans)"
  }
}

CSS custom properties cascade through the DOM, so every component can use them without importing anything.