A tiny Rails view helper for constructing CSS class strings conditionally.
This gem is essentially a clone if the clsx npm package. It provides a simple way to conditionally apply classes to HTML elements in Rails views. It is especially useful when you have a lot of conditional classes and you want to keep your views clean and readable.
Supported Ruby and Rails versions
Ruby 3.1+ and Rails 7.0+ are supported.
Installation
Install the gem and add to the application's Gemfile by executing:
bundle add clsx-rails
Or add it manually to the Gemfile:
gem 'clsx-rails', '~> 1.0'
Usage
The clsx
helper method can be used in views to conditionally apply classes to HTML elements.
You can also use a slightly more conise cn
alias.
It accepts a variety of arguments and returns a string of unique classes.
# 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'
<%= tag.div class: clsx('foo', 'baz', 'is-active' => @active) do %>
Hello, world!
<% end %>
<div class="<%= clsx('foo', 'baz', 'is-active' => @active) %>">
Hello, world!
</div>
%div{class: clsx('foo', 'baz', 'is-active' => @active)}
Hello, world!
div class=clsx('foo', 'baz', 'is-active' => @active)
| Hello, world!
So the basic idea is to get rid of constructions like this in your views:
<% classes = ['foo', 'baz'] %>
<% classes << 'is-active' if @active %>
<div class="<%= classes.join(' ') %>">
Hello, world!
</div>
or like this:
<div class="<%= ['foo', 'baz', @active ? 'is-active' : nil].compact.join(' ') %>">
Hello, world!
</div>
or like this:
<div class="foo bar <%= 'is-active' if @active %>">
Hello, world!
</div>
Differences from the original clsx
package
This gem reproduces the functionality of the original clsx
package, but with nuances of Ruby and Rails in mind.
The main differences are:
-
falsy values in Ruby are only
false
andnil
, so theclsx
method will not accept0
,''
,[]
,{}
, etc. as falsy values.clsx('foo' => 0, bar: []) # => 'foo bar'
-
clsx-rails
supports complex hash keys, like{ %[foo bar] => true }
, which will be converted tofoo bar
in the resulting string. Meaning, if it's a valid input for theclsx-rails
, it's a valid hash key.clsx([{ foo: true }, 'bar'] => true) # => 'foo bar'
-
clsx-rails
will ignore objects that areblank?
, boolean (true
orfalse
), or an instance ofProc
(so, procs and lambdas).clsx('', [], {}, proc {}, -> {}, nil, false, true) # => nil
-
clsx-rails
returnsnil
if there are no classes to apply, instead of an empty string. The reason for that is not to pollute the HTML with emptyclass
attributes when using Rails tag helpers: Rails will not render theclass
attribute if it'snil
.clsx(nil, false) # => nil
Although, it won't help if you're using it directly in erb:
<div class="<%= clsx(nil, false) %>"> Hello, world! </div>
This code will render
<div class="">Hello, world!</div>
anyway. -
clsx-rails
eliminates duplicate classes:clsx('foo', 'foo') # => 'foo'
Development
After checking out the repo, run bin/setup
to install dependencies. Then, run
rake test
to run the tests. You can also run bin/console
for an interactive
prompt that will allow you to experiment.
To install this gem onto your local machine, run bundle exec rake install
. To
release a new version, update the version number in version.rb
, and then run
bundle exec rake release
, which will create a git tag for the version, push
git commits and the created tag, and push the .gem
file to
rubygems.org.
There is a simple benchmark script in the benchmark
directory.
You can run it with bundle exec ruby benchmark/run.rb
.
I've added it for easier performance testing when making changes to the gem.
Conventional Commits
This project uses Conventional Commits for commit messages.
Types of commits are:
-
feat
: a new feature -
fix
: a bug fix -
perf
: code that improves performance -
chore
: updating build tasks, configs, formatting etc; no code change -
docs
: changes to documentation -
refactor
: refactoring code
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.