The only right way to merge Tailwind classes in ⚛️React. 👇 If you have ever built a reusable UI component with Tailwind, you have definitely run into this bug: You set a default class like px-4. Later, you use the component and try to override it by passing px-8 as a prop. You inspect the DOM, and both classes are there: class="px-4 px-8". But the padding hasn't changed. Why? Because Tailwind classes do not override based on the order they appear in your HTML. They override based on their order in the generated CSS stylesheet. The modern standard is the cn() utility function. ❌ The Legacy Way (String Concatenation): Using ${className} blindly adds classes without checking for conflicts. Ternary operators make your class strings incredibly hard to read. High risk of CSS cascade bugs. ✅ The Modern Way (clsx + tailwind-merge): A tiny utility function that intelligently merges Tailwind classes. • Conflict Resolution: If you pass px-8, it explicitly removes px-4 from the final string so the browser never gets confused. • Clean Conditionals: No more messy ternaries. Just use isActive && 'bg-blue'. • The Industry Standard: This is the exact architecture powering massive modern component libraries like shadcn/ui. The Shift: We are moving away from unpredictable string concatenation and using intelligent class merging to build bulletproof UI components. Learn how to solve Tailwind CSS class conflicts in React components using the cn utility. Discover how combining clsx and tailwind-merge prevents CSS cascade bugs, allowing you to safely override default padding, margins, and colors dynamically. #TailwindCSS #ReactJS #NextJS #WebDevelopment #Frontend #CSS #JavaScript #CleanCode #SoftwareEngineering #TechTips #TailwindTips #FrontendTips #FrontendDeveloper #DeveloperTips
an alternative approach could be to style your ui components in plain CSS and use the “components” cascade layer created by tailwind. then the component consumer can conveniently apply tailwind utilities without conflicts. cause tailwind puts these styles in a higher cascade layer (called “utilities”)
I greatly enjoy that the “right way” in react is adding another dependency to simply add/apply classes.
In the classnames npm lib you can try construction of the condition like this: classNames={cn(“simple-class”, {[“active”]: isActive})} Looks more professional
Umm, AFAIK cn() will not “merge” classes. This could lead to broken UI. Ok, just realised this WASN’T the popular cn package for React but in fact your own util.
I am using classnames + tailwind-merge looks pretty good.
برغم انه من الممكن استخدام "p-8!" لكن اراء هذا الكود انتظف
great post
🙈 Why all the abstractions? Why all the indirections? Why? See https://www.garudax.id/posts/mvneerven_frontend-webstandards-puredesignsystem-activity-7439269423850487809-lcp0