DEV Community

Cover image for You do not need to use the classnames package
Nick Taylor
Nick Taylor Subscriber

Posted on • Originally published at iamdeveloper.com on

You do not need to use the classnames package

Do not get me wrong, the classnames package is really handy. It is also quite popular with just over 3.5 million downloads per week as of the date of this blog post. Most React based projects I have worked on use it.

If you are not familiar with the classnames package, it allows you to build a set of CSS classes based on some conditionals. Straight from there documentation:

classNames('foo', 'bar'); // => 'foo bar'
classNames('foo', { bar: true }); // => 'foo bar'
classNames({ 'foo-bar': true }); // => 'foo-bar'
classNames({ 'foo-bar': false }); // => ''
classNames({ foo: true }, { bar: true }); // => 'foo bar'
classNames({ foo: true, bar: true }); // => 'foo bar'
Enter fullscreen mode Exit fullscreen mode

Note: true and false are used to simplify the example, but normally these would be conditional variables, methods or functions.

Having said that, JavaScript has come a long way and there are features in the language that allow us to do pretty much the same thing, specifically template strings or as it is also called, template literals.

If you are not familiar with template strings, you can build a string with variables mixed in. Let us look at the previous examples, but this time with template strings.

`foo bar` // => 'foo bar', not that exciting
`foo ${ true ? 'bar': '' }`; // => 'foo bar'
`${true ? 'foo-bar': '' }`; // => 'foo-bar'
`${ false ? 'foo-bar' : ''}` // => ''
`${ true? 'foo': '' }, { true ? 'bar': '' }`; // => 'foo bar'
`${ true ? 'foo' : ''} ${ true? 'bar' : '' }`; // => 'foo bar'
Enter fullscreen mode Exit fullscreen mode

These are trivial examples, but it is just to show you that you can do pretty much the same thing with template literals. If you want to see this in action, here is an example from my site's source:

GitHub logo nickytonline / nickytdotco

Source code for my web site nickyt.co

Netlify Status

Nick Taylor's Personal Website

This is the source code for nickyt.co, Nick Taylor's personal website and blog.

Tech Stack

  • Astro - Modern web framework for building fast, content-focused websites
  • React - For interactive UI components
  • MDX - For blog posts and content with embedded components
  • Tailwind CSS - Utility-first CSS framework
  • TypeScript - Type-safe JavaScript
  • Expressive Code - Syntax highlighting for code blocks
  • Netlify - Hosting and deployment platform
  • Node.js 22+ - Runtime environment

Terminal commands

Install the dependencies first

npm install
Enter fullscreen mode Exit fullscreen mode

Run in dev mode

npm run dev
Enter fullscreen mode Exit fullscreen mode

Build a production version of the site

npm run build
Enter fullscreen mode Exit fullscreen mode

Test the production site locally

npm run preview
Enter fullscreen mode Exit fullscreen mode

Styling

  • Tailwind v4 is configured in tailwind.config.cjs and postcss.config.cjs.
  • Global styles are loaded from src/styles/tailwind.css, which imports src/styles/legacy.css for bespoke rules.

Licensing

This project contains two separate licenses:

  1. Code License: The website's source code (in the project root and…







...
<nav
   className={`navbar is-transparent ${styles.navbar}`}
   role="navigation"
   aria-label="main-navigation"
   data-cy="nav-bar"
>
...
Enter fullscreen mode Exit fullscreen mode

https://github.com/nickytonline/www.iamdeveloper.com/blob/master/src/components/Navbar.tsx#L51

This is not mind blowing code, but just another way to do it.

Happy coding!

Photo by David Rotimi on Unsplash

Top comments (6)

Collapse
 
pallymore profile image
Yurui Zhang
`${ false ? '' : 'foo-bar'}` // => ''
Enter fullscreen mode Exit fullscreen mode

this should return 'foo-bar' instead of ''.

For simple use cases classnames is definitely an overkill, but I would say if you have more than 2 conditions in the same template literal it becomes ugly really quickly.

Also there is a smaller package for the same purpose called clsx.

Collapse
 
nickytonline profile image
Nick Taylor • Edited

Thanks, correction made. Yes, agreed that it could get unwieldy, just showing another way of doing things is all. 😉

Collapse
 
lesbaa profile image
Les • Edited

Agreed, I think classNames is a bit of overkill for what is essentially concatenation of strings. However template literals can get hectic and hard to reason about very quickly. What I normally do is:

const componentClassName = [
  'some-base-class',
  someBooleanCondition && 'a-class-in-here',
  someOtherBoolean && 'another-class',
]
  .filter(Boolean)
  .join(' ')

Enter fullscreen mode Exit fullscreen mode

Written on a mobile so forgive any typos!

Collapse
 
tomekbuszewski profile image
Tomasz Buszewski

I remember ditching classnames long ago. At some point we've decided that vendor for joining strings is an overkill. I think we've used something like this (pseudocode):

const cls = (input: string|boolean[]): string => input.filter((cond: string | boolean) => typeof cond === "string").join(", ");

<div className={cls(["one", isTrue ? "two" : "three", isAnything && "four"]) />
Enter fullscreen mode Exit fullscreen mode

And it worked perfectly. You could drop the filter element, but then you'll get false as one of the classes from time to time.

Collapse
 
gnsp profile image
Ganesh Prasad

I had written a very similar blogpost about 2 years ago. Eventually after using template literals in major projects, (some of them currently in production on zomato), I found a number of pitfalls and redundancies with this approach. This led me to developing a safer and easier-to-use template literals based classNames alternative called classd. Recently I wrote a blogpost on opensourcing classd describing the usecases. classd also provides a classNames like function (classdFn) which is intended to be a drop-in replacement for classNames. It supports more types than POJOs (like maps, sets and iterables) and in majority of cases it's more performant than classNames. Do give it a try if you are interested in using template literals for composing classes.

Collapse
 
simkessy profile image
simkessy

I've been using template strings to build classes for a while and every time I come up against an existing project which uses classNames I scratch my head trying to understand why this exist. Thanks for validating this view.