English

Code Pool - Utilities

Minimal alternative to `clsx`!

A screenshot of a react module importing cx utility
© Code pool series - cx utility to handle multi classes.
0
15th Jun 2025

About this post

In this post, we'll create a custom function for handling conditional classNames in your projects! It'll be minimal and let you forget about installing additional packages in most cases, as you can tailor it to your project needs.

 

Table of Contents

About code pool

I decided to create a reusable collection of bare UI components and generic functions that I believe can be more useful—if not better—than a standard starter kit. While a starter kit may fit all your needs in every aspect, this is often rare. In most cases, you will encounter many unnecessary modules, and over time, you might find the structure too rigid to implement your desired changes and patterns.

With the SOC (Separation of Concerns) convention in mind, we will enhance our assets and confidently create a starter for our project in no time by selecting only the usable components and utilities!

I definitely believe that re-inventing the wheel isn't wise, but relying solely on an all-in-one solution can limit your ability to identify and solve problems. I think it's important to strike a balance between using ready-to-use assets and creating your own solutions, as this approach can help you improve your skills over time. Consider each module in the "code pool" series as a wheel that is functional and open to improvements and customizations!

Why to use?

Here are the main reasons to use this instead of clsx, classnames, and other similar npm packages:

  • It reduces at least one dependency!
  • It's customizable, allowing for interception or modifications if needed!

CX Utility

This function is a single module that handles all your multi-className concerns!

type ClassValue = string | boolean | null | undefined;
type ClassArgument = ClassValue | ClassValue[] | Record<string, any>;
export const cx = (...classes: ClassArgument[]): string => {
const processedClasses: string[] = [];
for (let i = 0; i < classes.length; i++) {
const item = classes[i];
if (!item) continue;
if (typeof item === 'string' && item !== '') {
processedClasses.push(item);
} else if (Array.isArray(item)) {
for (let j = 0; j < item.length; j++) {
const nestedResult = cx(item[j]);
if (nestedResult) {
processedClasses.push(nestedResult);
}
}
} else if (typeof item === 'object') {
const keys = Object.keys(item);
for (let k = 0; k < keys.length; k++) {
const key = keys[k];
if (item[key]) {
processedClasses.push(key);
}
}
}
}
return processedClasses.join(' ');
};

This will accept classes just as clsx or classnames do and return a single string at the end!

And here is a usage example:

...
<div
className={cx(
'bg-slate-50',
'rounded-3xl',
'overflow-hidden',
'border-2 border-black-body',
'my-2'
)}
/>
...
Rating 5 of 5
#development#for_web#code_pool