PHPackages                             tailwindphp/tailwindphp - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. tailwindphp/tailwindphp

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

tailwindphp/tailwindphp
=======================

A full port of TailwindCSS 4.x to PHP

v1.4.1(1w ago)192.5k↓78.2%6[2 PRs](https://github.com/dnnsjsk/tailwindphp/pulls)1MITPHPPHP ^8.2CI passing

Since Dec 4Pushed 6d agoCompare

[ Source](https://github.com/dnnsjsk/tailwindphp)[ Packagist](https://packagist.org/packages/tailwindphp/tailwindphp)[ Docs](https://github.com/dnnsjsk/tailwindphp)[ RSS](/packages/tailwindphp-tailwindphp/feed)WikiDiscussions main Synced 1w ago

READMEChangelogDependencies (16)Versions (14)Used By (1)

🐘 TailwindPHP
=============

[](#-tailwindphp)

**A 1:1 port of TailwindCSS 4.x to PHP**

Generate Tailwind CSS using pure PHP — no Node.js required.

[![TailwindCSS](https://camo.githubusercontent.com/3bc862bada4e73f397090f0abe1926dad47cd9bc438b25d934985374edf97b48/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5461696c77696e644353532d76342e332e302d3338626466383f6c6f676f3d7461696c77696e64637373266c6f676f436f6c6f723d7768697465)](https://github.com/tailwindlabs/tailwindcss)[![PHP](https://camo.githubusercontent.com/68f08f50b4e992f78f1f52f8343e8bd003f5d3e5cdb32f5695cf690b04386a96/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048502d382e322b2d3737374242343f6c6f676f3d706870266c6f676f436f6c6f723d7768697465)](https://php.net)[![Tests](https://github.com/dnnsjsk/tailwindphp/actions/workflows/tests.yml/badge.svg)](https://github.com/dnnsjsk/tailwindphp/actions/workflows/tests.yml)[![Code Quality](https://github.com/dnnsjsk/tailwindphp/actions/workflows/code-quality.yml/badge.svg)](https://github.com/dnnsjsk/tailwindphp/actions/workflows/code-quality.yml)

[![clsx](https://camo.githubusercontent.com/0843917e7de02195461aaed7c15194fefe8e4913225af1804b7475e440d6a8c0/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f636c73782d76322e312e312d626c7565)](https://github.com/lukeed/clsx)[![tailwind-merge](https://camo.githubusercontent.com/191599028f0e6fd6346cead3c254af312bb04f692e749088796c2adffc06e82f/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f7461696c77696e642d2d6d657267652d76332e342e302d626c7565)](https://github.com/dcastil/tailwind-merge)[![cva](https://camo.githubusercontent.com/db0dc5a8849a4a5ddc6da85c70848e0a2fbea6134b9b736f46dd9ac95c8b77c1/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6376612d76312e302e302d2d626574612e342d626c7565)](https://github.com/joe-bell/cva)[![tw-animate-css](https://camo.githubusercontent.com/af393770a9ec66f8d175950b7c7c7a60390fc50e5e14dcd309eb5799aa55a5dd/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f74772d2d616e696d6174652d2d6373732d76312e342e302d626c7565)](https://github.com/Wombosvideo/tw-animate-css)

> **Built with AI** — This entire codebase (57,000+ lines, 4,000+ tests) was generated using [Claude Code](https://claude.ai/code). No manual coding was done.

Why This Exists
---------------

[](#why-this-exists)

TailwindCSS is written in TypeScript and requires Node.js. TailwindPHP is a complete rewrite in PHP, giving you the same functionality without the Node.js dependency.

- **WordPress &amp; PHP frameworks** — Ship Tailwind-powered plugins and themes without requiring users to install Node.js or run build tools. Just `composer require` and go. See [TailwindWP](https://github.com/dnnsjsk/tailwindwp) for a boilerplate WordPress block editor integration.
- **Dynamic CSS** — Generate utility CSS at runtime based on user input, database content, or template variables.
- **Simpler deployment** — No Node.js in your production stack, no build step in CI, no npm in your Docker image.

Similar to how [scssphp](https://github.com/scssphp/scssphp) brought SCSS compilation to PHP, TailwindPHP brings the full Tailwind 4.x feature set to any PHP environment.

### Batteries Included

[](#batteries-included)

Building TailwindPHP created an opportunity to unify the Tailwind ecosystem's best tools into a single package. The JavaScript world relies on several companion libraries that are essential to any serious Tailwind project — so we ported them too:

- **[clsx](https://github.com/lukeed/clsx)** — Conditionally construct class strings (`cn('btn', isActive && 'btn-active')`)
- **[tailwind-merge](https://github.com/dcastil/tailwind-merge)** — Intelligently merge classes without conflicts (`merge('p-2', 'p-4')` → `'p-4'`)
- **[CVA](https://github.com/joe-bell/cva)** — Create component variants declaratively (`variants(['size' => ['sm', 'md', 'lg']])`)

Table of Contents
-----------------

[](#table-of-contents)

- [Why This Exists](#why-this-exists)
- [Scope](#scope)
- [Status](#status)
- [Installation](#installation)
- [CLI](#cli)
- [Usage](#usage)
    - [Importing CSS Files](#importing-css-files)
    - [Preflight](#preflight)
    - [Minification](#minification)
    - [Caching](#caching)
- [API](#api)
    - [tw::generate()](#twgenerate)
    - [tw::compile()](#twcompile)
    - [tw::properties()](#twproperties)
    - [tw::computedProperties()](#twcomputedproperties)
    - [tw::value()](#twvalue)
    - [tw::computedValue()](#twcomputedvalue)
    - [tw::extractCandidates()](#twextractcandidates)
    - [tw::minify()](#twminify)
    - [tw::clearCache()](#twclearcache)
    - [tw::colors()](#twcolors)
    - [tw::breakpoints()](#twbreakpoints)
    - [tw::spacing()](#twspacing)
    - [Input Formats](#input-formats)
    - [TailwindCompiler Instance Methods](#tailwindcompiler-instance-methods)
- [Classname Utilities](#classname-utilities)
    - [cn()](#cn)
    - [merge()](#merge)
    - [join()](#join)
- [Variants (CVA Port)](#variants-cva-port)
    - [variants()](#variants)
    - [compose()](#compose)
- [Plugin System](#plugin-system)
    - [Built-in Plugins](#built-in-plugins)
    - [Plugin Options](#plugin-options)
    - [Creating Custom Plugins](#creating-custom-plugins)
- [How It Works](#how-it-works)
    - [Architecture](#architecture)
    - [Port Deviation Markers](#port-deviation-markers)
- [Testing](#testing)
- [Development](#development)
- [License](#license)
- [Credits](#credits)

Scope
-----

[](#scope)

TailwindPHP provides full CSS compilation with support for both inline CSS and file-based imports.

```
// Inline CSS with Tailwind directives
$css = tw::generate('', '@import "tailwindcss"; @theme { --color-brand: #3b82f6; }');

// File-based imports
$css = tw::generate([
    'content' => '',
    'importPaths' => '/path/to/styles.css',
]);
```

**What's included:**

- All CSS compilation features (utilities, variants, directives, functions)
- File-based `@import` resolution via `importPaths` option
- Virtual modules (`tailwindcss`, `tailwindcss/preflight`, `tailwindcss/utilities`, `tw-animate-css`, etc.)
- Preflight CSS reset
- Plugin system with `@tailwindcss/typography`, `@tailwindcss/forms`, and custom plugin support
- `cn()`, `variants()`, `merge()`, `join()` — class name utilities (no separate packages needed)
- No external dependencies beyond PHP

**What's NOT included:**

- IDE tooling — No IntelliSense, autocomplete, or source maps (these are editor features, not CSS compilation)

Status
------

[](#status)

✅ **4,074 tests passing** — Feature complete for core TailwindCSS functionality plus utility libraries.

Test SuiteTestsStatusCore (utilities, variants, integration)1,322✅API Coverage (utilities, modifiers, variants, directives, plugins)1,774✅API (tw::generate, tw::compile, tw::properties, tw::computedProperties, etc.)140✅PHP-specific unit tests (theme, design-system, utils, helpers)300✅Import functionality42✅Edge cases57✅CSS Minifier17✅Plugin system (typography, forms)25✅clsx (from reference test suite)27✅tailwind-merge (from reference test suite)52✅CVA (from reference test suite)50✅tw-animate-css23✅Cache14✅CLI26✅### Performance

[](#performance)

While this is a 1:1 port focused on correctness and maintainability, PHP-specific optimizations are applied where possible:

- **toCss**: Uses array accumulation + implode instead of string concatenation, pre-computed indent strings
- **CSS Parser**: Direct character comparison instead of ord() calls, tracked buffer lengths instead of strlen()

These optimizations maintain identical output while improving performance. TypeScript remains faster due to V8's JIT compilation, but this is expected for build-time CSS generation.

See [benchmarks/](benchmarks/) for detailed comparison.

Installation
------------

[](#installation)

```
composer require tailwindphp/tailwindphp
```

CLI
---

[](#cli)

TailwindPHP includes a command-line interface that is a **1:1 port of [@tailwindcss/cli](https://github.com/tailwindlabs/tailwindcss/tree/next/packages/%40tailwindcss-cli)** - same options, same behavior, no Node.js required.

### Quick Start

[](#quick-start)

```
# Build CSS from an input file
./vendor/bin/tailwindphp -i ./src/app.css -o ./dist/styles.css

# Watch for changes
./vendor/bin/tailwindphp -i ./src/app.css -o ./dist/styles.css --watch

# Build minified
./vendor/bin/tailwindphp -i ./src/app.css -o ./dist/styles.css --minify
```

### Options

[](#options)

```
tailwindphp [--input input.css] [--output output.css] [--watch] [options]

Options:
  -i, --input     Input CSS file (default: @import "tailwindcss")
  -o, --output    Output file (default: stdout)
  -w, --watch     Watch for changes and rebuild as needed
  -m, --minify    Optimize and minify the output
      --optimize  Optimize the output without minifying
      --cwd       The current working directory (default: .)
  -h, --help      Display usage information
```

### Input CSS

[](#input-css)

Create an `app.css` file with your Tailwind imports and `@source` directive:

```
@import "tailwindcss";
@source "./templates";  /* Directory to scan for classes */
```

The `@source` directive tells TailwindPHP where to find your template files. It supports:

- Directories: `@source "./templates";`
- Glob patterns: `@source "./src/**/*.php";`
- Multiple sources: Add multiple `@source` directives

### Examples

[](#examples)

```
# Build from CSS with @source directive
tailwindphp -i ./src/app.css -o ./dist/styles.css

# Build minified for production
tailwindphp -i ./src/app.css -o ./dist/styles.css -m

# Watch mode with minification
tailwindphp -i ./src/app.css -o ./dist/styles.css -w -m

# Use a different working directory
tailwindphp -i app.css -o dist/styles.css --cwd=/path/to/project
```

### Global Installation

[](#global-installation)

Install globally to use `tailwindphp` from anywhere:

```
composer global require tailwindphp/tailwindphp

# Now available globally
tailwindphp -i ./src/app.css -o ./dist/styles.css
```

Usage
-----

[](#usage)

### Basic Usage

[](#basic-usage)

The simplest way to use TailwindPHP is with the `generate()` function:

```
use TailwindPHP\tw;

// Generate CSS from HTML containing Tailwind classes
$css = tw::generate('Hello');
```

This parses the HTML, extracts class names, and generates only the CSS needed.

### Configuration Options

[](#configuration-options)

You can pass configuration as either a second parameter or an array:

```
// Option 1: String as second parameter
$css = tw::generate($html, '@import "tailwindcss"; @theme { --color-brand: #3b82f6; }');

// Option 2: Array with 'content' and 'css' keys
$css = tw::generate([
    'content' => 'Hello',
    'css' => '
        @import "tailwindcss";

        @theme {
            --color-brand: #3b82f6;
            --font-heading: "Inter", sans-serif;
        }

        .btn {
            @apply px-4 py-2 rounded-lg bg-brand text-white;
        }
    '
]);
```

### Importing CSS Files

[](#importing-css-files)

Use `importPaths` to load CSS from the filesystem with full `@import` resolution:

```
// Single file
$css = tw::generate([
    'content' => 'Hello',
    'importPaths' => '/path/to/styles.css',
]);

// Directory (loads all .css files alphabetically)
$css = tw::generate([
    'content' => 'Hello',
    'importPaths' => '/path/to/css/',
]);

// Multiple paths
$css = tw::generate([
    'content' => 'Hello',
    'importPaths' => [
        '/path/to/base.css',
        '/path/to/components/',
    ],
]);

// Combine with inline CSS
$css = tw::generate([
    'content' => 'Hello',
    'css' => '.custom { color: red; }',
    'importPaths' => '/path/to/styles.css',
]);
```

**Nested imports are resolved automatically.** If your CSS file contains `@import "./buttons.css"`, TailwindPHP resolves the path relative to the importing file.

```
/* /path/to/styles.css */
@import "tailwindcss";
@import "./components/buttons.css";
@import "./components/cards.css";

@theme {
    --color-brand: #3b82f6;
}
```

**Deduplication:** Multiple imports of the same file or virtual module (like `@import "tailwindcss"`) are automatically deduplicated.

**Custom resolver:** For advanced use cases (virtual file systems, databases), provide a callable:

```
$css = tw::generate([
    'content' => 'Hello',
    'importPaths' => function (?string $uri, ?string $fromFile): ?string {
        if ($uri === null) {
            return '@import "tailwindcss"; @import "custom.css";';
        }
        if ($uri === 'custom.css') {
            return '.virtual-class { color: purple; }';
        }
        return null; // Unknown imports are silently skipped
    },
]);
```

### Preflight

[](#preflight)

Preflight is Tailwind's opinionated set of base styles, built on top of [modern-normalize](https://github.com/sindresorhus/modern-normalize). It smooths over cross-browser inconsistencies and makes it easier to work within the constraints of the design system.

For full details on what Preflight does and why, see the [official Tailwind Preflight documentation](https://tailwindcss.com/docs/preflight).

**Key resets include:**

- **Default margins removed** — Headings, paragraphs, lists, etc. have zero margin
- **Headings unstyled** — All headings have the same font-size and font-weight as normal text
- **Lists unstyled** — `ul` and `ol` have no bullets/numbers or padding
- **Images are block-level** — No more phantom space below images
- **Border styles reset** — Empty borders so you can add borders just by setting `border-width`
- **Buttons inherit fonts** — Buttons use the parent's font family, size, and line-height
- **Hidden elements stay hidden** — Elements with a `hidden` attribute are invisible unless using `hidden="until-found"`

```
// Full import (includes theme + preflight + utilities)
$css = tw::generate([
    'content' => 'Hello',
    'css' => '@import "tailwindcss";',
]);
```

#### Extending Preflight

[](#extending-preflight)

Add your own base styles on top of Preflight using `@layer base`:

```
$css = tw::generate([
    'content' => 'TitleContent',
    'css' => '
        @import "tailwindcss";
        @layer base {
            h1 { font-size: var(--text-2xl); }
            h2 { font-size: var(--text-xl); }
            a { color: var(--color-blue-600); text-decoration-line: underline; }
        }
    ',
]);
```

#### Disabling Preflight

[](#disabling-preflight)

To disable Preflight — for example when integrating into an existing project or defining your own base styles — import only the parts of Tailwind you need.

By default, `@import "tailwindcss"` is equivalent to:

```
@layer theme, base, components, utilities;
@import "tailwindcss/theme.css" layer(theme);
@import "tailwindcss/preflight.css" layer(base);
@import "tailwindcss/utilities.css" layer(utilities);
```

To skip Preflight, simply omit its import:

```
$css = tw::generate([
    'content' => 'Hello',
    'css' => '
        @layer theme, base, components, utilities;
        @import "tailwindcss/theme.css" layer(theme);
        @import "tailwindcss/utilities.css" layer(utilities);
    ',
]);
```

#### Import Modifiers

[](#import-modifiers)

When importing Tailwind's files individually, modifiers like `prefix()`, `theme()`, and `important` should go on their respective imports:

```
/* Prefix affects both theme variables and utilities */
@import "tailwindcss/theme.css" layer(theme) prefix(tw);
@import "tailwindcss/utilities.css" layer(utilities) prefix(tw);

/* important affects utilities */
@import "tailwindcss/utilities.css" layer(utilities) important;

/* theme(static) or theme(inline) affects theme variables */
@import "tailwindcss/theme.css" layer(theme) theme(static);
```

### Extract Class Names

[](#extract-class-names)

If you need to extract Tailwind class names from content separately:

```
use TailwindPHP\tw;

$classes = tw::extractCandidates('');
// ['flex', 'p-4', 'bg-blue-500']
```

### Minification

[](#minification)

Minify CSS output for production:

```
use TailwindPHP\tw;

// Option 1: Minify during generation
$css = tw::generate([
    'content' => 'Hello',
    'minify' => true,
]);

// Option 2: Minify separately
$css = tw::generate('Hello');
$minified = tw::minify($css);
```

The minifier removes comments, collapses whitespace, shortens hex colors (`#ffffff` to `#fff`), removes units from zero values (`0px` to `0`), and other optimizations.

### Caching

[](#caching)

Enable file-based caching to avoid recompiling identical content:

```
use TailwindPHP\tw;

// Cache to default directory (sys_get_temp_dir()/tailwindphp)
$css = tw::generate([
    'content' => 'Hello',
    'cache' => true,
]);

// Cache to custom directory
$css = tw::generate([
    'content' => 'Hello',
    'cache' => '/path/to/cache',
]);

// With TTL (time-to-live in seconds)
$css = tw::generate([
    'content' => 'Hello',
    'cache' => true,
    'cacheTtl' => 3600, // Expire after 1 hour
]);
```

The cache key is computed from the content, CSS configuration, and minify option. Different inputs generate different cache files.

**Clear the cache:**

```
use TailwindPHP\tw;
use function TailwindPHP\clearCache;

// Clear default cache
tw::clearCache();

// Clear custom cache directory
tw::clearCache('/path/to/cache');

// Or use the function
clearCache('/path/to/cache');
```

---

API
---

[](#api)

TailwindPHP provides a comprehensive API for CSS generation and inspection.

### `tw::generate()`

[](#twgenerate)

Generate CSS from HTML content containing Tailwind classes.

**Returns:** `string` - The generated CSS

```
use TailwindPHP\tw;

// String input
$css = tw::generate('');

// String with custom CSS
$css = tw::generate('', '@import "tailwindcss"; @theme { --color-brand: #3b82f6; }');

// Array input
$css = tw::generate([
    'content' => '',
    'css' => '@import "tailwindcss";',
    'minify' => true,
]);
```

### `tw::compile()`

[](#twcompile)

Create a reusable `TailwindCompiler` instance for multiple operations.

**Returns:** `TailwindCompiler` - A reusable compiler instance

```
use TailwindPHP\tw;

// Create compiler with default Tailwind
$compiler = tw::compile();

// Create compiler with custom CSS
$compiler = tw::compile('@import "tailwindcss"; @theme { --color-brand: #3b82f6; }');

// Generate CSS
$css = $compiler->generate('');

// Or minify the output
$minified = $compiler->minify($css);
```

### `tw::properties()`

[](#twproperties)

Get raw CSS properties for a class (unresolved CSS variables).

**Returns:** `array` - Property name to value mapping

```
use TailwindPHP\tw;

// Single class
tw::properties('p-4');
// ['padding' => 'calc(var(--spacing) * 4)']

// Multiple classes (pass as array)
tw::properties(['flex', 'items-center', 'p-4']);
// ['display' => 'flex', 'align-items' => 'center', 'padding' => 'calc(var(--spacing) * 4)']

// From compiler instance
$compiler = tw::compile();
$compiler->properties('p-4');
```

### `tw::computedProperties()`

[](#twcomputedproperties)

Get computed CSS properties with all variables resolved.

**Returns:** `array` - Property name to resolved value mapping

```
use TailwindPHP\tw;

// Static method
tw::computedProperties('p-4');
// ['padding' => '1rem']

tw::computedProperties('text-blue-500');
// ['color' => 'oklch(.546 .245 262.881)']

// Multiple classes (pass as array)
tw::computedProperties(['flex', 'items-center', 'gap-4']);
// ['display' => 'flex', 'align-items' => 'center', 'gap' => '1rem']

// From compiler instance
$compiler = tw::compile();
$compiler->computedProperties('p-4');
// ['padding' => '1rem']
```

### `tw::value()`

[](#twvalue)

Get raw value for a utility class (unresolved).

**Returns:** `?string` - The raw CSS value, or null if utility not found

```
use TailwindPHP\tw;

// Static method
tw::value('p-4');
// 'calc(var(--spacing) * 4)'

tw::value('text-blue-500');
// 'var(--color-blue-500)'

// From compiler instance
$compiler = tw::compile();
$compiler->value('p-4');
```

### `tw::computedValue()`

[](#twcomputedvalue)

Get computed value for a utility class (resolved).

**Returns:** `?string` - The resolved CSS value, or null if utility not found

```
use TailwindPHP\tw;

// Static method
tw::computedValue('p-4');
// '1rem'

tw::computedValue('text-blue-500');
// 'oklch(.546 .245 262.881)'

tw::computedValue('gap-4');
// '1rem'

// From compiler instance
$compiler = tw::compile();
$compiler->computedValue('p-4');
// '1rem'
```

### `tw::extractCandidates()`

[](#twextractcandidates)

Extract Tailwind class names from content.

**Returns:** `array` - Array of extracted class names

```
use TailwindPHP\tw;

tw::extractCandidates('');
// ['flex', 'p-4', 'bg-blue-500']

// From compiler instance
$compiler = tw::compile();
$compiler->extractCandidates('');
// ['flex', 'p-4']
```

### `tw::minify()`

[](#twminify)

Minify CSS output.

**Returns:** `string` - The minified CSS

```
use TailwindPHP\tw;

$css = tw::generate('');
$minified = tw::minify($css);

// From compiler instance
$compiler = tw::compile();
$css = $compiler->generate('');
$minified = $compiler->minify($css);
```

### `tw::clearCache()`

[](#twclearcache)

Clear the CSS cache.

**Returns:** `int` - Number of files deleted

```
use TailwindPHP\tw;

// Clear default cache
tw::clearCache();

// Clear custom cache directory
tw::clearCache('/path/to/cache');
```

### `tw::colors()`

[](#twcolors)

Get all color values from the theme.

**Returns:** `array` - Map of color name to computed value

```
use TailwindPHP\tw;

tw::colors();
// ['red-500' => 'oklch(63.7% 0.237 25.331)', 'blue-500' => 'oklch(62.3% 0.214 259.815)', ...]

// With custom theme
tw::colors('@import "tailwindcss"; @theme { --color-brand: #3b82f6; }');
// [..., 'brand' => '#3b82f6']

// From compiler instance
$compiler = tw::compile();
$compiler->colors();
```

### `tw::breakpoints()`

[](#twbreakpoints)

Get all breakpoint values from the theme.

**Returns:** `array` - Map of breakpoint name to value

```
use TailwindPHP\tw;

tw::breakpoints();
// ['sm' => '40rem', 'md' => '48rem', 'lg' => '64rem', 'xl' => '80rem', '2xl' => '96rem']

// With custom theme
tw::breakpoints('@import "tailwindcss"; @theme { --breakpoint-xs: 20rem; }');
// ['xs' => '20rem', 'sm' => '40rem', ...]

// From compiler instance
$compiler = tw::compile();
$compiler->breakpoints();
```

### `tw::spacing()`

[](#twspacing)

Get custom spacing values from the theme.

**Returns:** `array` - Map of spacing name to value

```
use TailwindPHP\tw;

// Note: TailwindCSS 4 uses a single --spacing base value, not --spacing-* namespace
// This returns any custom --spacing-* values defined in the theme
tw::spacing('@import "tailwindcss"; @theme { --spacing-huge: 10rem; }');
// ['huge' => '10rem']

// From compiler instance
$compiler = tw::compile();
$compiler->spacing();
```

### Input Formats

[](#input-formats)

All static methods accept multiple input formats:

```
// Format 1: String only
tw::generate('');
tw::properties('p-4');

// Format 2: String + CSS string
tw::generate('', '@import "tailwindcss"; @theme { ... }');
tw::properties('bg-brand', '@import "tailwindcss"; @theme { --color-brand: #3b82f6; }');

// Format 3: Array with 'content' and optional 'css'
tw::generate(['content' => '', 'css' => '@import "tailwindcss";']);
tw::properties(['content' => 'p-4', 'css' => '@import "tailwindcss";']);
```

### TailwindCompiler Instance Methods

[](#tailwindcompiler-instance-methods)

When using `tw::compile()`, the returned compiler provides instance methods:

```
$compiler = tw::compile('@import "tailwindcss"; @theme { --color-brand: #3b82f6; }');

// Generate CSS
$css = $compiler->generate('');

// Extract candidates
$candidates = $compiler->extractCandidates('');

// Get properties
$compiler->properties('bg-brand');           // ['background-color' => 'var(--color-brand)']
$compiler->computedProperties('bg-brand');   // ['background-color' => '#3b82f6']

// Get single values
$compiler->value('bg-brand');           // 'var(--color-brand)'
$compiler->computedValue('bg-brand');   // '#3b82f6'

// Minify CSS
$minified = $compiler->minify($css);

// Get theme values
$compiler->colors();          // All color values
$compiler->breakpoints();     // All breakpoint values
$compiler->spacing();         // Custom spacing values

// Access internals (advanced)
$compiler->getTheme();        // Theme object with resolved values
$compiler->getDesignSystem(); // Design system with utilities, variants, etc.
$compiler->getCompiled();     // Raw compiled state array
```

---

Classname Utilities
-------------------

[](#classname-utilities)

TailwindPHP includes PHP ports of the popular Tailwind companion libraries. No additional packages required.

### `cn()`

[](#cn)

The recommended utility. Combines conditional class construction with intelligent conflict resolution.

```
use function TailwindPHP\cn;

// Basic usage - conflicts are resolved
cn('px-2 py-1', 'px-4');
// => 'py-1 px-4' (px-4 overrides px-2)

// Conditional classes
cn('btn', ['btn-primary' => true, 'btn-disabled' => false]);
// => 'btn btn-primary'

// React-style component
function Card(array $props = []): string {
    $class = cn(
        'rounded-lg border bg-card text-card-foreground shadow-sm',
        $props['class'] ?? null
    );
    return "" . ($props['children'] ?? '') . "";
}

Card(['class' => 'p-6', 'children' => 'Content']);
```

### `merge()`

[](#merge)

Merge Tailwind classes, resolving conflicts. Later classes override earlier ones.

```
use function TailwindPHP\merge;

merge('px-2 py-1 bg-red-500', 'px-4 bg-blue-500');
// => 'py-1 px-4 bg-blue-500'

merge('hover:bg-red-500', 'hover:bg-blue-500');
// => 'hover:bg-blue-500'
```

### `join()`

[](#join)

Join classes without conflict resolution. Use when you know there are no conflicts.

```
use function TailwindPHP\join;

join('foo', 'bar', null, 'baz');
// => 'foo bar baz'
```

---

Variants (CVA Port)
-------------------

[](#variants-cva-port)

PHP port of [CVA (Class Variance Authority)](https://github.com/joe-bell/cva) for creating component style variants.

### `variants()`

[](#variants)

Create component variants with declarative configuration.

```
use function TailwindPHP\variants;

// Define component styles
$button = variants([
    'base' => 'inline-flex items-center justify-center rounded-md font-medium',
    'variants' => [
        'variant' => [
            'default' => 'bg-primary text-white hover:bg-primary/90',
            'outline' => 'border border-input bg-background hover:bg-accent',
            'ghost' => 'hover:bg-accent hover:text-accent-foreground',
        ],
        'size' => [
            'default' => 'h-10 px-4 py-2',
            'sm' => 'h-9 px-3',
            'lg' => 'h-11 px-8',
        ],
    ],
    'defaultVariants' => [
        'variant' => 'default',
        'size' => 'default',
    ],
]);

// Usage (React-style single props object)
$button();                              // defaults applied
$button(['variant' => 'outline']);      // override variant
$button(['size' => 'sm', 'class' => 'mt-4']); // override + custom class

// Use in a component function with cn() for easy class extension
function Button(array $props = []): string {
    static $styles = null;
    $styles ??= variants([
        'base' => 'inline-flex items-center justify-center rounded-md font-medium',
        'variants' => [
            'variant' => [
                'default' => 'bg-primary text-white hover:bg-primary/90',
                'outline' => 'border border-input hover:bg-accent',
            ],
            'size' => [
                'default' => 'h-10 px-4 py-2',
                'sm' => 'h-9 px-3',
            ],
        ],
        'defaultVariants' => ['variant' => 'default', 'size' => 'default'],
    ]);

    // cn() merges variant output with custom classes, resolving conflicts
    $class = cn($styles($props), $props['class'] ?? null);
    $text = $props['children'] ?? 'Button';
    return "{$text}";
}

// Custom classes override variant defaults via cn()
Button(['variant' => 'outline', 'size' => 'sm', 'class' => 'mt-4 px-8']);
```

### `compose()`

[](#compose)

Merge multiple variant components into one.

```
use function TailwindPHP\variants;
use function TailwindPHP\compose;

$box = variants(['variants' => ['shadow' => ['sm' => 'shadow-sm', 'md' => 'shadow-md']]]);
$stack = variants(['variants' => ['gap' => ['1' => 'gap-1', '2' => 'gap-2']]]);
$card = compose($box, $stack);

$card(['shadow' => 'md', 'gap' => '2']); // => 'shadow-md gap-2'
```

---

Plugin System
-------------

[](#plugin-system)

TailwindPHP includes PHP ports of official TailwindCSS plugins. These are 1:1 ports following the same logic as the JavaScript originals.

### Built-in Plugins

[](#built-in-plugins)

PluginDescription`@tailwindcss/typography`Beautiful typographic defaults for HTML content`@tailwindcss/forms`Form element reset and styling utilities### Usage

[](#usage-1)

Use the `@plugin` directive in your CSS:

```
$css = tw::generate([
    'content' => 'HelloContent here',
    'css' => '
        @plugin "@tailwindcss/typography";
        @import "tailwindcss/utilities.css";
    '
]);
```

### Plugin Options

[](#plugin-options)

Pass options using CSS block syntax:

```
// Typography with custom class name
$css = '
    @plugin "@tailwindcss/typography" {
        className: "markdown";
    }
    @import "tailwindcss/utilities.css";
';

// Forms with class strategy (no base styles)
$css = '
    @plugin "@tailwindcss/forms" {
        strategy: "class";
    }
    @import "tailwindcss/utilities.css";
';
```

### Typography Plugin

[](#typography-plugin)

Generates the `.prose` class with beautiful typographic defaults:

```
// Basic usage
$css = tw::generate('...', '@plugin "@tailwindcss/typography"; @import "tailwindcss/utilities.css";');

// Available classes: prose, prose-sm, prose-lg, prose-xl, prose-2xl
// Modifiers: prose-invert (dark mode), prose-slate, prose-gray, etc.
```

### Forms Plugin

[](#forms-plugin)

Provides form element utilities:

```
// Class strategy - explicit form classes
$css = tw::generate(
    '...',
    '@plugin "@tailwindcss/forms" { strategy: "class"; } @import "tailwindcss/utilities.css";'
);

// Available classes: form-input, form-textarea, form-select, form-multiselect,
// form-checkbox, form-radio
```

### Creating Custom Plugins

[](#creating-custom-plugins)

You can create your own plugins by implementing the `PluginInterface`:

```
use TailwindPHP\Plugin\PluginInterface;
use TailwindPHP\Plugin\PluginAPI;

class MyCustomPlugin implements PluginInterface
{
    public function getName(): string
    {
        return 'my-custom-plugin';
    }

    public function __invoke(PluginAPI $api, array $options = []): void
    {
        // Add static utilities
        $api->addUtilities([
            '.btn' => [
                'padding' => '0.5rem 1rem',
                'border-radius' => '0.25rem',
                'font-weight' => '600',
            ],
            '.btn-primary' => [
                'background-color' => 'blue',
                'color' => 'white',
            ],
        ]);

        // Add functional utilities with values
        $api->matchUtilities(
            [
                'tab' => function ($value) {
                    return ['tab-size' => $value];
                },
            ],
            ['values' => ['1' => '1', '2' => '2', '4' => '4', '8' => '8']]
        );

        // Add component classes
        $api->addComponents([
            '.card' => [
                'background-color' => 'white',
                'border-radius' => '0.5rem',
                'padding' => '1rem',
                'box-shadow' => '0 1px 3px rgba(0,0,0,0.1)',
            ],
        ]);

        // Add custom variants
        $api->addVariant('hocus', '&:hover, &:focus');

        // Access theme values
        $primary = $api->theme('colors.blue.500', '#3b82f6');
    }

    public function getThemeExtensions(array $options = []): array
    {
        return []; // Return theme additions if needed
    }
}
```

Register and use your plugin:

```
use TailwindPHP\tw;
use function TailwindPHP\registerPlugin;

// Register the plugin
registerPlugin(new MyCustomPlugin());

// Use it in CSS
$css = tw::generate(
    '...',
    '@plugin "my-custom-plugin"; @import "tailwindcss/utilities.css";'
);
```

### Architecture

[](#architecture)

The plugin system follows the TailwindCSS plugin API pattern:

```
src/plugin.php                    # PluginInterface, PluginAPI, PluginManager
src/plugin/plugins/
├── typography-plugin.php         # @tailwindcss/typography port
└── forms-plugin.php              # @tailwindcss/forms port

```

**PluginAPI** provides the same methods as TailwindCSS:

- `addBase(array $css)` — Add base styles
- `addUtilities(array $utilities)` — Add static utilities
- `matchUtilities(array $utilities, array $options)` — Add functional utilities with values
- `addComponents(array $components)` — Add component classes
- `addVariant(string $name, string|array $variant)` — Add custom variants
- `matchVariant(string $name, callable $callback, array $options)` — Add functional variants
- `theme(string $path, mixed $default)` — Access theme values
- `config(string $path, mixed $default)` — Access config values

---

How It Works
------------

[](#how-it-works)

### Architecture

[](#architecture-1)

The codebase mirrors TailwindCSS's structure — same file names, same organization:

```
src/
├── _tailwindphp/                # PHP-specific helpers (NOT part of the TailwindCSS port)
│   ├── LightningCss.php         # CSS optimizations (lightningcss Rust library equivalent)
│   ├── CssMinifier.php          # CSS minification
│   └── lib/                     # Companion library ports
│       ├── clsx/                # clsx port (27 tests from reference)
│       ├── tailwind-merge/      # tailwind-merge port (52 tests from reference)
│       └── cva/                 # CVA port (50 tests from reference)
│
├── plugin/                      # Plugin system
│   └── plugins/                 # Built-in plugin implementations
│       ├── typography-plugin.php  # @tailwindcss/typography port
│       └── forms-plugin.php       # @tailwindcss/forms port
│
├── utilities/                   # Utility implementations (split from utilities.ts)
│   ├── accessibility.php        # sr-only, forced-colors
│   ├── backgrounds.php          # bg-*, gradient-*, from-*, via-*, to-*
│   ├── borders.php              # border-*, rounded-*, divide-*, outline-*
│   ├── effects.php              # shadow-*, opacity-*, mix-blend-*
│   ├── filters.php              # blur-*, brightness-*, contrast-*, etc.
│   ├── flexbox.php              # flex-*, grid-*, gap-*, justify-*, align-*
│   ├── interactivity.php        # cursor-*, scroll-*, touch-*, select-*
│   ├── layout.php               # display, position, z-*, overflow-*, etc.
│   ├── masks.php                # mask-linear-*, mask-radial-*, mask-conic-*, mask-x/y/t/r/b/l-*
│   ├── sizing.php               # w-*, h-*, min-*, max-*, size-*
│   ├── spacing.php              # m-*, p-*, space-*
│   ├── svg.php                  # fill-*, stroke-*
│   ├── tables.php               # border-collapse, table-layout
│   ├── transforms.php           # translate-*, rotate-*, scale-*, skew-*
│   ├── transitions.php          # transition-*, duration-*, ease-*, delay-*
│   └── typography.php           # font-*, text-*, leading-*, tracking-*, text-shadow-*
│
├── utils/                       # Helper functions (ported from utils/)
│
├── index.php                    # Main entry point, compile(), cn(), variants(), merge(), join()
├── ast.php                      # AST nodes and toCss()
├── candidate.php                # Candidate parsing (class name → parts)
├── compile.php                  # Candidate to CSS compilation
├── css-functions.php            # theme(), --theme(), --spacing(), --alpha()
├── css-parser.php               # CSS parsing
├── design-system.php            # Central registry for utilities/variants
├── plugin.php                   # Plugin system (PluginInterface, PluginAPI, PluginManager)
├── theme.php                    # Theme value resolution
├── utilities.php                # Utility registration and lookup
├── value-parser.php             # CSS value parsing
├── variants.php                 # Variant handling (hover, focus, responsive, etc.)
└── walk.php                     # AST traversal

```

**Note:** TailwindCSS's `utilities.ts` is 6,000+ lines. We split it into `src/utilities/` (one file per category) for maintainability.

### Port Deviation Markers

[](#port-deviation-markers)

All implementation files are documented with `@port-deviation` markers explaining where and why the PHP implementation differs from TypeScript:

MarkerMeaning`@port-deviation:none`Direct 1:1 port with no deviations`@port-deviation:async`PHP uses synchronous code (no async/await)`@port-deviation:storage`Different data structures (array vs Map/Set)`@port-deviation:types`PHPDoc instead of TypeScript types`@port-deviation:sourcemaps`Source map tracking omitted`@port-deviation:omitted`Entire module/feature not ported (outside scope)`@port-deviation:errors`Different error handling approach`@port-deviation:enum`PHP constants instead of TypeScript enums`@port-deviation:dispatch`Different function dispatch pattern`@port-deviation:structure`Different code organization`@port-deviation:helper`PHP-specific helper not in originalTesting
-------

[](#testing)

Tests ensure the PHP port stays in sync with TailwindCSS's TypeScript implementation. We use two approaches:

### Test Types

[](#test-types)

1. **Extraction-based tests** — Tests automatically extracted from TailwindCSS's `.test.ts` files using scripts in `test-coverage/`. These cover complex utilities, variants, and integration tests.
2. **Unit test ports** — Direct PHP ports of simpler TypeScript test files (AST, parsing, escaping, etc.). These live alongside their source files as `*.test.php`.

### Running Tests

[](#running-tests)

```
# Extract tests from TypeScript source
composer extract

# Run all tests
composer test

# Run specific test file
./vendor/bin/phpunit src/utilities.test.php

# Run tests matching a pattern
./vendor/bin/phpunit --filter="translate"

# Run library tests only
./vendor/bin/phpunit src/_tailwindphp/lib/
```

### How Extraction Works

[](#how-extraction-works)

1. **Extract** — Scripts in `test-coverage/` parse TailwindCSS's `.test.ts` files and extract test cases to JSON
2. **Run** — PHPUnit tests read extracted data and compare PHP output against expected CSS
3. **Verify** — Any mismatch means the PHP port has drifted from TailwindCSS behavior

### Test Coverage

[](#test-coverage)

CategoryTestsSource**Extraction-based**utilities.test.php547utilities.test.tsvariants.test.php139variants.test.tsindex.test.php78index.test.tscss\_functions.test.php60css-functions.test.tsui\_spec.test.php68ui.spec.ts**Unit test ports**css\_parser.test.php70css-parser.test.tscandidate.test.php66candidate.test.tsdecode\_arbitrary\_value.test.php60decode-arbitrary-value.test.tsast.test.php18ast.test.tsescape.test.php10escape.test.ts+ 12 more unit test files~180Various .test.ts files**Library tests**clsx.test.php27clsx/test/\*.jstailwind\_merge.test.php52tailwind-merge/tests/\*.tscva.test.php50cva/src/index.test.ts**API coverage tests**1,684Custom exhaustive tests**Plugin tests**25Plugin functionality### Requirements

[](#requirements)

- PHP 8.2+
- Composer

Development
-----------

[](#development)

See [CLAUDE.md](CLAUDE.md) for detailed development guide, project structure, and porting phases.

License
-------

[](#license)

MIT

Credits
-------

[](#credits)

This project ports:

- [TailwindCSS](https://tailwindcss.com) by Tailwind Labs
- [clsx](https://github.com/lukeed/clsx) by Luke Edwards
- [tailwind-merge](https://github.com/dcastil/tailwind-merge) by Dany Castillo
- [CVA](https://github.com/joe-bell/cva) by Joe Bell

###  Health Score

53

—

FairBetter than 96% of packages

Maintenance98

Actively maintained with recent releases

Popularity33

Limited adoption so far

Community14

Small or concentrated contributor base

Maturity55

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~14 days

Recently: every ~21 days

Total

13

Last Release

13d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/dc81a975082b6843421de211768cfb67d8237bed4c972c9a1eaad46aac14b372?d=identicon)[dnnsjsk](/maintainers/dnnsjsk)

---

Top Contributors

[![dnnsjsk](https://avatars.githubusercontent.com/u/73965001?v=4)](https://github.com/dnnsjsk "dnnsjsk (219 commits)")

---

Tags

phpcsstailwindtailwindcssutility-css

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StyleLaravel Pint

Type Coverage Yes

### Embed Badge

![Health badge](/badges/tailwindphp-tailwindphp/health.svg)

```
[![Health](https://phpackages.com/badges/tailwindphp-tailwindphp/health.svg)](https://phpackages.com/packages/tailwindphp-tailwindphp)
```

###  Alternatives

[yieldstudio/tailwind-merge-php

Merge Tailwind CSS classes without style conflicts

4974.6k1](/packages/yieldstudio-tailwind-merge-php)[gehrisandro/tailwind-merge-php

TailwindMerge for PHP merges multiple Tailwind CSS classes by automatically resolving conflicts between them

1391.7M12](/packages/gehrisandro-tailwind-merge-php)[awssat/tailwindo

Convert Bootstrap CSS to Tailwind CSS

1.1k20.4k1](/packages/awssat-tailwindo)[arnolem/tailwindphp

TailwindPHP - use Tailwind CSS in your PHP projects (without npm)

1316.8k](/packages/arnolem-tailwindphp)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
