Styling

Jx uses JSON objects for styling with camelCase CSS property names, nested selectors, and named media breakpoints.

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 using a generated data-jx attribute selector.

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.

Static Style Extraction

The compiler extracts all static style definitions into a single <style> block in the document <head>, producing clean, efficient CSS output.

Design Tokens with CSS Custom Properties

Define tokens in site.json 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 naturally through the DOM — every component can use them without importing anything.