tailwind-merge

Merge Tailwind CSS classes without style conflicts

Library
npm
v3.7.0
5,692 stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum. How we score it →
86 /100 Excellent
Development Activity 92
Maintenance 100
Community 56
Maturity 56
Momentum 40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation. How we score it →
90 /100 Excellent
Architecture 90
Code Quality 92
Innovation 90
Learning Curve 88

tailwind-merge is a TypeScript utility that merges strings of Tailwind CSS classes and resolves conflicts between them, so that when two classes target the same styling concern the last one specified wins instead of both being applied and silently fighting in the CSS cascade.

It ships with zero runtime dependencies, understands the full default Tailwind config out of the box, and can be extended to understand custom themes, plugins, and class groups via extendTailwindMerge and mergeConfigs.

What You Get

  • A single twMerge() function that merges any number of class strings/arrays and strips out conflicting Tailwind utilities.
  • A twJoin() helper for conditionally joining class names (a typed subset of clsx) when conflict resolution isn’t needed.
  • extendTailwindMerge, createTailwindMerge, and mergeConfigs for teaching the merge logic about a customized Tailwind theme or plugin classes.
  • Full TypeScript types for every export, plus a legacy ./es5 bundle for older browser targets.

Common Use Cases

  • Accepting an overridable className prop in a reusable component.
  • Merging variant classes generated by cva or tailwind-variants in a design system.
  • Resolving conditionally-applied Tailwind classes in state-driven UI.
  • Supporting a customized Tailwind theme with non-default spacing/color scales.

Under The Hood

Architecture — twMerge (src/lib/tw-merge.ts) is createTailwindMerge(getDefaultConfig): a factory in src/lib/create-tailwind-merge.ts that lazily builds its config and an LRU cache (src/lib/lru-cache.ts) on first call, then swaps its internal functionToCall reference to a fast cached path for every call after — avoiding config-parsing cost when twMerge is never invoked. The actual merge happens in mergeClassList (src/lib/merge-classlist.ts): the input is first joined by twJoin (a typed clsx subset, src/lib/tw-join.ts), then class names are walked right-to-left, each parsed by parseClassName (src/lib/parse-class-name.ts) into modifiers, base class, important-flag, and postfix-modifier position while tracking bracket/paren depth for arbitrary values like bg-[#B91C1C]. Each class resolves to a classGroupId via config-utils’ class-group matching (built from src/lib/default-config.ts and src/lib/validators.ts); a class is dropped if a later class already claimed the same modifier+classGroupId conflict key, with getConflictingClassGroupIds expanding transitive conflicts (e.g. px conflicts with pl and pr).

Tech Stack — Pure TypeScript with zero runtime dependencies ("dependencies": {} in package.json); built with Rollup (scripts/rollup.config.mjs) into separate ESM/CJS/ES5 bundles exposed via package.json’s exports map (. vs ./es5); tested with Vitest 4 plus @vitest/coverage-v8 for coverage and @codspeed/vitest-plugin for benchmark-regression tracking; linted with ESLint 9’s flat config and typescript-eslint; managed as a pnpm 11 workspace (pnpm-workspace.yaml) requiring Node >=22 via devEngines.runtime.

Code Quality — 36 test files under tests/ cover arbitrary values/properties/variants, class-group conflicts, the important modifier, negative values, lazy initialization, and even a docs-examples.test.ts that runs the README’s own code samples to keep documentation honest. A dedicated typescript-compat devDependency pins an older TypeScript version to verify the shipped .d.ts declarations stay compatible. Source modules are small and single-purpose (parse-class-name.ts, merge-classlist.ts, lru-cache.ts, sort-modifiers.ts are each well under 150 lines) with inline comments justifying non-obvious performance choices, such as the “Fast path: skip sorting for empty or single modifier” branch in merge-classlist.ts.

API Design — The zero-config twMerge default covers the common case with no setup (twMerge('a', 'b')), while power users extend behavior via extendTailwindMerge, createTailwindMerge, and mergeConfigs without forking internals, and fromTheme lets custom class groups key off the consumer’s own Tailwind theme. Bundle size is treated as a first-class concern (a Bundlephobia badge in the README, a dedicated ./es5 export for legacy targets), and documentation is split into task-oriented pages (what-is-it-for, when-and-how-to-use-it, configuration, recipes, api-reference, writing-plugins) rather than one long README.

Used by 219 apps in this directory

TypeScript
94%
MIT

paperclip

AI Agents · Automation

90,417

The open-source control plane that turns a pile of AI agents into an actual company — with org charts, budgets, heartbeats, and governance.

View details
86
Repo Health
78
Technical
71
Dependency
Built with
TypeScript 94%
Updated 1 weeks ago
TypeScript
99%
Other

Papermark

Digital Signiture · File Storage

9,218

Open-source DocSend alternative with page-by-page analytics, secure data rooms, and custom domains for document sharing.

View details
82
Repo Health
63
Technical
67
Dependency
Built with
TypeScript 99%
Updated 1 months ago
TypeScript
93%
AGPL 3.0

Papra

Bookmarks Archiving

5,519

Self-hosted document archiving with email ingestion, OCR full-text search, and pluggable storage — store once, find anything.

View details
86
Repo Health
82
Technical
69
Dependency
Built with
TypeScript 93%
Updated 1 weeks ago
TypeScript
96%
MIT

Payload CMS

Blogging · CMS · Developer Tools

44,995

The open-source, Next.js-native headless CMS that lives inside your /app folder and gives you a full TypeScript backend instantly.

View details
91
Repo Health
88
Technical
65
Dependency
Built with
TypeScript 96%
Updated 1 weeks ago
TypeScript
96%
Apache 2.0

Pezzo

AI Development · Monitoring

3,275

Open-source LLMOps platform for prompt management, AI observability, intelligent caching, and real-time cost tracking across LLM providers.

View details
61
Repo Health
75
Technical
66
Dependency
Built with
TypeScript 96%
Updated 1 months ago
TypeScript
69%
AGPL 3.0

Plane

Collaboration · Productivity · Project Management

59,964

Open-source project management platform to replace Jira, Linear, and ClickUp — with built-in cycles, real-time collaborative docs, and full self-hosting.

View details
90
Repo Health
82
Technical
77
Dependency
Built with
TypeScript 69%
Python 27%
Updated 1 weeks ago
Python
65%
Apache 2.0

Polar

Developer Tools · Ecommerce · Invoicing Finance

10,293

Open source payments infrastructure that turns software into a business — subscriptions, usage-based billing, digital products, and merchant-of-record compliance in one platform.

View details
90
Repo Health
82
Technical
66
Dependency
Built with
Python 65%
TypeScript 28%
Updated 1 weeks ago
Python
55%
Other

PostHog

Ab Testing Experimentation · Analytics · Developer Tools

39,975

The all-in-one open source product platform combining analytics, session replay, feature flags, error tracking, AI observability, and a built-in data warehouse in a single self-hostable stack.

View details
92
Repo Health
80
Technical
65
Dependency
Built with
Python 55%
TypeScript 36%
Updated 1 weeks ago
TypeScript
97%
MIT

Promptfoo

AI Development

25,506

An open-source CLI and library for evaluating and red-teaming LLM applications — replace trial-and-error prompt engineering with systematic evals, vulnerability scanning, and CI/CD integration.

View details
90
Repo Health
73
Technical
68
Dependency
Built with
TypeScript 97%
Updated 1 weeks ago

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers