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'
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'
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:
nickytonline / www.nickyt.co
Source code for my web site nickyt.co
Welcome
This is the source code for the web site of Nick Taylor built using the Eleventy static site generator. It uses Andy Bell's Hylia template. I've made tweaks to it and will probably make more over time, but just wanted to give Andy a shout out for his awesome template.
Terminal commands
Install the dependencies first
npm install
Serve the site locally in watch mode
npm start
Build a production version of the site
npm run production
Test the production site locally
cd dist
npx serve
Licensing
This project contains two separate licenses:
-
Content License: All blog posts, articles, and other written content in the
src/blog
directory are licensed under the Creative Commons Attribution 4.0 International License (CC BY 4.0).- You are free to share and adapt this content for any purpose, even commercially, as long as you give appropriate credit.
- To view a copy of…
...
<nav
className={`navbar is-transparent ${styles.navbar}`}
role="navigation"
aria-label="main-navigation"
data-cy="nav-bar"
>
...
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)
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
.Thanks, correction made. Yes, agreed that it could get unwieldy, just showing another way of doing things is all. 😉
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:
Written on a mobile so forgive any typos!
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):And it worked perfectly. You could drop the
filter
element, but then you'll getfalse
as one of the classes from time to time.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.
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.