Skip to content

Styling

Three approaches, pick what fits:

  1. Plain CSS / Tailwind / your stylesheet of choice — works without anything special. Just import .css.
  2. Inline style attribute — pass a CSSProperties object directly to elements.
  3. flexium/css — atomic CSS-in-JS with build-time extraction.

Inline style

tsx
<div style={{ color: 'red', padding: '12px', fontWeight: 600 }}>
  styled
</div>

For dynamic styles based on signals:

tsx
const [active, setActive] = use(false)
<div style={{ background: active ? '#3b82f6' : '#e5e7eb' }}>...</div>

Pros: zero setup. Cons: not cacheable, slightly more bytes per node.

Plain CSS / Tailwind

Import a CSS file at the entry point:

tsx
// src/main.tsx
import './global.css'
import './tailwind.css'

Use class (lowercase, matching HTML) on elements:

tsx
<div class="text-red-500 font-bold">styled</div>

(Note: class, not className — Flexium passes attributes straight to the DOM.)

This is the path most apps take. Tailwind v4 works out of the box.

flexium/css — atomic CSS-in-JS

For colocated styles that get extracted at build time:

tsx
import { css } from 'flexium/css'

const button = css({
  padding: '8px 16px',
  background: '#3b82f6',
  color: 'white',
  borderRadius: '8px',
  cursor: 'pointer',
  '&:hover': {
    background: '#2563eb'
  }
})

function Submit() {
  return <button class={button}>Submit</button>
}

At build time, vite-plugin-flexium with optimize: 'auto' extracts the rule to a static CSS file with a hashed class name (flx-abc123). Result:

  • Zero runtime CSS-in-JS overhead in production
  • Atomic deduplication across all css() calls
  • Same class hash for identical rule sets

Pseudo-selectors and media queries

tsx
const card = css({
  padding: '16px',
  background: 'white',
  '&:hover': { background: '#f3f4f6' },
  '&:focus-visible': { outline: '2px solid #3b82f6' },
  '@media (max-width: 640px)': {
    padding: '8px'
  }
})

Theming

For app-wide design tokens, use CSS variables — works with any of the three approaches:

css
/* global.css */
:root {
  --color-primary: #3b82f6;
  --space-2: 8px;
  --space-4: 16px;
}

[data-theme='dark'] {
  --color-primary: #60a5fa;
}
tsx
<div style={{ color: 'var(--color-primary)', padding: 'var(--space-4)' }}>...</div>

Swap themes via a shared signal:

tsx
const [theme, setTheme] = use<'light' | 'dark'>('light', { key: 'theme' })

unsafeEffect(() => {
  document.documentElement.dataset.theme = theme
})

Composition

Compose multiple class names with a template literal or a helper:

tsx
<div class={`${base} ${active && activeStyle}`}>...</div>

Or use clsx / classnames if you prefer.

Next

Server-Side RenderingrenderToString, hydration.

Released under the MIT License.