CSS Variables

CSS custom properties are a platform feature and JAF does nothing special to them.

Define them where you like and use them anywhere:

source
<style global>
:root {
  --primary: #3B82F6;
  --secondary: #64748B;
  --radius: 8px;
}
</style>

<style>
.btn {
  background: var(--primary);
  border-radius: var(--radius);
}
</style>

:root is one of the selectors scoping leaves alone, so a <style global> block on :root defines variables for the whole app.

Setting one from state

This is the part JAF adds.

The style: directive writes a custom property, so a variable can come from component state and every rule using it follows:

<script>
let brand = '#22d3ee'
let radius = 10
</script>

<div class="preview" style:--brand={brand} style:--radius={radius + 'px'}>
  <button class="chip">Buy now</button>
</div>

<div class="controls">
  <button class="swatch cyan" onclick="brand = '#22d3ee'"></button>
  <button class="swatch violet" onclick="brand = '#a78bfa'"></button>
  <button class="swatch amber" onclick="brand = '#fbbf24'"></button>

  <label>
    Corner
    <input type="range" bind:value={radius} min="0" max="24" />
  </label>
</div>
output
style: writes the value, it does not add units. style:--radius={10} sets --radius: 10, which the CSS parser then throws away. Write style:--radius={radius + 'px'}.

Variables as a component's dials

A component that reads its own sizes from variables gives its user somewhere to turn:

<!-- Card.html -->
<div class="card">
  <slot />
</div>

A style attribute on the tag is merged onto the component's root element, so the inline value beats the class rule:

source
<Card style="--card-padding: 2rem; --card-radius: 16px">
  Roomier, rounder, same component.
</Card>

Fallbacks

var() takes a second argument, which is what the component uses when nobody set the variable:

source
<style>
.card {
  background: var(--card-bg, white);
  color: var(--card-text, inherit);
  padding: var(--card-padding, 1rem);
}
</style>