Project

clsx-rails

0.0
No release in over a year
Build CSS class strings from conditional expressions, hashes, arrays, or nested structures. 2-4x faster drop-in replacement for Rails class_names. Supports ViewComponent, Phlex, and Tailwind CSS.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
 Dependencies

Runtime

~> 1.1, >= 1.1.3
 Project Readme

clsx-rails Gem Version Codecov CI GitHub License

The fastest conditional CSS class builder for Rails — 2-4x faster drop-in replacement for class_names. Powered by clsx-ruby.

Adds clsx and cn helpers to all views automatically.

Quick Start

bundle add clsx-rails

Or add it manually to the Gemfile:

gem 'clsx-rails', '~> 3.0'

That's it — clsx and cn are now available in all your views:

<%= tag.div class: clsx('btn', 'btn-primary', active: @active) do %>
  Click me
<% end %>

Why clsx-rails over Rails class_names?

Faster

2-4x faster than Rails class_names across every scenario:

Scenario clsx Rails class_names Speedup
String array 1.2M i/s 317K i/s 3.9x
Multiple strings 1.3M i/s 346K i/s 3.8x
Single string 2.3M i/s 812K i/s 2.9x
Mixed types 901K i/s 331K i/s 2.7x
Hash 1.7M i/s 684K i/s 2.4x
String + hash 1.2M i/s 550K i/s 2.1x

Ruby 4.0.1, Apple M1 Pro. Reproduce: bundle exec ruby benchmark/run.rb

More features

Feature clsx-rails Rails class_names
Conditional classes yes yes
Auto-deduplication yes yes
2-4x faster yes no
Returns nil when empty yes no (returns "")
Complex hash keys yes no
Short cn alias yes no

Usage

# Strings (variadic)
clsx('foo', true && 'bar', 'baz')
# => 'foo bar baz'

# Hashes
cn(foo: true, bar: false, baz: a_method_that_returns_true)
# => 'foo baz'

# Hashes (variadic)
clsx({ foo: true }, { bar: false }, nil, { '--foobar': 'hello' })
# => 'foo --foobar'

# Arrays
cn(['foo', nil, false, 'bar'])
# => 'foo bar'

# Arrays (variadic)
clsx(['foo'], ['', nil, false, 'bar'], [['baz', [['hello'], 'there']]])
# => 'foo bar baz hello there'

# Kitchen sink (with nesting)
cn('foo', ['bar', { baz: false, bat: nil }, ['hello', ['world']]], 'cya')
# => 'foo bar hello world cya'

ERB

<%= tag.div class: clsx('foo', 'baz', 'is-active': @active) do %>
  Hello, world!
<% end %>

<div class="<%= clsx('foo', 'baz', 'is-active': @active) %>">
  Hello, world!
</div>

HAML

%div{class: clsx('foo', 'baz', 'is-active': @active)}
  Hello, world!

Slim

div class=clsx('foo', 'baz', 'is-active': @active)
  | Hello, world!

Framework Examples

ViewComponent

class AlertComponent < ViewComponent::Base
  def initialize(variant: :info, dismissible: false)
    @variant = variant
    @dismissible = dismissible
  end

  def classes
    clsx("alert", "alert-#{@variant}", dismissible: @dismissible)
  end
end

Phlex

class Badge < Phlex::HTML
  include Clsx::Helper

  def initialize(color: :blue, pill: false)
    @color = color
    @pill = pill
  end

  def view_template
    span(class: clsx("badge", "badge-#{@color}", pill: @pill)) { yield }
  end
end

Tailwind CSS

class NavLink < ViewComponent::Base
  def initialize(active: false)
    @active = active
  end

  def classes
    clsx(
      'px-3 py-2 rounded-md text-sm font-medium transition-colors',
      'text-white bg-indigo-600': @active,
      'text-gray-300 hover:text-white hover:bg-gray-700': !@active
    )
  end
end

Differences from JavaScript clsx

  1. Returns nil when no classes apply (not an empty string). Rails tag helpers skip nil, preventing empty class="" attributes:

    clsx(nil, false) # => nil
  2. Deduplication — duplicate classes are automatically removed:

    clsx('foo', 'foo') # => 'foo'
  3. Falsy values — in Ruby only false and nil are falsy, so 0, '', [], {} are all truthy:

    clsx('foo' => 0, bar: []) # => 'foo bar'
  4. Complex hash keys — any valid clsx input works as a hash key:

    clsx([{ foo: true }, 'bar'] => true) # => 'foo bar'
  5. Ignored values — boolean true and Proc/lambda objects are silently ignored:

    clsx('', proc {}, -> {}, nil, false, true) # => nil

Looking for a framework-agnostic version?

See clsx-ruby — works with Rails, Sinatra, Hanami, or plain Ruby.

Supported Versions

Ruby 3.2+ and Rails 7.2+.

Development

bin/setup                          # install dependencies
bundle exec rake test              # run tests
bundle exec ruby benchmark/run.rb  # run benchmarks

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/svyatov/clsx-rails.

License

The gem is available as open source under the terms of the MIT License.