A standalone Tailwind CSS class sorter utility powered by @herb-tools/tailwind-class-sorter. This package provides Prettier-compatible sorting, deduplication, and organization of Tailwind classes with support for multiple languages and frameworks.
- Prettier-Compatible Sorting - Uses @herb-tools/tailwind-class-sorter for consistent, Prettier-compatible class ordering
- Async API - Modern async/await interface for all functions
- Language Support - Built-in support for HTML, JSX/TSX, Haml, and customizable patterns
- CLI Tool - Command-line interface for processing files
- Ignore Comments - Respect
headwind-ignoreandheadwind-ignore-allcomments - File & Text Processing - Process entire files or text snippets programmatically
- TypeScript Support - Full type definitions included
npm install tailwind-sortimport { sortClassString } from 'tailwind-sort';
// Sort classes (async)
const sorted = await sortClassString('px-4 container mx-auto text-center', {
shouldRemoveDuplicates: true,
shouldPrependCustomClasses: false,
customTailwindPrefix: ''
});
console.log(sorted); // "container mx-auto px-4 text-center"# Sort classes in a file
npx tailwind-sort src/components/Button.tsx
# Process with custom config
npx tailwind-sort src/index.html --config tailwind.config.json
# Keep duplicates
npx tailwind-sort src/page.jsx --no-duplicates
# Use custom Tailwind prefix
npx tailwind-sort src/app.tsx --prefix "tw-"Sorts a string of CSS classes using @herb-tools/tailwind-class-sorter.
Parameters:
classString- A space-separated string of CSS classesoptions- Configuration object:shouldRemoveDuplicates: boolean- Whether to remove duplicate classesshouldPrependCustomClasses: boolean- Whether custom classes appear before Tailwind classescustomTailwindPrefix: string- Custom prefix for Tailwind classes (e.g., "tw-")separator?: RegExp- Optional custom separator patternreplacement?: string- Optional custom replacement separator
Returns: Promise<string> - The sorted and optionally deduplicated string of classes
Example:
import { sortClassString } from 'tailwind-sort';
const sorted = await sortClassString('text-lg p-4 bg-blue-500 text-center', {
shouldRemoveDuplicates: true,
shouldPrependCustomClasses: false,
customTailwindPrefix: ''
});
console.log(sorted); // "bg-blue-500 p-4 text-center text-lg"Processes text and sorts Tailwind CSS classes found using language-specific regex patterns.
Parameters:
text- The text content to processlangConfig- Language configuration (string regex, array of regexes, or config object)options- Same options assortClassString
Returns: Promise<string> - Text with sorted classes
Example:
import { processText } from 'tailwind-sort';
const html = '<div class="px-4 container mx-auto">Content</div>';
const processed = await processText(html, 'class="([^"]+)"', {
shouldRemoveDuplicates: true,
shouldPrependCustomClasses: false,
customTailwindPrefix: ''
});
console.log(processed); // '<div class="container mx-auto px-4">Content</div>'Language Config Examples:
// Simple regex string
const htmlConfig = 'class="([^"]+)"';
// JSX/React
const jsxConfig = 'className="([^"]+)"';
// Haml
const hamlConfig = '\\.([\\._a-zA-Z0-9\\-]+)';
// Multiple patterns
const multiConfig = ['class="([^"]+)"', 'className="([^"]+)"'];
// With custom separator
const customConfig = {
regex: 'class="([^"]+)"',
separator: '\\.',
replacement: '.'
};processFile(filePath: string, langConfig: LangConfig | LangConfig[], options: Options): Promise<void>
Processes a file and sorts Tailwind CSS classes in place.
Parameters:
filePath- Path to the file to processlangConfig- Language configuration for finding class stringsoptions- Same options assortClassString
Returns: Promise<void> - Resolves when file is processed and saved
Example:
import { processFile } from 'tailwind-sort';
// Process HTML file
await processFile('src/index.html', 'class="([^"]+)"', {
shouldRemoveDuplicates: true,
shouldPrependCustomClasses: false,
customTailwindPrefix: ''
});
// Process JSX file
await processFile('src/App.jsx', 'className="([^"]+)"', {
shouldRemoveDuplicates: true,
shouldPrependCustomClasses: false,
customTailwindPrefix: ''
});Builds an array of matchers from language configuration. Converts various configuration formats into a normalized array of Matcher objects.
Recursively matches text against a series of regular expressions. Used internally to extract class strings from nested language constructs.
The package includes a command-line tool for processing files directly.
tailwind-sort <file> [options]-c, --config <path>- Path to config file with langConfig (JSON)--no-duplicates- Do not remove duplicate classes--prepend-custom- Place custom classes before Tailwind classes--prefix <prefix>- Custom Tailwind prefix (e.g., "tw-")
# Basic usage
tailwind-sort src/index.html
# With config file
tailwind-sort src/app.tsx --config my-config.json
# Keep duplicates and use custom prefix
tailwind-sort src/styles.jsx --no-duplicates --prefix "tw-"
# JSX files (automatically detected)
tailwind-sort src/components/Button.tsx{
"langConfig": "className=\"([^\"]+)\""
}Or with multiple patterns:
{
"langConfig": [
"class=\"([^\"]+)\"",
"className=\"([^\"]+)\""
]
}You can prevent sorting of specific classes using special comments:
Prevents sorting of a single class string:
<!-- headwind-ignore -->
<div class="custom-order z-50 p-4 bg-blue-500">Content</div>{/* headwind-ignore */}
<div className="custom-order z-50 p-4 bg-blue-500">Content</div>Prevents sorting of all classes in a file:
<!-- headwind-ignore-all -->
<html>
<div class="unsorted classes here">Content</div>
<div class="these too will stay">More content</div>
</html>Version 2.0.0 introduces significant breaking changes. Follow this guide to migrate:
v1.x:
const sorted = sortClassString('px-4 container', options);v2.0.0:
const sorted = await sortClassString('px-4 container', options);The sortOrder parameter has been removed. Sorting now uses @herb-tools/tailwind-class-sorter which provides Prettier-compatible ordering.
v1.x:
sortClassString('px-4 container', {
classOrder: ['container', 'px-4'], // ❌ No longer used
shouldRemoveDuplicates: true,
shouldPrependCustomClasses: false
});v2.0.0:
await sortClassString('px-4 container', {
shouldRemoveDuplicates: true,
shouldPrependCustomClasses: false,
customTailwindPrefix: ''
});v1.x:
interface Options {
classOrder: string[]; // ❌ Removed
shouldRemoveDuplicates: boolean;
shouldPrependCustomClasses: boolean;
}v2.0.0:
interface Options {
shouldRemoveDuplicates: boolean;
shouldPrependCustomClasses: boolean;
customTailwindPrefix: string; // ✅ New
separator?: RegExp; // ✅ New
replacement?: string; // ✅ New
}Due to the switch to @herb-tools/tailwind-class-sorter, the sort order may differ from v1.x. The new ordering is Prettier-compatible and follows Tailwind CSS's recommended class order.
Example:
// Input
'px-4 hover:bg-blue-500 lg:px-8 text-center'
// v1.x output (depends on classOrder config)
'px-4 lg:px-8 hover:bg-blue-500 text-center'
// v2.0.0 output (Prettier-compatible)
'px-4 text-center hover:bg-blue-500 lg:px-8'v2.0.0 adds new capabilities:
// Process entire text blocks
const processed = await processText(htmlContent, 'class="([^"]+)"', options);
// Process files directly
await processFile('src/index.html', 'class="([^"]+)"', options);
// Use CLI
// npx tailwind-sort src/app.tsximport { processFile } from 'tailwind-sort';
import { glob } from 'glob';
async function sortAllClasses() {
const files = await glob('src/**/*.{html,jsx,tsx}');
for (const file of files) {
const langConfig = file.endsWith('.html')
? 'class="([^"]+)"'
: 'className="([^"]+)"';
await processFile(file, langConfig, {
shouldRemoveDuplicates: true,
shouldPrependCustomClasses: false,
customTailwindPrefix: ''
});
console.log(`Processed ${file}`);
}
}
sortAllClasses();{
"scripts": {
"precommit": "tailwind-sort $(git diff --cached --name-only --diff-filter=ACM | grep -E '\\.(html|jsx|tsx)$')"
}
}const sorted = await sortClassString('tw-px-4 tw-container tw-mx-auto', {
shouldRemoveDuplicates: true,
shouldPrependCustomClasses: false,
customTailwindPrefix: 'tw-'
});import { processText } from 'tailwind-sort';
import * as fs from 'fs/promises';
async function sortReactComponent(filePath: string) {
const content = await fs.readFile(filePath, 'utf-8');
const processed = await processText(content, 'className="([^"]+)"', {
shouldRemoveDuplicates: true,
shouldPrependCustomClasses: false,
customTailwindPrefix: ''
});
await fs.writeFile(filePath, processed, 'utf-8');
}This package is written in TypeScript and includes full type definitions.
import {
sortClassString,
processText,
processFile,
buildMatchers,
getTextMatch,
Options,
LangConfig,
Matcher
} from 'tailwind-sort';
// Full type safety
const options: Options = {
shouldRemoveDuplicates: true,
shouldPrependCustomClasses: false,
customTailwindPrefix: ''
};
const sorted: Promise<string> = sortClassString('px-4 container', options);# Install dependencies
npm install
# Build the package
npm run build
# Run tests
npm testBefore publishing:
- Ensure all tests pass:
npm test - Build the package:
npm run build - Update version in package.json
- Login to npm:
npm login - Publish:
npm publish
The prepublishOnly script will automatically run build and tests before publishing.
- @herb-tools/tailwind-class-sorter - The underlying sorting engine
- Headwind VS Code Extension - VS Code extension using this package
MIT
Murilo muriloime@gmail.com
Contributions are welcome! Please feel free to submit a Pull Request.
If you encounter any issues or have questions, please open an issue on GitHub.