or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

configuration.mdcore-functions.mdindex.mdvalidation.md

index.mddocs/

0

# tailwind-merge

1

2

tailwind-merge is a utility function to efficiently merge Tailwind CSS classes in JavaScript without style conflicts. It provides intelligent conflict resolution that understands Tailwind's class precedence rules, allowing developers to programmatically combine CSS classes while ensuring the final result maintains proper styling without conflicting declarations.

3

4

## Package Information

5

6

- **Package Name**: tailwind-merge

7

- **Package Type**: npm

8

- **Language**: TypeScript

9

- **Installation**: `npm install tailwind-merge`

10

11

## Core Imports

12

13

```typescript

14

import { twMerge, twJoin, createTailwindMerge, extendTailwindMerge, getDefaultConfig, mergeConfigs, fromTheme } from "tailwind-merge";

15

```

16

17

For CommonJS:

18

19

```javascript

20

const { twMerge, twJoin, createTailwindMerge, extendTailwindMerge, getDefaultConfig, mergeConfigs, fromTheme } = require("tailwind-merge");

21

```

22

23

## Basic Usage

24

25

```typescript

26

import { twMerge } from "tailwind-merge";

27

28

// Basic merging with conflict resolution

29

const result = twMerge('px-2 py-1 bg-red hover:bg-dark-red', 'p-3 bg-[#B91C1C]');

30

// → 'hover:bg-dark-red p-3 bg-[#B91C1C]'

31

32

// Handle conditional classes

33

const buttonClasses = twMerge(

34

'px-4 py-2 rounded-md font-medium',

35

isLoading && 'opacity-50 cursor-not-allowed',

36

variant === 'primary' && 'bg-blue-500 text-white',

37

variant === 'secondary' && 'bg-gray-200 text-gray-900',

38

size === 'sm' && 'px-2 py-1 text-sm',

39

size === 'lg' && 'px-6 py-3 text-lg'

40

);

41

```

42

43

## Architecture

44

45

tailwind-merge is built around several key components:

46

47

- **Core Merger**: `twMerge` function that handles conflict resolution using the default Tailwind configuration

48

- **Class Joiner**: `twJoin` function for conditional class joining without conflict resolution

49

- **Configuration System**: Extensible configuration allowing customization of class groups and conflict rules

50

- **Factory Functions**: `createTailwindMerge` and `extendTailwindMerge` for creating custom merge instances

51

- **Validation System**: Comprehensive validators for different types of Tailwind class values

52

- **Performance Optimization**: LRU caching and efficient parsing for high-frequency usage

53

54

## Capabilities

55

56

### Core Merging Functions

57

58

Primary functions for merging and joining Tailwind CSS classes with conflict resolution and conditional handling.

59

60

```typescript { .api }

61

function twMerge(...classLists: ClassNameValue[]): string;

62

function twJoin(...classLists: ClassNameValue[]): string;

63

64

type ClassNameValue = ClassNameArray | string | null | undefined | 0 | 0n | false;

65

type ClassNameArray = ClassNameValue[];

66

```

67

68

[Core Functions](./core-functions.md)

69

70

### Configuration and Customization

71

72

Advanced configuration system for extending or customizing tailwind-merge behavior with custom class groups, theme scales, and conflict resolution rules.

73

74

```typescript { .api }

75

function extendTailwindMerge<

76

AdditionalClassGroupIds extends string = never,

77

AdditionalThemeGroupIds extends string = never,

78

>(

79

configExtension: ConfigExtension<

80

DefaultClassGroupIds | AdditionalClassGroupIds,

81

DefaultThemeGroupIds | AdditionalThemeGroupIds

82

>,

83

...createConfig: CreateConfigSubsequent[]

84

): TailwindMerge;

85

86

function createTailwindMerge(

87

createConfigFirst: () => AnyConfig,

88

...createConfigRest: CreateConfigSubsequent[]

89

): TailwindMerge;

90

91

function getDefaultConfig(): Config<DefaultClassGroupIds, DefaultThemeGroupIds>;

92

```

93

94

[Configuration](./configuration.md)

95

96

### Validation System

97

98

