classnames

A tiny utility for conditionally joining CSS class names together.

Library
npm
v2.5.1
17,770 stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum. How we score it →
56 /100 Fair
Development Activity 56
Maintenance 8
Community 60
Maturity 60
Momentum 40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation. How we score it →
87 /100 Excellent
Architecture 82
Code Quality 88
Innovation 85
Learning Curve 92

classnames is a lightweight JavaScript utility, ubiquitous in the React ecosystem, that merges strings, objects, and arrays into a single space-separated className string. Instead of hand-building conditional className logic with ternaries and string concatenation, developers pass truthy/falsy flags as a plain object and let classnames decide which class names survive.

With zero runtime dependencies and a footprint of well under 1KB, it has become a de facto standard for building dynamic UI class lists in component-based frameworks, and ships bind and dedupe variants for CSS Modules and dedup-sensitive use cases respectively.

What You Get

  • Zero-dependency, sub-1KB core classNames() function for conditional class joining
  • classnames/bind variant pre-bound to a CSS Modules style map via a cx() helper
  • classnames/dedupe variant that removes duplicate and overridden class names
  • Full TypeScript type definitions shipped inline (index.d.ts, bind.d.ts, dedupe.d.ts)
  • ESM-only package with sideEffects: false for optimal tree-shaking

Common Use Cases

  • Toggling a CSS class based on component state (e.g. isActive, isPressed, isHovered)
  • Merging a consumer-supplied className prop with a component’s own base classes
  • Building dynamic utility-class strings from multiple conditional sources
  • Binding to CSS Modules style objects to reference local class names instead of raw strings

Under The Hood

Architecture classnames is deliberately minimal: three independent entry points (index.js, bind.js, dedupe.js) share the same conceptual pipeline of recursively flattening arguments (string, object, or array) into class names, but each swaps its accumulation strategy for a different goal. The default build concatenates into a string as it goes; bind.js layers a this-bound lookup so cx() can translate logical names into CSS Modules’ hashed class names; dedupe.js instead accumulates into a null-prototype StorageObject keyed by class name so later truthy/falsy values naturally overwrite earlier ones, producing de-duplicated output at roughly 5x the cost of the default. Module boundaries are exposed cleanly via package.json exports subpaths rather than a single monolithic API.

Tech Stack The package itself has zero runtime dependencies and ships as pure ESM ("type": "module") with sideEffects: false for tree-shaking. Its devDependency set is entirely tooling: Rollup for browser benchmark bundling, tsd for asserting the shipped .d.ts files against real usage, and tinybench/http-server for the in-repo benchmark suite that runs in CI. TypeScript types are hand-written and versioned alongside the JS, not generated.

Code Quality The tests/ directory covers all three entry points (index.js, bind.js, dedupe.js) plus .test-d.ts type-assertion files, using Node’s built-in node:test runner — no external test framework dependency. Coverage is thorough for a small library: truthy/falsy edge cases (NaN, -0, empty string, empty object/array), deep array recursion, custom/inherited toString() overrides, and even execution inside a Node vm context to catch cross-realm bugs. CI (.github/workflows/node.js.yml) runs the test suite across Node 18/20/21, type-checks the .d.ts files, and runs the benchmark suite on every push and PR — there is no separate ESLint/Prettier config in the repo, so style consistency relies on convention rather than tooling.

API Design The public API is a single variadic function call that accepts strings, objects, arrays, or any mix thereof, which removes essentially all boilerplate compared to manual ternary/string-concatenation class building. Argument handling is intuitive and well documented in the README with realistic React examples. The bind and dedupe variants reuse the exact same calling convention as the default export, so switching between them is a one-line import change with no API relearning. The main friction point is the ESM-only, type: module packaging, which is a minor breaking change for consumers still on CommonJS-only tooling.

Used by 68 apps in this directory

TypeScript
55%
Other

agenta

AI Development · Developer Tools · Devops

4,856

The open-source LLMOps platform unifying prompt engineering, evaluation, and observability for teams building reliable LLM applications.

View details
91
Repo Health
77
Technical
66
Dependency
Built with
TypeScript 55%
Python 40%
Updated 6 days ago
Python
86%
MIT

ai-toolkit

AI Design Tools · AI Development

12,446

An all-in-one open-source training suite for finetuning diffusion models—FLUX, SDXL, Wan video, and audio—on consumer GPU hardware via CLI or web UI.

View details
79
Repo Health
66
Technical
72
Dependency
Built with
Python 86%
TypeScript 14%
Updated 1 weeks ago
TypeScript
95%
Apache 2.0

AionUi

AI Agents · Productivity

33,741

Free, open-source Cowork desktop app that unifies Claude Code, Codex, Gemini CLI, and 20+ AI agents into a single platform with multi-agent teams, 24/7 cron automation, and zero-config built-in agent.

View details
88
Repo Health
76
Technical
66
Dependency
Built with
TypeScript 95%
Updated 1 weeks ago
Python
48%
Other

Airbyte

Data Engineering · Developer Tools

22,260

Open-source ELT platform with 600+ connectors for moving data from any source to warehouses, lakes, and AI agents.

View details
95
Repo Health
80
Technical
64
Dependency
Built with
Python 48%
Kotlin 44%
Updated 6 days ago
TypeScript
72%
AGPL 3.0

APITable

Databases · Low Code Platforms

15,647

API-first collaborative spreadsheet-database platform that auto-generates REST APIs and lets teams build internal tools, CRMs, and dashboards without code.

View details
68
Repo Health
77
Technical
60
Dependency
Built with
TypeScript 72%
Java 22%
Updated 1 months ago
TypeScript
96%
Other

Amplication

AI Code Assistants · Automation · Developer Tools

16,009

Create production-ready backend services with your organization's standards baked in — generating NestJS, Prisma, and GraphQL code that you own and control.

View details
57
Repo Health
84
Technical
60
Dependency
Built with
TypeScript 96%
Updated 4 months ago
Go
61%
Apache 2.0

Apache Answer

Community

15,700

Open-source Q&A platform for communities, help centers, and knowledge bases with AI assistant and plugin extensibility

View details
89
Repo Health
78
Technical
68
Dependency
Built with
Go 61%
TypeScript 36%
Updated 1 weeks ago
TypeScript
68%
Apache 2.0

Appsmith

Automation · Developer Tools · No Code Platforms

41,113

Open-source low-code platform to build admin panels, dashboards, and internal tools connected to any database or API.

View details
94
Repo Health
79
Technical
63
Dependency
Built with
TypeScript 68%
Java 22%
Updated 1 weeks ago
Go
86%
Apache 2.0

Argo Workflows

Data Engineering · Devops

17,050

The most popular Kubernetes-native workflow engine for orchestrating containerized DAGs, ML pipelines, CI/CD, and parallel batch jobs at scale.

View details
96
Repo Health
90
Technical
68
Dependency
Built with
Go 86%
TypeScript 10%
Updated 1 weeks ago

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers