API ReferenceArray API

Array API

%styled.{{tag}} [%styled.{{tag}}] and %cx [%cx] support an alternative to the string-based API. That’s the Array API, where the rules can be defined as an array of Css.rules Css.rules.

The type Css.rule Css.rule is a reference to a CSS declaration rule which can be a CSS property, a CSS selector or an CSS at-rule (like @media or @font-face).

To create a CSS.rule you can use the extension %css(...) or the CSS module.

Example

Both cx and styled extensions support the following:

module Component = %styled.section([
  %css("display: flex"),
  %css("justify-content: center"),
])
 
let className = %cx([%css("display: flex;")])
module Component = [%styled.section [|
  [%css "display: flex"],
  [%css "justify-content: center"]
|]];
 
let className = [%cx [|[%css "display: flex;"]|]];
Any expression that is a Css.rule is valid inside the array.

Features

  • Allowing composability and re-usability of CSS.
  • Useful to reference other variables, a function call or a pattern match.
  • Solves the migration problem from other systems (such as bs-css) and bypasses the styled-ppx parser which might not support a property.

Here are some illustrative examples:

module Button = %styled.button([
  buttonStyles, /* a variable reference */
  anyRandomFunction(123), /* a function call */
  boolean ? %css("width: 100%;") : %css("width: auto"), /* conditional */
])
module Button = [%styled.button
  [|
    buttonStyles /* a variable reference */,
    anyRandomFunction(123) /* a function call */,
    if (boolean) {
      [%css "width: 100%;"];
    } else {
      [%css "width: auto"];
    } /* conditional */,
  |]
];
module Align = %styled.div((~distribute=#Center, ~align=#Center) => [
    %css("display: flex"),
    %css("height: 100%"),
    %css("width: 100%;"),
    switch distribute {
    | #Start => %css("justify-content: flex-start")
    | #Center => %css("justify-content: center")
    | #End => %css("justify-content: flex-end")
    },
    switch align {
    | #Start => %css("align-items: flex-start")
    | #Center => %css("align-items: center")
    | #End => %css("align-items: flex-end")
    },
  ]
)
 
<Align distribute=#Start align=#Start />
module Align = [%styled.div (~distribute=`Center, ~align=`Center) => [|
  [%css "display: flex"],
  [%css "height: 100%"],
  [%css "width: 100%;"],
  switch (distribute) {
  | `Start => [%css "justify-content: flex-start"]
  | `Center => [%css "justify-content: center"]
  | `End => [%css "justify-content: flex-end"]
  },
  switch (align) {
  | `Start => [%css "align-items: flex-start"]
  | `Center => [%css "align-items: center"]
  | `End => [%css "align-items: flex-end"]
  },
|]];
 
<Align distribute=`Start align=`Start />;

Usage with Dynamic components

There’s a nice composability that dynamic components and the Array API provides. You can create a component that can run any code before the styles. It will be called each time the component renders. Such as this example of runtime styles where it derives the color’s background button based on a variant prop passed to a Theme module.

module Button = %styled.button((~variant) => {
  let color = Theme.button(~variant)
 
  [
    %css("background-color: $(color)"),
    %css("width: 100%;"),
    %css("display: inline-flex"),
  ]
})
module Button = [%styled.button (~variant) => {
  let color = Theme.button(~variant);
 
  [|
    [%css "background-color: $(color)"],
    [%css "width: 100%;"],
    [%css "display: inline-flex"],
  |];
}];

Note: The last expression of the function, the returned value has to be an array of Css.rules (it can’t be a reference or a function call). This is a limitation of ppxes where it needs to check the current AST to know which type is.