Skip to content
ONIWC
iwc 0.1.0

Style property reference

Every styling property an IWC element, layout or theme accepts, in one place. For the reasoning behind them — the four styling layers, dark mode, hooks for your CSS — read Styling & responsive design.

Where styles come from

LayerWhereWins over
Theme tokensapp.iwc theme.tokens / theme.dark → CSS variables on :root—
Your stylesheetsapp.iwc styles, and styleSource on screens, layouts, components and elementsbuilt-in CSS, always
Element stylingclassName, style, responsive, states, transition, animation, vars—
Built-in CSSthin defaults inside @layer iwcnothing: any rule you write wins

Layout: flexbox

layout on any container sets flexbox:

KeyValuesCSS
directionrow column row-reverse column-reverseflex-direction
alignstart center end stretch baselinealign-items
justifystart center end between around evenlyjustify-content (between = space-between)
gapCSS lengthgap
wrapbooleanflex-wrap: wrap

row and column/stack already set the direction.

element (in a .iwc file)
{
  "type": "row",
  "layout": { "align": "center", "justify": "between", "gap": "16px", "wrap": true },
  "elements": [
    { "type": "text", "variant": "h3", "content": "Orders" },
    { "type": "button", "label": "Export", "variant": "secondary", "action": "navigate", "target": "/orders" }
  ]
}

Layout: grid

PropertyValueEffect
columnsinteger 1–24, or a CSS stringequal columns, or grid-template-columns ("2fr 1fr", "repeat(auto-fill, minmax(220px, 1fr))")
responsiveColumns{breakpoint: count}column count at or below a breakpoint
gapCSS lengthgap between cells (also for flex)
element (in a .iwc file)
{
  "type": "grid",
  "columns": "repeat(auto-fill, minmax(220px, 1fr))",
  "gap": "20px",
  "elements": [{ "type": "box", "content": "A" }, { "type": "box", "content": "B" }, { "type": "box", "content": "C" }]
}

style: spacing, sizing, colour, typography, borders, shadows

