Guides

Tailwind on Lynx

Why Lynx apps are pinned to Tailwind v3, what the Lynx preset actually does to your utility set, and how to run v3 and v4 in the same repository.

Lynx apps have to use Tailwind v3. Every current tutorial and npm create template hands you v4, which then either errors on the Lynx preset or builds a stylesheet missing most of what you wrote.

As of 25 July 2026 the latest @lynx-js/tailwind-preset on npm is 0.5.0, and it still declares peerDependencies: { tailwindcss: "^3.4.0" }, unchanged from 0.4.0. The next two sections explain why, and the fix itself is further down.

What the Lynx preset actually does

Lynx renders through its own CSS engine, which implements a subset of CSS. A class emitting float: left or --tw-ring-shadow becomes a silent no-op rather than an error, so the preset uses an allowlist to stop those utilities existing:

// inside @lynx-js/tailwind-preset
corePlugins: DEFAULT_CORE_PLUGINS  // an array, not an object

Passing an array to corePlugins in Tailwind v3 means enable only these. DEFAULT_CORE_PLUGINS holds 57 entries against the 179 core plugins v3 ships, so roughly two thirds of Tailwind is off before your config is read. Flexbox, sizing, spacing, colors, typography, borders, opacity, and z-index survive. Floats, most positioning, and the whole ring family do not, which is why a focus ring on Lynx comes from a spread-only box-shadow instead of ring-2.

Everything else sits on ordinary plugin APIs, with matchUtilities and addUtilities called around 28 times each, matchVariant five times, and addBase twice, adding Lynx-specific utilities and the ui-* variants that stand in for data-[state] selectors.

Why the preset has not been ported to v4

Tailwind v4 removed corePlugins. Searching the published [email protected] package for the string finds nothing, because v4 has no way to disable parts of the utility set, so every utility is always available.

The rest would mostly port, since matchUtilities, addUtilities, matchVariant, and addBase all still exist in v4, and moving configuration from a JavaScript presets array to CSS-first @theme blocks is disruptive but tractable. The allowlist has no successor, so the preset's central job cannot be expressed in v4 as it stands.

The Lynx side cannot fix that alone. Either Tailwind reintroduces a way to restrict the emitted utility set, or the preset post-processes the generated CSS to strip what the engine will not understand, and both are real work rather than a version bump. The tracking issue has stayed open since May.

This answer has a shelf life, so check that issue before assuming v4 is still blocked.

Running both versions in one repo

The constraint follows the rendering engine rather than the repository, so a monorepo does not have to pick one version. Vy UI runs both:

PackageTailwindWhy
@vyui/kit^3.4.0Compiles for the Lynx CSS engine
Example apps (7)^3.4.17Lynx apps
Docs site^4.0.0A browser target, so no preset

pnpm and other content-addressed installers handle the duplication without complaint, since the two versions never meet in a single module graph.

What to do today

Pin v3 explicitly in any package that builds for Lynx, and use the v3 PostCSS pipeline rather than v4's:

package.json
{
  "devDependencies": {
    "tailwindcss": "^3.4.17",
    "@lynx-js/tailwind-preset": "^0.5.0",
    "rsbuild-plugin-tailwindcss": "^0.2.4"
  }
}

@tailwindcss/postcss, @tailwindcss/vite, and @tailwindcss/cli are the usual accidental route back to v4, because they are v4-only and pull it in behind you.

Spacing in v3 has no half-steps above 3.5, so size-4.5 and p-6.5 compile to nothing rather than failing, and an arbitrary value like size-[18px] is the fix. Classes built dynamically, such as `bg-${color}-500`, need a safelist because they cannot be statically extracted, and a missing class on Lynx is invisible rather than merely unstyled.

Our installation guide covers the preset wiring, including the uiVariants registration behind the ui-* state classes.

Verified against @lynx-js/[email protected] and [email protected] on 25 July 2026. Issue #5 tracks any movement.

Installation

Wiring the Lynx and Vy UI presets together.

Theming

Semantic tokens, and the single-level var() constraint on device.

Testing on your phone

Where styling that works in the browser stops working on device.