Open-Source Wikis

/

Tailwind CSS

/

Packages

/

@tailwindcss/browser

tailwindlabs/tailwindcss

@tailwindcss/browser

Active contributors: Robin, Philipp, Jordan

Purpose

A self-contained Tailwind build that runs entirely in the browser. Drop a <script> tag, write <style type="text/tailwindcss">…</style> blocks, and the bundle compiles them on the fly while watching the DOM for changes. The bundle ships as a single global IIFE (./dist/index.global.js).

It is the only Node-free production consumer of the compiler — the tailwindcss package's zero-runtime-dependency design exists in part for this package.

Directory layout

packages/@tailwindcss-browser/
├── package.json                # main: ./dist/index.global.js
├── README.md
├── tsconfig.json
├── tsup.config.ts              # output: iife, minify
├── playwright.config.ts        # UI tests
├── src/
│   ├── index.ts                # The browser orchestrator (~7,000 bytes)
│   ├── assets.ts               # Inlines preflight.css, theme.css, utilities.css, index.css
│   ├── instrumentation.ts      # Performance API instrumentation
│   └── types.d.ts
└── tests/
    └── (Playwright spec files)

How it works

graph TD
    Boot[Page load] --> Init[index.ts top-level]
    Init -->|find STYLE_TYPE styles| Read[Read all style[type='text/tailwindcss'] tags]
    Read -->|inject @import 'tailwindcss' if missing| Compile[tailwindcss.compile]
    Compile --> Build[Build CSS from collected classes]
    Build --> Inject[<style> output]
    Boot --> Observe[MutationObserver on documentElement]
    Observe -->|class change| Incr[Incremental rebuild]
    Observe -->|new <style type='text/tailwindcss'>| Full[Full rebuild + recompile]
    Full --> Compile
    Incr --> Build

Two observers run continuously:

  1. A MutationObserver on document.documentElement watching:
    • attributeFilter: ['class'] — re-collect classes from changed elements (incremental rebuild).
    • childList: true + subtree: true — detect new <style type="text/tailwindcss"> tags (full rebuild).
  2. A second MutationObserver on each individual <style> block watching for content changes (characterData, subtree).

Whenever a rebuild is queued, the work is serialized through a buildQueue Promise so concurrent rebuilds collapse safely.

Asset loading

Because there's no filesystem, the browser build inlines the Tailwind asset CSS files at bundle time. assets.ts exports assets.css.index, assets.css.preflight, assets.css.theme, and assets.css.utilities as string constants. The loadStylesheet callback handed to tailwindcss.compile returns these strings for the canonical asset IDs (tailwindcss, tailwindcss/preflight, ./preflight.css, etc.).

loadModule always throws — plugins and JS configs are not supported in the browser bundle.

What's missing vs. the Node adapters

  • No file scanning. Classes come from document.querySelectorAll('[class]'), not the Rust scanner.
  • No @plugin, no @config. loadModule rejects the call.
  • No @import resolution beyond the built-in assets. The bundle throws "The browser build does not support @import for """ for unknown IDs.
  • No source maps. They aren't useful in this mode and the bundler skips them.
  • No optimization step. No Lightning CSS in the bundle.

Performance instrumentation

packages/@tailwindcss-browser/src/instrumentation.ts reports timings to the browser performance timeline. Open DevTools → Performance, record a load, and you'll see Tailwind: Compile, Tailwind: Build, Tailwind: Reading Stylesheets, and per-build markers. This makes it easy to see how much rendering cost the framework is adding to a page.

Tests

packages/@tailwindcss-browser/tests/ runs Playwright UI tests (pnpm test:ui includes them). They drive a real browser via listhen (a small HTTP-server library) plus h3 (a route handler) and assert that DOM mutations result in the expected CSS being injected.

Integration points

  • Depends only on tailwindcss (workspace) at runtime. Devs use h3/listhen for the test harness.
  • Bundles into a single global IIFE. The package's main and browser fields both point at ./dist/index.global.js.
  • Has no peerDependencies. Anyone with a script tag can load it.

Entry points for modification

  • Add support for a new asset import (e.g. tailwindcss/forms): edit loadStylesheet in index.ts to recognize the ID, and add the file's content to assets.ts.
  • Change rebuild scheduling: edit the MutationObserver callbacks in index.ts. The buildQueue Promise is the serialization point.
  • Add new instrumentation timings: extend instrumentation.ts; the class wraps performance.mark and performance.measure.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

@tailwindcss/browser – Tailwind CSS wiki | Factory