Introduction
StyleX compiles style definitions into CSS during the frontend build. Fluid
templates run later, on the server, and cannot call stylex.. The
connector closes that gap with a manifest file.
What is StyleX?
StyleX is a compile-time CSS-in-JS library developed by Meta (Facebook) and deployed in high-scale production applications including Facebook, Instagram, WhatsApp, and Threads. It is completely framework-agnostic and open source.
The Core Concept
Instead of writing CSS classes or SCSS selector trees, you author styles using JavaScript objects. A build-time compiler (via Babel or unplugin/Vite) transforms supported style declarations into reusable atomic CSS rules. The compiler also produces metadata used by StyleX APIs and, in TYPO3, by a compatible Connector manifest producer. Do not depend on generated class names in templates or source code.
There is zero runtime style injection in the browser. The output is a standard static .css file.
// What you write (components/nav.stylex.js):
import * as stylex from '@stylexjs/stylex';
import { colors } from '../tokens/color-tokens.stylex.js';
import { spacing } from '../tokens/spacing-tokens.stylex.js';
export const styles = stylex.create({
link: {
color: colors.bodyText,
padding: spacing.md,
borderRadius: '4px',
},
active: {
color: colors.primary,
fontWeight: 'bold',
},
});
/* What StyleX emits into the compiled CSS bundle: */
.x1a2b3 { color: #212529; }
.x4c5d6 { padding: 1rem; }
.x7e8f9 { border-radius: 4px; }
.x9g0h1 { color: #ff8700; }
.x2i3j4 { font-weight: 700; }
When two styles are composed (e.g. link and active), both define color. StyleX resolves the conflict at build time (or in PHP via the StyleX Connector) using a deterministic rule: the last style applied wins.
Note
For the connector's manifest loading and class resolution, see Architecture.
Core Advantages of StyleX
Deterministic, Conflict-Free Styling
- The Problem with Traditional CSS/SCSS: The cascade and specificity create implicit ordering dependencies. Adding a class in one SCSS file can unexpectedly override or be overridden by rules in another file based purely on stylesheet order or selector specificity. Furthermore, developers and AI coding assistants alike frequently fail to take the load or bundling order of separate CSS/SCSS files into account, leading to component styles that are quietly and unintentionally overridden by other styles.
- What StyleX Solves: Every CSS property maps to an atomic class with identical specificity (a single class selector). When two style definitions declare conflicting values for the same property, the last applied style strictly wins. Import order and stylesheet load order no longer dictate which rule applies, completely eliminating specificity battles, silent cascade overrides, and
!importanthacks.
Atomic CSS and token reuse
StyleX compiles declared styles into atomic CSS and deduplicates equivalent declarations across the build. CSS size follows the unique rules the project uses; it is not tied one-to-one to the number of source files or components. Do not rely on a fixed growth curve. Keep styles statically discoverable and import only the recipes needed by the relevant entrypoint.
Design tokens and themes
Use stylex. for values that need to vary by theme or runtime
scope. Keep token families in separate, named .stylex. modules, then
import the exported variable groups into recipes. StyleX's API abstracts the
generated CSS variable identifiers; consume variables through their exports
instead of hardcoding generated names.
// tokens/color-tokens.stylex.js
import * as stylex from '@stylexjs/stylex';
export const colors = stylex.defineVars({
textPrimary: '#212529',
textInverse: '#ffffff',
accent: '#ff8700',
surface: '#ffffff',
});
// tokens/spacing-tokens.stylex.js
import * as stylex from '@stylexjs/stylex';
export const spacing = stylex.defineVars({
compact: '0.5rem',
normal: '1rem',
spacious: '1.5rem',
});
Import those tokens into component recipes rather than copying values. Use
stylex. for shared values that are not themeable. Create
component-specific token groups only when they form a deliberate reusable
contract; keep one-off layout values in the recipe that uses them.
Use stylex. to override token groups for a named theme.
Keep theme identity separate from color mode: a brand theme such as ocean
can support both light and dark modes, while mode describes the color-scheme
variant. Use semantic token names such as text rather than names
that encode a theme or mode.
// themes/ocean-theme.stylex.js
import * as stylex from '@stylexjs/stylex';
import { colors } from '../tokens/color-tokens.stylex.js';
export const oceanTheme = stylex.createTheme(colors, {
accent: '#006b91',
surface: '#f3fbff',
});
Theme overrides may be sparse when omitted values inherit from a parent theme. Check every independently themed subtree and nested theme boundary so all consumed variables resolve to the intended values. If a surface can render outside its normal parent, provide a complete set of needed values or a safe default.
The connector resolves manifest keys; it does not infer keys from token or
theme source files. A theme class used in server-rendered Fluid must be present
in the manifest, for example as theme.. The maintained Vite adapter
documents static compiled stylex. styles; check whether the
selected manifest producer also exports create classes. If it
does not, add a consumer adapter that emits semantic theme keys or apply the
theme in a JavaScript-owned surface. Validate theme keys with
stylex:.
Dead Style Elimination
Because all style rules are imported and referenced as ES modules in JavaScript, bundlers like Vite and Rollup can automatically tree-shake unused .stylex. files or unreferenced style exports. Removing a TYPO3 component or retiring an obsolete element automatically removes its CSS from the production bundle.
Style Encapsulation Without a Component Framework
StyleX does not provide CSS-Module-style selector scoping: generated class selectors exist in the shared stylesheet. Encapsulation comes from applying the generated classes only to the intended elements and composing styles through StyleX. Keep generated class strings out of templates, and do not treat a recipe module as a selector namespace. See StyleX authoring and themes for source and key naming.
Conditional Styling via Pure Logic
Conditional styles do not require brittle class-string concatenations. With EXT:, conditional styling in Fluid templates is declarative:
<f:link.page
class="{stylex:class(styles: 'Nav.link', when: {isActive: 'Nav.active'})}"
pageUid="{item.data.uid}"
>
{item.title}
</f:link.page>
The ViewHelper resolves 'Nav. and, if the template variable is evaluates to true, layers 'Nav. on top, cleanly overriding conflicting properties.
CSS Layers (@layer) — Taming Specificity
StyleX supports native CSS Cascade Layers (use), grouping atomic classes inside @layer stylex. When third-party frameworks like Bootstrap are also compiled into layers, an initial declaration:
@layer bootstrap, stylex, overrides;
guarantees that StyleX styles override Bootstrap without requiring higher selector specificity or !important.
However, in many projects (including standard TYPO3 setups), Bootstrap is loaded unlayered (via CDN or standard JS bundle import). In CSS Cascade Level 5, unlayered styles take precedence over layered styles (Unlayered > Layered). To handle this, StyleX provides a powerful alternative: disabling CSS layers (use).
When use, the StyleX compiler automatically appends a :not pseudo-class selector to every atomic class (e.g. .x1a2b3:). This bumps the selector specificity from (0,1,0) to (0,2,0), allowing StyleX atomic rules to cleanly override Bootstrap's unlayered element or single-class rules without cascade layers.
Future-Proof Architecture (Headless Ready)
If a TYPO3 project transitions toward a hybrid or headless architecture (e.g. TYPO3 headless with React, Next.js, Vue, or Web Components), the .stylex. source files can be used directly by those frontend frameworks without rewriting a single line of CSS.
StyleX Compared to Bootstrap CSS
Bootstrap provides a comprehensive UI kit and 12-column grid. StyleX is an authoring system, not a component library.
| Dimension | Bootstrap CSS | StyleX |
|---|---|---|
| Paradigm | Pre-built utility classes & component CSS | Compile-time atomic CSS-in-JS |
| Specificity | Deep selector chains (.navbar-) | Flat atomic selectors with :not bump (.x1abc:) |
| Bundle Size | Full bundle shipped ( 30-60 KB min+gz) | Only used property-value rules emitted |
| Custom Overrides | Requires fighting the cascade or using !important | Deterministic property override + Specificity Bump |
| Tokens | SCSS variable overrides | Typed define generating CSS Custom Properties |
Possible Coexistence in TYPO3
Bootstrap provides the responsive layout grid and JavaScript components (modals, collapse). StyleX powers custom components and design system styling, overriding Bootstrap visual styles cleanly either via :not specificity bumping (use) or via @layer when Bootstrap is layered.
StyleX Compared to Tailwind CSS
Tailwind CSS uses utility classes in HTML markup (class="flex items-). StyleX defines styles in JavaScript objects and applies atomic classes through compiled references.
| Feature | Tailwind CSS | StyleX |
|---|---|---|
| HTML Markup | Long, verbose class attribute strings | Clean template attributes (styles: 'Button.) |
| Conflict Resolution | Depends on stylesheet generation order | Deterministic: last argument strictly wins |
| Design Constraint | Arbitrary values easy to slip in (bg-) | Static build enforcement against token definitions |
| CSS Purging | Regex-based source file scanning (safelisting needed) | Native module graph tree-shaking |
| Typing | Editor extensions (Tailwind CSS IntelliSense) | Native TypeScript / JavaScript type safety |
The Astryx Design System
Astryx is Meta’s open-source design system built on StyleX. It provides over 170 accessible, themeable components used internally across Meta products.
Because Astryx is authored entirely in StyleX, its design tokens, color ramps, and atomic CSS share the exact same compiler pipeline as custom StyleX code. For TYPO3, Astryx tokens can serve as the design token baseline in tokens., unifying custom Fluid components with Meta's production-tested accessibility and dark-mode foundation.
StyleX and AI / LLM-Assisted Development
Modern development workflows increasingly leverage AI coding assistants (Cursor, Claude, Codex, GitHub Copilot). StyleX delivers substantially higher accuracy and fewer hallucinations when generated by LLMs:
- Typed Objects vs. Hallucinated Strings: In Tailwind or Bootstrap, an LLM might generate plausible-looking but non-existent class strings (such as
bg-orblue- 6000 text-). StyleX styles are typed JavaScript objects; invalid properties fail at build time.primary- semibold - Constrained Solution Space: When an AI assistant reads
tokens., it is constrained to valid token properties (stylex. js colors.,primary spacing.), preventing design system drift.lg - Natural Context Co-location: A single component's styling lives entirely within its
.stylex.file, fitting cleanly within an LLM's context window.js - Predictable Logic: The rule that "the second argument overrides conflicting properties of the first" is easy for LLMs to reason about mathematically without simulating the browser CSS cascade.
- Immunity to CSS/SCSS Load-Order Blindness: LLMs typically generate styles in component isolation and notoriously struggle to anticipate the implicit load, import, or concatenation order of CSS/SCSS files across a project. In traditional stylesheets, an LLM frequently produces selectors that look correct in isolation but are quietly and unintentionally overridden by rules from other stylesheets loaded later in the document head or build sequence. With StyleX's atomic architecture and flat specificity, load order does not dictate style precedence. Conflicts are resolved deterministically at the call site (
stylex./props () {stylex:), ensuring LLM-generated component styles render as intended without accidental cascade overrides.class ()}
AI Agent Workflows & typo3-stylex Skill
When working with an AI agent or coding assistant (such as Antigravity, Cursor, or Claude Code), installing the typo3- Skill can be useful. It provides the agent with dedicated instructions, best practices, and integration workflows for installing, configuring, and verifying skom/, Vite asset pipelines, and atomic styling in TYPO3.
The typo3- Skill can be found in the ai-typo3-integrator-plugin at the following URL:
https://github.com/Starraider/ai-typo3-integrator-plugin/tree/main/skills/typo3-stylex
StyleX Benefits for TYPO3 Content Blocks
The TYPO3 Content Blocks initiative (friendsoftypo3/ / TYPO3 Core Content Blocks in v14) provides a declarative, directory-based format for structuring custom content elements. While Content Blocks conventionally loads individual frontend. files via <f:, combining Content Blocks with StyleX via EXT: elevates the architecture to enterprise-grade web performance.
Atomic CSS reuse across components
StyleX can reuse identical compiled declarations across recipes. The final CSS size depends on the distinct declarations, variants, selectors and build entries required by the application. Avoid predicting a fixed linear or logarithmic growth curve. Multiple Content Blocks may use repeated declarations such as:
- Card, Testimonial, and Teaser all define
padding: 1.5rem; - Hero, Banner, and FeatureGrid all define
display: flex; align-items: center; - Multiple buttons across different blocks define identical border radii and transitions.
The StyleX Advantage:
- Repeated declarations can share compiled atomic rules within the same delivered build output.
- New blocks still add CSS when they introduce new declarations, variants or responsive states.
- Measure the production bundle rather than assuming that adding blocks has negligible cost.
Strict Brand & Design Token Adherence
Independent Content Block CSS files are notorious for design drift: developers copy-paste arbitrary hex colors (#1a73e8), custom paddings (18px), and inconsistent font sizes into separate frontend. files.
The StyleX Advantage:
-
Content Blocks import typed design tokens directly from the sitepackage:
import * as stylex from '@stylexjs/stylex'; import { colors } from '../../../../Resources/Private/JavaScript/StyleX/tokens/color-tokens.stylex.js'; import { spacing } from '../../../../Resources/Private/JavaScript/StyleX/tokens/spacing-tokens.stylex.js'; import { shape } from '../../../../Resources/Private/JavaScript/StyleX/tokens/shape-tokens.stylex.js'; import { typography } from '../../../../Resources/Private/JavaScript/StyleX/tokens/typography-tokens.stylex.js'; export const styles = stylex.create({ root: { backgroundColor: colors.surface, padding: spacing.spacious, borderRadius: shape.radiusMedium, }, title: { fontFamily: typography.fontFamily, fontSize: typography.sizeXl, color: colors.accent, }, });Copied! - Compile-Time Validation: Any mistyped token (
colors.) or invalid CSS property is flagged immediately duringprimry npm run buildorddev vite. - Consistent rebranding: Updating a shared semantic token updates recipes that consume it after the relevant build output is regenerated.
Deterministic Variant Composition in Fluid
Content Blocks frequently provide backend select boxes or checkboxes for visual variants (e.g. background theme, highlighted state, alignment).
In traditional CSS, this requires fragile string concatenation:
<div class="cb-card {f:if(condition: isFeatured, then: 'cb-card--featured')} {f:if(condition: isDark, then: 'cb-card--dark')}">
This pattern frequently breaks down when .cb- and .cb- fight over the same CSS properties (e.g. border- or color) because selector specificity and declaration order in the CSS file dictate the winner.
The StyleX Advantage:
-
Handled cleanly via the connector's Fluid ViewHelper:
<div class="{stylex:class( styles: 'Card.root', when: {isFeatured: 'Card.featured', isDark: 'Card.dark'} )}">Copied! - The PHP
Stylexresolves property collisions deterministically: the last active style strictly wins on a per-property level. There are no class collision bugs or specificity fights.Manifest Service
Coexistence with Third-Party & Vendor Content Blocks
Projects do not have to rewrite every Content Block into StyleX:
- Custom In-House Blocks: Authored in StyleX for maximum performance and token integration.
- Third-Party / Marketplace Blocks: Load their pre-compiled
frontend.files cleanly isolated within CSS Cascade Layers (css @layer vendor-).blocks, stylex; - Sitepackage StyleX utility classes can deterministically override vendor Content Block styling when customized branding is required, without resorting to
!important.
Tip
For Vite glob discovery and migration guidance, see Content Blocks.
The build writes stylex-. Its styles object maps a style
key to a class and, when available, a compiler conflict map. TYPO3
loads the manifest and the ViewHelper writes the resolved classes into a
class attribute.
StyleX source -> Vite build -> stylex-manifest.json
|
v
Fluid template <- StyleX Connector <- registered manifest
Requirements
The extension targets TYPO3 12.4, 13.4, and 14.3 or later within their
respective major lines. It requires PHP 8.1 through 8.4 and
typo3/ in the same supported TYPO3 range.
The sitepackage also needs a frontend build that produces a compatible manifest. The connector does not compile StyleX source files and it does not provide a Vite configuration.
What the extension provides
Stylexregisters one or more manifest paths.Registry Stylexloads and caches the merged manifest data.Manifest Service stylex:resolves base, conditional, and fallback style keys in Fluid.class - A Site Set and TypoScript files can include the optional CSS delivery and standalone stylesheet ordering.
- An optional maintained static Vite adapter produces versioned manifests.
stylex:checks required keys, collisions and declared CSS hashes.validate
The ViewHelper namespace is registered globally by ext_.
Templates can therefore use {stylex: without declaring the
namespace themselves.
For source organization, token naming, themes and CSS boundaries, see StyleX authoring and themes. For the StyleX API, read the StyleX documentation.