Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/davesnx/styled-ppx/llms.txt

Use this file to discover all available pages before exploring further.

%cx (ReScript) / [%cx] (Reason) is styled-ppx’s lightweight alternative to %styled.<tag>. Instead of producing a React component module, it produces a plain string — the scoped class name generated by emotion. You attach that string to any element via its className prop. This is useful when naming a whole component feels like overkill, when you need to apply styles inline in JSX, or when you want to reuse a single class definition across multiple elements without creating a module for it.

When to use %cx vs %styled.*

SituationRecommendation
You need a reusable, named React componentUse %styled.<tag>
Styles are used in exactly one place inlineUse %cx
You want to compose several class strings with logicUse %cx
You need DOM prop forwarding (onChange, ref, etc.)Use %styled.<tag>

Basic inline usage

The simplest form is writing %cx(...) directly inside a className prop:
<span className=%cx("font-size: 32px")>
  {React.string("Hello!")}
</span>

Multi-line declarations

For longer style blocks, use a backtick string (ReScript) or a quoted string (Reason) to span multiple lines. The result is still a string:
let fullWidth: string = %cx(`
  position: absolute;
  width: 100%;
  height: 100%;
  top: 0;
  left: 0;
`)

<div className=fullWidth> {React.string("Hello!")} </div>
The value fullWidth is a string that contains a hash pointing to a style <style> tag injected into the document <head>. It is stable across renders — emotion only injects each unique rule set once.

Combining class names

Because %cx is just a string, you can concatenate it with other class names using the standard string concatenation operator (++):
<div className={fullWidth ++ " " ++ "extra-classname"}>
  {React.string("Hello!")}
</div>

Features

  • Selectors — pseudo-classes, pseudo-elements, and nested selectors work exactly as in %styled.<tag>:
    let hoverable = %cx(`
      color: blue;
      &:hover { color: darkblue; }
    `)
    
  • Media queries@media blocks are fully supported inside %cx.
  • Interpolation — embed typed OCaml/ReScript values with $(identifier) syntax:
    %cx("color: $(Theme.colors.primary)")
    
    See Interpolation for how type inference works.
  • Array API — pass an array of Css.rule values instead of a string:
    let className = %cx([%css("display: flex;")])
    
    See Array API for full details.

What is NOT allowed

Wrapping braces ({ }) around the declarations are not permitted. The content of %cx must be a list of CSS declarations (property–value pairs and nested rules), not a CSS rule block.
This will cause a compile-time error:
// 🔴 Wrapping braces are not allowed
let bad = %cx("{ display: block; }")
Write the declarations directly, without an enclosing block:
// ✅ Correct
let good = %cx("display: block;")

Build docs developers (and LLMs) love