Comprehensive validation functions for different types of Tailwind class values, used in custom configurations and class group definitions.

99

100

```typescript { .api }

101

interface Validators {

102

isLength(value: string): boolean;

103

isArbitraryLength(value: string): boolean;

104

isNumber(value: string): boolean;

105

isInteger(value: string): boolean;

106

isPercent(value: string): boolean;

107

isArbitraryValue(value: string): boolean;

108

isTshirtSize(value: string): boolean;

109

isArbitrarySize(value: string): boolean;

110

isArbitraryPosition(value: string): boolean;

111

isArbitraryImage(value: string): boolean;

112

isArbitraryNumber(value: string): boolean;

113

isArbitraryShadow(value: string): boolean;

114

isAny(): boolean;

115

}

116

```

117

118

[Validation System](./validation.md)

119

120

## Types

121

122

```typescript { .api }

123

interface Config<ClassGroupIds extends string, ThemeGroupIds extends string>

124

extends ConfigStaticPart, ConfigGroupsPart<ClassGroupIds, ThemeGroupIds> {}

125

126

interface ConfigExtension<ClassGroupIds extends string, ThemeGroupIds extends string>

127

extends Partial<ConfigStaticPart> {

128

override?: PartialPartial<ConfigGroupsPart<ClassGroupIds, ThemeGroupIds>>;

129

extend?: PartialPartial<ConfigGroupsPart<ClassGroupIds, ThemeGroupIds>>;

130

}

131

132

type ClassValidator = (classPart: string) => boolean;

133

134

type DefaultClassGroupIds = 'accent' | 'align-content' | 'align-items' | 'align-self' | 'animate' | 'appearance' | 'aspect' | 'auto-cols' | 'auto-rows' | 'backdrop-blur' | 'backdrop-brightness' | 'backdrop-contrast' | 'backdrop-filter' | 'backdrop-grayscale' | 'backdrop-hue-rotate' | 'backdrop-invert' | 'backdrop-opacity' | 'backdrop-saturate' | 'backdrop-sepia' | 'basis' | 'bg-attachment' | 'bg-blend' | 'bg-clip' | 'bg-color' | 'bg-image' | 'bg-opacity' | 'bg-origin' | 'bg-position' | 'bg-repeat' | 'bg-size' | 'blur' | 'border-collapse' | 'border-color-b' | 'border-color-e' | 'border-color-l' | 'border-color-r' | 'border-color-s' | 'border-color-t' | 'border-color-x' | 'border-color-y' | 'border-color' | 'border-opacity' | 'border-spacing-x' | 'border-spacing-y' | 'border-spacing' | 'border-style' | 'border-w-b' | 'border-w-e' | 'border-w-l' | 'border-w-r' | 'border-w-s' | 'border-w-t' | 'border-w-x' | 'border-w-y' | 'border-w' | 'bottom' | 'box-decoration' | 'box' | 'break-after' | 'break-before' | 'break-inside' | 'break' | 'brightness' | 'caption' | 'caret-color' | 'clear' | 'col-end' | 'col-start-end' | 'col-start' | 'columns' | 'container' | 'content' | 'contrast' | 'cursor' | 'delay' | 'display' | 'divide-color' | 'divide-opacity' | 'divide-style' | 'divide-x-reverse' | 'divide-x' | 'divide-y-reverse' | 'divide-y' | 'drop-shadow' | 'duration' | 'ease' | 'end' | 'fill' | 'filter' | 'flex-direction' | 'flex-wrap' | 'flex' | 'float' | 'font-family' | 'font-size' | 'font-smoothing' | 'font-style' | 'font-weight' | 'forced-color-adjust' | 'fvn-figure' | 'fvn-fraction' | 'fvn-normal' | 'fvn-ordinal' | 'fvn-slashed-zero' | 'fvn-spacing' | 'gap-x' | 'gap-y' | 'gap' | 'gradient-from-pos' | 'gradient-from' | 'gradient-to-pos' | 'gradient-to' | 'gradient-via-pos' | 'gradient-via' | 'grayscale' | 'grid-cols' | 'grid-flow' | 'grid-rows' | 'grow' | 'h' | 'hue-rotate' | 'hyphens' | 'indent' | 'inset-x' | 'inset-y' | 'inset' | 'invert' | 'isolation' | 'justify-content' | 'justify-items' | 'justify-self' | 'leading' | 'left' | 'line-clamp' | 'list-image' | 'list-style-position' | 'list-style-type' | 'm' | 'max-h' | 'max-w' | 'mb' | 'me' | 'min-h' | 'min-w' | 'mix-blend' | 'ml' | 'mr' | 'ms' | 'mt' | 'mx' | 'my' | 'object-fit' | 'object-position' | 'opacity' | 'order' | 'outline-color' | 'outline-offset' | 'outline-style' | 'outline-w' | 'overflow-x' | 'overflow-y' | 'overflow' | 'overscroll-x' | 'overscroll-y' | 'overscroll' | 'p' | 'pb' | 'pe' | 'pl' | 'place-content' | 'place-items' | 'place-self' | 'placeholder-color' | 'placeholder-opacity' | 'pointer-events' | 'position' | 'pr' | 'ps' | 'pt' | 'px' | 'py' | 'resize' | 'right' | 'ring-color' | 'ring-offset-color' | 'ring-offset-w' | 'ring-opacity' | 'ring-w-inset' | 'ring-w' | 'rotate' | 'rounded-b' | 'rounded-bl' | 'rounded-br' | 'rounded-e' | 'rounded-ee' | 'rounded-es' | 'rounded-l' | 'rounded-r' | 'rounded-s' | 'rounded-se' | 'rounded-ss' | 'rounded-t' | 'rounded-tl' | 'rounded-tr' | 'rounded' | 'row-end' | 'row-start-end' | 'row-start' | 'saturate' | 'scale-x' | 'scale-y' | 'scale' | 'scroll-behavior' | 'scroll-m' | 'scroll-mb' | 'scroll-me' | 'scroll-ml' | 'scroll-mr' | 'scroll-ms' | 'scroll-mt' | 'scroll-mx' | 'scroll-my' | 'scroll-p' | 'scroll-pb' | 'scroll-pe' | 'scroll-pl' | 'scroll-pr' | 'scroll-ps' | 'scroll-pt' | 'scroll-px' | 'scroll-py' | 'select' | 'sepia' | 'shadow-color' | 'shadow' | 'shrink' | 'size' | 'skew-x' | 'skew-y' | 'snap-align' | 'snap-stop' | 'snap-strictness' | 'snap-type' | 'space-x-reverse' | 'space-x' | 'space-y-reverse' | 'space-y' | 'sr' | 'start' | 'stroke-w' | 'stroke' | 'table-layout' | 'text-alignment' | 'text-color' | 'text-decoration-color' | 'text-decoration-style' | 'text-decoration-thickness' | 'text-decoration' | 'text-opacity' | 'text-overflow' | 'text-transform' | 'text-wrap' | 'top' | 'touch-pz' | 'touch-x' | 'touch-y' | 'touch' | 'tracking' | 'transform-origin' | 'transform' | 'transition' | 'translate-x' | 'translate-y' | 'underline-offset' | 'vertical-align' | 'visibility' | 'w' | 'whitespace' | 'will-change' | 'z';

135

136

type DefaultThemeGroupIds = 'blur' | 'borderColor' | 'borderRadius' | 'borderSpacing' | 'borderWidth' | 'brightness' | 'colors' | 'contrast' | 'gap' | 'gradientColorStopPositions' | 'gradientColorStops' | 'grayscale' | 'hueRotate' | 'inset' | 'invert' | 'margin' | 'opacity' | 'padding' | 'saturate' | 'scale' | 'sepia' | 'skew' | 'space' | 'spacing' | 'translate';

137

138

interface ExperimentalParseClassNameParam {

139

className: string;

140

parseClassName(className: string): ExperimentalParsedClassName;

141

}

142

143

interface ExperimentalParsedClassName {

144

modifiers: string[];

145

hasImportantModifier: boolean;

146

baseClassName: string;

147

maybePostfixModifierPosition: number | undefined;

148

}

149

```