Robin Malfait

April 28, 2024

Conditionally applying CSS classes

There are a lot of npm packages for conditionally rendering your CSS classes. But you can also use this tiny function to do 90% of what you want.

A nice benefit is that this is such a small and simple function, which means that you can copy and paste it to all your projects without the need for installing another dependency or even maintaining it.

It works by filtering out all falsey values, this means that if you use a condition like someCondition && "the classes to apply" that you will either get a falsey value or the string of classes when the someCondition was truthy.

Implementation

function classNames(...classes: (string | false | undefined | null)[]) {
  return classes.filter(Boolean).join(' ')
}

Usage

Grouping classes together

<div
  classNames={classNames(
    'flex flex-col items-center',
    'bg-blue-500 hover:bg-blue-400',
    'text-white',
  )}
/>

Using short-circuit evaluation

<div
  classNames={classNames(
    disabled && 'opacity-50',
    selected && 'bg-blue-500 text-white',
    large && 'text-3xl',
  )}
/>

Using ternary operators

<div
  classNames={classNames(
    active ? 'bg-blue-500 text-white' : 'bg-gray-100 text-gray-900',
    large ? 'text-3xl' : 'text-base',
  )}
/>

Using explicit states, with short-circuit evaluation

<div
  classNames={classNames(
    stopLightState === 'stop' && 'bg-red-500',
    stopLightState === 'go' && 'bg-green-500',
    stopLightState === 'wait' && 'bg-orange-500',
    stopLightState === 'be-careful' && 'bg-orange-500 animate-pulse',
  )}
/>

Using lookup objects

let variants = {
  primary: 'bg-blue-500 text-white',
  secondary: 'bg-white text-gray-700',
}

let sizes = {
  sm: 'text-sm',
  md: 'text-md',
  xl: 'text-xl',
}

function Example({ variant, size }) {
  return <div classNames={classNames(sizes[size], variants[variant])} />
}

Want more control?

If you prefer to write your conditional styles using arrays or objects, then this utility is not for you. In that case I can recommend some of these libraries instead:

👨‍💻

Copyright © 2024 Robin Malfait. All rights reserved.