tw-mrg Svelte Themes

Tw Mrg

Smart Tailwind CSS v4 class merger with automatic conflict resolution. Features twStates() for CVA-like variants, twPrefix() for bulk modifier application, and runtime CSS injection using Tailwind's design system. Includes LRU caching, O(n) performance, full TypeScript support. Works with React, Vue, Svelte, or vanilla JS.


tw-mrg

tw-mrg

A utility library for intelligently merging Tailwind CSS v4 class names in JavaScript and TypeScript applications. When you need to conditionally combine Tailwind classes or allow component consumers to override default styles, tw-mrg ensures that conflicting classes are resolved correctly by keeping only the most relevant styles.

This package is based on tailwind-merge and is designed to complement the official Tailwind CSS framework by solving the class conflict problem that arises in component-based architectures.

import { tw } from "tw-mrg";

// Later classes override earlier conflicting classes
tw("p-4", "p-8"); // → 'p-8'

// Non-conflicting classes are preserved together
tw("p-4", "mt-2"); // → 'p-4 mt-2'

Acknowledgments

This project builds on the excellent work done by Dany Castillo on tailwind-merge, adapting and extending the concepts for Tailwind CSS v4 with additional features like runtime CSS injection and an integrated variant system.

Why You Need This

When building reusable components with Tailwind CSS, you often encounter a frustrating limitation: CSS class order in HTML has no effect on which styles are applied. The styles are determined solely by the order in which they appear in the generated stylesheet.

Consider this common scenario where you want to create a reusable button component that accepts custom class overrides:

function Button({ className, children }) {
    return (
        <button className={`px-4 py-2 bg-blue-500 ${className}`}>
            {children}
        </button>
    );
}

// Attempting to override the padding
<Button className="px-8">Click me</Button>;
// Result: "px-4 py-2 bg-blue-500 px-8"
// Problem: Both px-4 and px-8 exist in the class string,
// but which one wins depends on stylesheet order, not HTML order

This unpredictable behavior makes it difficult to build component libraries where consumers can reliably override styles. The tw-mrg library solves this problem by intelligently analyzing class names and removing conflicting classes, always keeping the ones that appear later in the arguments.

Installation

Install tw-mrg using your preferred package manager:

npm add tw-mrg
pnpm add tw-mrg
yarn add tw-mrg
bun add tw-mrg

Requirements: Node.js 18 or higher, and Tailwind CSS v4.0.0 or higher as a peer dependency.

Quick Start

Import the tw function and use it to merge your Tailwind classes:

import { tw } from "tw-mrg";

// Basic conflict resolution: the last conflicting class wins
tw("p-4", "p-8"); // → 'p-8'
tw("text-red-500", "text-blue-500"); // → 'text-blue-500'
tw("inline", "block", "flex"); // → 'flex'

// Refinements are intelligently preserved when they don't truly conflict
tw("p-4", "pt-2"); // → 'p-4 pt-2' (pt-2 refines the top padding)
tw("mx-auto", "ml-4"); // → 'mx-auto ml-4' (ml-4 refines the left margin)

// Modifiers create separate conflict contexts
tw("hover:bg-blue-500", "hover:bg-red-500"); // → 'hover:bg-red-500'
tw("md:p-4", "lg:p-8"); // → 'md:p-4 lg:p-8' (different breakpoints)
tw("p-4", "hover:p-8"); // → 'p-4 hover:p-8' (different states)

// Supports conditional classes similar to clsx/classnames
tw("base-class", isActive && "active-class", { disabled: isDisabled });

// Works with arrays for organizing complex class lists
tw(["p-4", "text-lg"], "bg-white", ["border", "rounded"]);

Component Variant System

The twStates function provides a powerful way to define component variants, similar to CVA (Class Variance Authority). This makes it easy to create consistent, reusable components with predefined style variations:

import { twStates } from "tw-mrg";

