logoNavigate back to the homepage




June 19th, 2020 · 2 min read


A very common situation in the lives of web developers is to add classes to change the way a component or <div> looks when the user clicks or interacts with the website. Most commonly developers try a very imperative approach where classes are added upon a series of if-else conditions.

what if we were to tell you that is a more well defined declarative way of doing this. In this article we will be discussing classnames, a npm package which provides us the tools for the same.


Originally classnames was shipped with the react addon bundle as classSet and was later pulled out, now it can also be used in a vanilla javascript project. It provides typescript typings through @types/classnames and needs no extra configuration. it exports a single function that can be included into your scripts as:

1/* babel */
2import classnames from "classnames";
4/* node or require js */
5const classnames = require("classnames");

usage of this package most commonly falls into one of the following buckets:

Simple Class Augmentation

The most basic functionality of classnames can be considered as to take a list of strings and join them with a space in between. The main advantage we get by doing this is to make it more declarative.

Let us consider the following example:

1<div class="block block-a"></div>

This can be written using classnames as

1<div class=classnames("block", "block-a")></div>

Conditional Class Augmentation

The most widely used application of this package is to specify that the class names must be included based on a condition.

let us consider the following example:

1const classes = "block ";
2if (condition1) {
3 classes += "block-a ";
4} else {
5 classes += "block-b ";
7<div class=classes></div>

In the above example we should keep in mind that there is a whitespace at the end, else it will not get interpreted in the manner we intend. we can convert this to a more easy to maintain one liner as follows:

1const classes = classnames({
2 "block": true
3 "block-a": condition1,
4 "block-b": !condition1
6<div class=classes></div>

Here all classes whose values are true or conditions that evaluate to true are taken to the result.

Flattening Class Augmentation

In actual the classnames function takes any number of arguments and can be one of string, object, array and any combination of the above types. In cases of objects and arrays it recursively traverses and includes the truthy values to the result. By now you might have guessed that our Simple Augmentation example in reality is actually a shorthand of this to simplify the expression. Below you can find a cheat sheet of some examples and how the result comes out as:

1classnames("block", {"block-a": true}) &rarr; <em>block block-a</em>
2classnames("block", "block-a") &rarr; <em>block block-a</em>
3classnames("block", {"block-a": false}, {"block-b": true}) &rarr; <em>block block-b</em>
4classnames("block", ["block-a", {"block-b": true}]) &rarr; <em>block block-a block-b</em>
6/* truthy and falsy values */
7classnames(null, "block", undefined, 1, {"block-a": null}) &rarr; <em>block 1</em>

Evaluation metrics

Active usageGoodAround 5M weekly downloads at the time of writing, more than 22K dependent packages on npm, pretty stable API’s
SecurityGoodNo vulnerabilities reported on npm audit or retire.js
Ease of useGoodTypescript support, no extra configuration required, zero dependencies, Simple syntax, extensible feature set,
CommunityAveragerecent updates have been few and far apart, no activity in regards to pending issues, backed by thinkmill
Docs and TrainingsGoodofficial docs have detailed examples and are more than enough to understand the complete API

Our video review of the package

Video review of the package with interesting use cases and in-depth exploration of the features coming soon!


The content and evaluation scores mentioned in this article/review is subjective and is the personal opinion of authors at Unpackaged Reviews based on everyday usage and research on popular developer forums. They do not represent any company’s views and is not impacted by any sponsorships/collaboration.

Header Photo by Pankaj Patel on Unsplash

More articles from Unpackaged Reviews

Distributed Tracing - Explained

An Introduction to Distributed Tracing

May 12th, 2021 · 3 min read


Unhinge Yourself From Boilerplate Code

January 29th, 2021 · 4 min read
© 2020-2021 Unpackaged Reviews
Link to $https://twitter.com/unpakgd_reviewsLink to $https://unpackaged-reviews.medium.com