What if you want to incrementally switch to Bulma? Or build a marketing site with Tailwind while keep using SASS for your main application? It’s not as hard as you think.
The cssbundling-rails
gem is a popular choice when it comes to handling CSS in Rails. It supports Bulma, plain SASS, Tailwind, PostCSS, and Bootstrap out of the box. While there are other option, cssbundling-rails
is the most flexible solution for most.
The best part of it is design which is easy to understand.
One framework
In case you are not using cssbundling-rails
gem, you can add the gem and install the framework you are using:
$ ./bin/bundle add cssbundling-rails
$ ./bin/rails css:install:bulma
If we installed Bulma, we would end up with the bulma
package dependency as well as build:css
entry in package.json
:
{
"name": "app",
"private": "true",
"dependencies": {
...
"bulma": "^0.9.3",
"sass": "^1.45.0",
...
},
"scripts": {
"build:css": "sass ./app/assets/stylesheets/application.bulma.scss ./app/assets/builds/application.css --no-source-map --load-path=node_modules",
"build": "..."
}
}
And it’s the build:css
that does the trick in building our assets. Here we are calling the sass
executable with our stylesheet entrypoint followed by the desired build path. The whole magic is assumption that build:css
will build your assets for production.
The build name then references the bundle we include with stylesheet_link_tag
, e.g.:
<%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
On top, the gem will also add an entry to Procfile.dev
for auto-reloading in development.
$ cat Procfile.dev
web: bin/rails server -p 3000
css: yarn build:css --watch
...
Again, the magic is appending the --watch
option to the yarn
build command, so the command will rerun when there are new changes.
Two frameworks
To support two frameworks side by side, it’s enough to include both in the build:css
task.
We can start by adding our second framework the same as the first one:
$ ./bin/rails css:install:tailwind
Running the task will make sure we have all the Node packages present (adding tailwindcss
to devDependencies
) and will also update the scripts
and Procfile.dev
entries.
The key here is to keep both build commands around. In this case sass
as well as tailwindcss
:
{
"name": "app",
"private": "true",
"dependencies": {
...
"bulma": "^0.9.3",
"sass": "^1.45.0",
...
},
"scripts": {
"build:css": "sass ./app/assets/stylesheets/application.bulma.scss ./app/assets/builds/bulma_application.css --no-source-map --load-path=node_modules && tailwindcss -i ./app/assets/stylesheets/application.tailwind.css -o ./app/assets/builds/tailwind_application.css --minify",
"build": "..."
},
"devDependencies": {
"tailwindcss": "^3.3.2"
}
}
The entrypoint files are already without conflict but I changed the output names for the final CSS files to bulma_application
and tailwind_application
.
The layout will now have to require both files:
<%= stylesheet_link_tag "bulma_application", "data-turbo-track": "reload" %>
<%= stylesheet_link_tag "tailwind_application", "data-turbo-track": "reload" %>
Now things should generally work when running bin/rails assets:precompile
.
The last step is to update the Procfile.dev
. We can add each framework task as a separate script and then run both separately with Foreman:
...
"scripts": {
"build:bulma": "sass ./app/assets/stylesheets/application.bulma.scss ./app/assets/builds/application.css --no-source-map --load-path=node_modules",
"build:tailwind": "tailwindcss -i ./app/assets/stylesheets/application.tailwind.css -o ./app/assets/builds/tailwind_application.css --minify",
"build:css": "sass ./app/assets/stylesheets/application.bulma.scss ./app/assets/builds/application.css --no-source-map --load-path=node_modules && tailwindcss -i ./app/assets/stylesheets/application.tailwind.css -o ./app/assets/builds/tailwind_application.css --minify",
"build": "esbuild app/javascript/*.* --bundle --sourcemap --outdir=app/assets/builds"
}
}
And:
$ cat Procfile.dev
web: bin/rails server -p 3000
bulma: yarn build:bulma --watch
tailwind: yarn build:tailwind --watch
...
Conclusion
cssbundling-rails
can run more CSS frameworks if you want to and I was able to copy & paste Tailwind components into my Bulma layout.
Get Test Driving Rails and make your tests faster and easier to maintain.