const button = twStates({
    // Base classes applied to all variants
    base: "px-4 py-2 rounded font-medium transition-colors focus-visible:outline-none",

    // Define variant axes with their possible values
    variants: {
        variant: {
            primary: "bg-blue-500 text-white hover:bg-blue-600",
            secondary: "bg-gray-200 text-gray-800 hover:bg-gray-300",
            ghost: "bg-transparent hover:bg-gray-100",
        },
        size: {
            sm: "text-sm px-2 py-1",
            md: "text-base px-4 py-2",
            lg: "text-lg px-6 py-3",
        },
    },

    // Optional: specify which variants to use by default
    defaultVariants: {
        variant: "primary",
        size: "md",
    },
});

// Usage in components
button(); // Uses default variants
button({ variant: "secondary" }); // Override specific variant
button({ size: "lg", className: "mt-4" }); // Additional classes are merged

Core API Functions

Function Description
tw() The primary function for merging classes with intelligent conflict resolution. Accepts strings, arrays, objects, and conditional expressions.
twJoin() A faster alternative that joins classes without conflict resolution. Use when you control all classes and know there are no conflicts.
twStates() Creates a variant function for component styling with predefined style variations and compound variants support.
twDebug() Returns detailed information about how classes were resolved, useful for understanding and debugging unexpected results.
twPrefix() Adds modifier prefixes to all classes in a string, useful for programmatically applying responsive or state modifiers.
createTw() Factory function for creating customized tw instances with custom prefixes, cache sizes, or extended class groups.

Key Features and Capabilities

  • Optimized O(n) Performance: The conflict resolution algorithm processes each class exactly once using a reverse iteration strategy, ensuring consistent performance regardless of input complexity.

  • Trie-Based Class Classification: Class group lookups use an efficient prefix trie data structure, providing O(k) lookup time where k is the length of the class name, rather than iterating through all possible patterns.

  • LRU Caching for Repeated Calls: Results are cached using a Least Recently Used (LRU) cache with a configurable size (default: 500 entries), making repeated calls with the same inputs instant.

  • Runtime CSS Injection: For dynamic or arbitrary classes that aren't in your built CSS, tw-mrg can generate and inject the necessary styles at runtime using Tailwind's design system.

  • Specificity-Aware Merging: The library understands Tailwind's class hierarchy. For example, p-4 (all sides) and pt-2 (top only) can coexist because pt-2 has higher specificity for the top padding.

  • Complete Modifier Support: Full support for responsive modifiers (sm:, md:, lg:), state modifiers (hover:, focus:, active:), and arbitrary variants ([&:nth-child(2)]:).

  • Tree-Shakeable Configurations: Choose between the full configuration (7KB gzipped) covering all Tailwind utilities, or the minimal configuration (1.5KB gzipped) covering only the most commonly used utilities.

  • Full TypeScript Support: Complete type definitions with inferred types for variant configurations, providing excellent IDE autocomplete and compile-time error checking.

Documentation

The following documentation guides cover all aspects of using tw-mrg effectively in your projects:

  • Getting Started — Complete installation instructions, input format details, and introductory examples to help you start using tw-mrg in your project.
  • Core Concepts — Deep dive into how the conflict resolution algorithm works, including class groups, specificity hierarchies, and the data flow through the system.
  • Variants — Comprehensive guide to the twStates variant system, including compound variants, boolean variants, and React component integration patterns.
  • CSS Injection — How to use runtime CSS generation for dynamic classes, including initialization, validation, and practical React hook patterns.
  • Customization — Configuration options for custom Tailwind setups, including prefixes, extending class groups, and creating custom tw instances.
  • Utilities — Reference for helper functions like parsing utilities, cache management, and configuration access.
  • API Reference — Complete API documentation with all function signatures, types, and configuration options.
  • Patterns — Common recipes and best practices for component libraries, slot patterns, and integration strategies.
  • Edge Cases — Handling of edge cases, limitations, and workarounds for complex scenarios.

Development

For contributors and developers who want to build or modify tw-mrg locally:

# Install dependencies
pnpm install

# Build the library for production
pnpm build

# Run in development mode with file watching
pnpm dev

# Run type checking to verify TypeScript types
pnpm typecheck

# Run the test suite
pnpm test

License

MIT

Top categories

Loading Svelte Themes