gehrisandro/tailwind-merge-php
TailwindMerge for PHP merges multiple Tailwind CSS classes and resolves conflicts automatically, keeping only the class defined later. A PHP port of tailwind-merge supporting Tailwind v3.0 through v3.4, requiring PHP 8.1+, with caching and configurable options.
px-6 being overridden by a passed-in pl-4) is a small, boring, high-frequency problem. Porting tailwind-merge yourself is a multi-week correctness rabbit hole involving arbitrary values, variants stacking, the !important modifier, and breakpoint ordering. This package converts that into a one-line Composer dependency, so the decision becomes "do we staff a utility library?" — and the answer is almost certainly no.!important hacks or class prop collision bugs. That is a roadmap-level decision about developer ergonomics for your design system, not just an implementation detail, and it directly reduces the ticket volume of "my style override didn't apply."prefix, custom classGroups), this package is the mechanism that makes per-tenant or per-brand Tailwind prefixes viable in a multi-tenant product. If multi-brand is on the roadmap, this is a cheap enabler; if it isn't, that capability is not worth paying the config-sync tax for.tailwind-merge cannot help you. This package is what unlocks consistent styling for those surfaces, which matters if email/PDF output is a customer-visible product surface.Consider it when all of the following hold:
tailwind-merge has a v4 story this port can follow).tailwind-merge is simply not available.tailwind.config.js is mostly default. The more custom class groups, renamed scales, plugin utilities, or prefixes you have, the more PHP-side config you must hand-maintain in parallel.tailwind-merge-laravel wrapper for Laravel projects rather than hand-wiring the core package.Look elsewhere (or build/wait) when:
tailwind-merge.!important because the component contract is unclear, a merger is a painkiller, not the fix.To executives (30 seconds): Our PHP-rendered UI — components, emails, PDFs — has a recurring class-collision problem that creates visual bugs and support tickets and that engineers keep half-solving by hand. This is a small, MIT-licensed, single-purpose utility that solves it definitively, with no infrastructure, no hosting, and no vendor contract. Cost is one Composer line; the main caveat is that it only covers Tailwind v3, so we should confirm our styling upgrade timeline before committing.
To engineering leadership (2 minutes): It is a faithful PHP port of the widely-used JS tailwind-merge, framework-agnostic, stateless, PHP 8.1+, with an optional PSR-16 cache and a fluent config factory. Integration is a single merge() call behind a thin internal ClassMerger interface so we are not spread across the codebase if we swap it out. Real risks are narrow but real: (1) it is pinned to Tailwind v3.0–v3.4, (2) our custom Tailwind config must be mirrored in PHP, creating config drift, and (3) it is a single-maintainer project with 140 stars — budget for a possible fork. Mitigations: wrap it, add a fixture test suite of our own real class strings targeting arbitrary values/variants (where upstream bugs have historically landed), and gate adoption on the Tailwind v4 question.
To design-system / frontend stakeholders: This lets components accept overrides reliably, which means fewer !important escalations and a clearer contract for how consumers style our components. It does not change how anyone writes Tailwind — it just makes the last class win, deterministically.
The decision we are asking for: Approve a time-boxed spike (one engineer, ~1 week) that answers three questions — Tailwind v4 timeline, how much of our config is non-default, and whether the wrapper's release cadence tracks the core — before we commit to adoption.
How can I help you explore Laravel packages today?