style takes any CSS property, in camelCase or kebab-case, with string or number values. Unsafe CSS (expression(, javascript:, @import, </) is dropped. Each element's CSS is scoped to it with a generated class and sent under the page's CSP nonce.

CategoryProperties (examples)
Spacingpadding, paddingInline, margin, marginTop, gap
Sizingwidth, maxWidth, minHeight, aspectRatio, flex
Colourcolor, background, backgroundImage, opacity
TypographyfontSize, fontWeight, fontFamily, lineHeight, letterSpacing, textAlign, textTransform
Borders & radiusborder, borderBottom, borderRadius, outline
ShadowsboxShadow, textShadow, filter
Positionposition, top, zIndex, overflow
element (in a .iwc file)
{
  "type": "box",
  "content": "Free delivery over ₹999",
  "style": {
    "padding": "12px 20px",
    "maxWidth": "60ch",
    "background": "var(--color-surface)",
    "color": "var(--color-text)",
    "fontSize": "15px",
    "fontWeight": 600,
    "border": "1px solid var(--color-border)",
    "borderRadius": "var(--radius)",
    "boxShadow": "0 8px 24px rgba(0,0,0,.08)"
  }
}

responsive: breakpoints

Breakpoints are max-widths. Defaults: mobile = 640px, tablet = 1024px. Add or change them in app.iwc:

app.iwc
{ "name": "Shop", "breakpoints": { "mobile": 640, "tablet": 1024, "wide": 1440 } }

responsive applies CSS at or below a breakpoint's width. Write desktop styles first, then override:

element (in a .iwc file)
{
  "type": "section",
  "layout": { "direction": "row", "gap": "48px" },
  "responsive": { "tablet": { "flexDirection": "column", "gap": "24px" }, "mobile": { "padding": "32px 16px" } },
  "elements": [{ "type": "text", "variant": "title", "content": "Light that feels like home." }]
}

states: hover, focus, active

KeyCSS selector
hover:hover
focus:focus-visible
active:active
element (in a .iwc file)
{
  "type": "card",
  "fields": { "title": "name" },
  "states": { "hover": { "transform": "translateY(-4px)", "boxShadow": "0 18px 40px rgba(0,0,0,.12)" }, "focus": { "outline": "2px solid var(--color-primary)" } },
  "transition": "transform 200ms ease, box-shadow 200ms ease"
}

transition and animation

transition is a CSS transition string. animation is an entrance animation:

KeyValuesDefault
name (required)fade fade-up fade-down slide-left slide-right zoom none—
triggervisible (when scrolled into view), loadvisible
durationduration (700ms)—
delayduration (100ms)—

Visitors who prefer reduced motion see no movement.

element (in a .iwc file)
{ "type": "column", "animation": { "name": "fade-up", "duration": "700ms", "delay": "100ms" }, "elements": [{ "type": "text", "content": "Appears as it scrolls into view" }] }

vars: values from data

vars sets CSS custom properties per record, from data. Your stylesheet reads them:

element (in a .iwc file)
{
  "type": "grid",
  "columns": 3,
  "data": { "source": "STATIC", "items": [{ "name": "Design", "pct": 80, "color": "#7c3aed" }, { "name": "Build", "pct": 45, "color": "#2563eb" }] },
  "item": { "type": "box", "className": "progress", "vars": { "--accent": "=color", "--progress": "=concat(pct, '%')" }, "bind": "name" }
}
styles/main.css
.progress { background: linear-gradient(90deg, var(--accent) var(--progress), #eee 0); }

Theme tokens

app.iwc theme.tokens become CSS variables on :root; theme.dark overrides them under prefers-color-scheme: dark. Any names work; the built-in elements read these:

TokenUsed for
color-primary, color-on-primaryprimary buttons, active tabs, charts
color-text, color-backgroundthe page
color-surface, color-bordercards, inputs, tables, dropdowns
color-linklinks (default: the text colour)
color-dangerfield errors
color-ratingreview stars
radiusbuttons, cards, inputs
font-body, font-headingbody text and h1–h6
carousel-gapspace between carousel slides
app.iwc
{
  "name": "Shop",
  "theme": {
    "tokens": { "color-primary": "#5b4cf5", "color-on-primary": "#fff", "color-surface": "#f6f4ff", "radius": "14px", "font-body": "Inter, sans-serif", "font-heading": "'Plus Jakarta Sans', sans-serif" },
    "dark": { "color-background": "#0f0f1a", "color-text": "#ececf4", "color-surface": "#1a1a2b" },
    "fonts": [{ "family": "Inter", "google": true, "weights": [400, 600] }, { "family": "Plus Jakarta Sans", "google": true, "weights": [700, 800] }]
  }
}

fonts entries are {family, google, weights} (Google Fonts) or {family, source, weight, style} (a file under assets/, emitted as @font-face).

Layout slots

.layout.iwc structure sets per-slot behaviour:

OptionValuesEffect
positionnormal sticky fixedsticky keeps a header in view
mobilenormal hidden drawer bottombelow the mobile breakpoint: hide, slide-in drawer, or pin to the bottom
collapsiblebooleana button that collapses the slot
widthCSS lengthfixed width
styleCSSextra styles

template lays slots out as CSS grid areas (["header header", "sidebar content"]). See Layouts.

Custom CSS

Everything is also reachable from plain CSS. Hooks: your classNames; each element's type class (.iwc-text, .iwc-button, .iwc-card); variants (.iwc-text-h1, .iwc-button-secondary); parts (.iwc-card-media, .iwc-field-error, .iwc-navbar-links); slots (.iwc-slot-header); states ([aria-current="page"], details[open]); and your attributes ([data-tone=dark]). Because IWC's own CSS is in @layer iwc, any rule you write wins over it.

app.iwc
{ "name": "Shop", "styles": ["styles/theme.css", "styles/main.css"] }

className accepts utility-framework syntax (md:grid-cols-2); IWC runs no CSS build step, so compile the framework's CSS into styles/ yourself.

Source: apps/marketing/content/docs/style-reference.md