A high-performance .NET library for merging Tailwind CSS class names with full conflict resolution, deduplication, and support for all major Tailwind v4 utilities, responsive breakpoints, and modifiers.
$ dotnet add package TwMerge![]()
A high-performance .NET library for merging Tailwind CSS class names with full conflict resolution, deduplication, and support for all major Tailwind v4 utilities, responsive breakpoints, and modifiers.
w-[32px])dotnet add package TwMerge
using TailwindMerge;
// Create instance with default config
var twMerge = new TwMerge();
// merged == "w-4 hover:w-4 text-blue-500"
var merged = twMerge.Merge("w-3", "w-4", "hover:w-3", "hover:w-4", "text-red-500", "text-blue-500");
The main entry point for merging Tailwind CSS class names, resolving conflicts and removing duplicates.
Configures class groups, conflict rules, theme, and other options. Use TwConfig.Default() for standard Tailwind v4 support, or customize as needed.
Each property in TwConfig serves a specific purpose in controlling how Tailwind classes are merged and resolved:
Type: int (default: 500)
Purpose: Controls the size of the LRU cache for memoizing merge results.
var config = new TwConfig().CacheSize(1000); // Increase cache for better performanceWhen to customize:
Type: string (default: ":")
Purpose: Defines the character(s) used to separate modifiers from base classes.
var config = new TwConfig().Separator("__"); // Custom separator
// Now supports: "hover__bg-blue-500" instead of "hover:bg-blue-500"When to customize:
Type: string (default: "")
Purpose: Adds a prefix to all Tailwind class names for namespacing.
var config = new TwConfig().Prefix("tw-");
// Supports: "tw-bg-blue-500", "tw-hover:bg-red-500"When to customize:
prefix config optionType: Dictionary<string, object>
Purpose: Defines theme values that can be referenced by class groups (colors, spacing, sizes, etc.).
var customTheme = new Dictionary<string, object>
{
["colors"] = new List<object> { /* custom color definitions */ },
["spacing"] = new List<object> { /* custom spacing values */ }
};
var config = new TwConfig().Theme(customTheme);When to customize:
Type: Dictionary<string, List<object>>
Purpose: Defines all available Tailwind class groups and their valid class patterns.
var customClassGroups = new Dictionary<string, List<object>>
{
["custom-size"] = new List<object>
{
new Dictionary<string, List<object>>
{
["size"] = new List<object> { "tiny", "huge", "massive" }
}
}
};
var config = new TwConfig().ClassGroups(customClassGroups, extend: true);When to customize:
Type: Dictionary<string, List<string>>
Purpose: Defines which class groups conflict with each other (e.g., p-4 conflicts with px-2).
var customConflicts = new Dictionary<string, List<string>>
{
["custom-margin"] = new List<string> { "margin", "margin-x", "margin-y" },
["custom-layout"] = new List<string> { "display", "position" }
};
var config = new TwConfig().ConflictingClassGroups(customConflicts, extend: true);When to customize:
Type: Dictionary<string, List<string>>
Purpose: Defines additional conflicts that occur when classes have postfix modifiers (e.g., text-lg/tight conflicts with leading-*).
var modifierConflicts = new Dictionary<string, List<string>>
{
["font-size"] = new List<string> { "leading", "line-height" },
["custom-text"] = new List<string> { "tracking", "letter-spacing" }
};
var config = new TwConfig().ConflictingClassGroupModifiers(modifierConflicts);When to customize:
Type: List<string>
Purpose: Specifies modifiers where order matters for CSS specificity (e.g., before:, after:, first-letter:).
var orderSensitive = new List<string>
{
"before", "after", "first-letter", "first-line",
"custom-pseudo", "custom-element"
};
var config = new TwConfig().OrderSensitiveModifiers(orderSensitive);When to customize:
// For a company design system with custom tokens
var designSystemConfig = new TwConfig()
.Prefix("ds-")
.Theme(new Dictionary<string, object>
{
["colors"] = new List<object>
{
"brand-primary", "brand-secondary", "accent-blue", "accent-green"
},
["spacing"] = new List<object>
{
"micro", "tiny", "small", "medium", "large", "xlarge", "huge"
}
})
.ClassGroups(new Dictionary<string, List<object>>
{
["brand-colors"] = new List<object>
{
new Dictionary<string, List<object>>
{
["bg"] = new List<object> { "brand-primary", "brand-secondary" },
["text"] = new List<object> { "brand-primary", "brand-secondary" }
}
}
}, extend: true)
.ConflictingClassGroups(new Dictionary<string, List<string>>
{
["brand-colors"] = new List<string> { "bg-color", "text-color" }
}, extend: true);
var dstwMerge = new TwMerge(designSystemConfig);
var result = dstwMerge.Merge("ds-bg-brand-primary", "ds-bg-accent-blue");
// Result: "ds-bg-accent-blue" (brand colors conflict with regular colors)// Supporting Tailwind plugins like @tailwindcss/typography
var typographyConfig = new TwConfig()
.ClassGroups(new Dictionary<string, List<object>>
{
["prose"] = new List<object>
{
"prose",
new Dictionary<string, List<object>>
{
["prose"] = new List<object> { "sm", "base", "lg", "xl", "2xl" }
}
},
["prose-colors"] = new List<object>
{
new Dictionary<string, List<object>>
{
["prose"] = new List<object>
{
"gray", "red", "yellow", "green", "blue", "indigo", "purple", "pink"
}
}
}
}, extend: true)
.ConflictingClassGroups(new Dictionary<string, List<string>>
{
["prose"] = new List<string> { "prose-colors" }
}, extend: true);
var proseTwMerge = new TwMerge(typographyConfig);
var result = proseTwMerge.Merge("prose", "prose-lg", "prose-gray", "prose-blue");
// Result: "prose-lg prose-blue"// For React/Blazor component libraries
var componentConfig = new TwConfig()
.Separator("__") // Avoid conflicts with CSS-in-JS
.CacheSize(2000) // Higher cache for component reuse
.ConflictingClassGroupModifiers(new Dictionary<string, List<string>>
{
["component-size"] = new List<string> { "padding", "margin", "gap" }
})
.OrderSensitiveModifiers(new List<string>
{
"before", "after", "hover", "focus", "active", "group-hover"
});
var componentTwMerge = new TwMerge(componentConfig);// For high-frequency merging scenarios
var performanceConfig = new TwConfig()
.CacheSize(5000) // Large cache
.Theme(minimalTheme) // Reduced theme for faster lookups
.ClassGroups(essentialClassGroups); // Only required class groups
var fastTwMerge = new TwMerge(performanceConfig);Contributions are welcome! Please feel free to submit a Pull Request.
This project is a C# adaptation of tailwind-merge originally developed by dcastil.
This project is licensed under the MIT License.