Contents

Cascade layers

Copied utilities can steamroll the host Tailwind pane — or lose to it — depending on stylesheet order. Cascade layers wrap those class definitions in @layer utilities or @layer components so they compete the same way Tailwind does. Or leave them unlayered if your app already owns cascade.

Copied utilities fight the host Tailwind pane

Tailwind is layers — base, components, utilities. RuleCMS Class Definitions emit as unlayered [data-rulecms-published-key] .name rules. The same utility can steamroll the host or lose to it depending on which stylesheet loads last. A class body cannot contain a top-level @layer.

Cascade layers is a setting for how those class definitions are emitted. It is not a second stylesheet and it does not compile Tailwind. You pick utilities or components. RuleCMS wraps the existing class sheet.

When to use it / when not to

You wantLeave unlayeredWrap in a layer
Copied utilities to compete with host Tailwind the same way Tailwind utilities doUnlayered rules win or lose by stylesheet order. A later host sheet can override them — or they can override the host.Pick utilities. Class rules sit in @layer utilities and compete with the host pane.
Component-style classes that should sit under host utilitiesThey fight utilities as unlayered CSS.Pick components. Host utilities still win the cascade the way Tailwind intends.
A host that already puts these class names in a layerWorks today. Do not wrap them again.Turn published inclusion off. Composer and Preview still wrap when the setting is defined.
This does not compile Tailwind. You still paste declaration blocks on Class Definitions. Cascade layers only wraps that existing emit.
utilities vs components. Use utilities for copied Tailwind utilities. Use components when the classes should lose to host utilities. There is no free-text layer name and no @layer reset, theme, utilities list.

The project catalog

Open an environment, then Cascade layers. The page is project-scoped: Development, Staging, and Production share it.

  • Preview shows a short example using .rounded-xl — wrapped or unlayered — not a pasted stylesheet editor.
  • Edit is one select: Do not wrap (default), utilities, or components. Saving “do not wrap” deletes the setting. Catalog Save is explicit.

A typical wrapped emit looks like this:

@layer utilities {
  [data-rulecms-published-key="env---w"] .rounded-xl {
    border-radius: var(--radius-xl);
  }
}

Empty or omitted is today's unlayered class emit. This setting never styles :root, html, or body.

What the renderer does with the catalog

SurfaceWhat happens
Composer canvas and PreviewAlways wraps the surface class stylesheet when a layer is set. The published-inclusion flag is ignored here so authors still see cascade while they work.
Published widget (React SDK and HTML custom element)When inclusion is on and a layer is set, the class stylesheet is wrapped. When inclusion is off, classes still emit — unlayered — even if a layer is saved. If there are no class definitions, nothing is emitted.

You do not republish a widget to change the wrap. The setting is joined when the host fetches the widget. The next uncached fetch picks up the current choice.

Published widgets

On the project's Cascade layers page, the Published widgets accordion holds two radios. Changing a radio saves immediately. Catalog Save is separate.

  • Include this cascade layer wrapper when published widgets are rendered. A saved layer wraps the class stylesheet. This is the default.
  • My apps already put these utilities in a layer. Do not wrap them again when the widget is being rendered. Published widgets still carry class definitions, but RuleCMS does not wrap them. Your host stylesheet already owns cascade.
Composer and Preview still wrap when inclusion is off. Only the published (and Development-draft) embed on your site emits classes unlayered.
If you turn inclusion off, the host must already layer those utilities. Unlayered RuleCMS classes will fight the host pane by stylesheet order again.

How a published widget receives the setting

Hosts already fetch the widget once. RuleCMS hangs the setting on that same response as a sibling of the widget and its class definitions — not folded into itemList. The fields are classLayer and, when wrapping is off, includeClassLayer: false.

{
  "success": true,
  "data": {
    "widget": { "publishedKey": "…", "itemList": "…", "…": "…" },
    "childCollections": { },
    "classDefinitions": {
      "rounded-xl": "border-radius: var(--radius-xl);"
    },
    "classLayer": "utilities"
  }
}

classLayer is omitted when the setting is empty, when inclusion is off, or if the catalog cannot be read. When inclusion is off, the same response also sends includeClassLayer: false so renderers that still receive a layer name must not wrap. Missing on the payload means include (legacy clients). The widget still loads.

The React renderer (@rulecms/widget-react) and the HTML custom element wrap the existing class stylesheet, for example:

@layer utilities {
  [data-rulecms-published-key="env---w"] .rounded-xl {
    border-radius: var(--radius-xl);
  }
}

Good to know

  • One setting per project. Not per environment, not per widget. At most one layer entry.
  • This is not generic @layer authoring. You cannot name a layer reset or write a layer-order list.
  • React and the HTML embed this pass. Other framework SDKs do not wrap class emit yet.
  • Leave the setting empty if unlayered emit is what you want. Class names still work. Nothing extra is sent.

Related docs