How I implemented CSS Modules to Ruby on Rails, easily.

Front-end has grown up. It is not easy to maintain front-end projects as we were doing in 2000’s. There are so many technologies, so many techniques and paradigms. Front-end is more responsible part of an application now. And when you develop a front-end included project, it may become hard to manage.

Smart people realise this issues and try to make the front-end more modular and more maintainable. One of these attempts is CSS Modules approach. This basically aims to separate CSS management into modules (as we are doing in JavaScript for a while).

Me and Adem are working in a Rails based project and it become slightly confusing b/c of the CSS parts. For sure, we are separating CSS files into files to make it manageable, but it’s not too easy to maintain HTML side then.

Modular and reusable CSS! — No more conflicts. — Explicit dependencies. — No global scope. (from CSS Modules)

I tried to find a cool way to integrate CSS Modules into our Rails project, but I cannot. So I decided to make my own.


Rails has awesome features that I still surprise when I learn about them. When I learn about I can write my own Sprockets Processors it made me feel powerful👌🏻

Me when I learn about Sprockets’ asset processors.

I created a file: config/initializers/css_modules.rb to write my own processor.

Sprockets.register_postprocessor "text/css", CSSModules.new

This allows you to register your own postprocessor (I want SASS to compile first)

And I created a class into the css_modules.rb

class CSSModules
def call(input)
{data: "body {background-color: red}"}
end
end

This rewrote all of my CSS files with body {background-color: red} (Yes, a bit trolling)

Now I need a thing that parses CSS, so I can rebuild my CSS files modularised. I found css_parser gem to parse my CSS files.

My development of config/initializers/css_modules.rb come this:

Now I need to separate my CSS modules into files.

You can change it as you wish. The important thing is you should separate your CSS files into modules.

This is how my application.scss file looks like. I created two scss files called `login` and `product`.

This is how login.scss looks like.

:global .title {
font-size: 16px;
}
.title {
font-weight: bold;
text-align: center;
  .close {
float: right;
background-color: red;
}
}

Now let’s start our server and check how our CSS looks like:

.title {
font-size: 16px; }
.bG9naW4_title {
font-weight: bold;
text-align: center; }

.bG9naW4_title .bG9naW4_close {
float: right;
background-color: red; }

😎

Done! We made the CSS parser. But it’s not finished yet. As you can see, we need to use them in HTML files!

Using CSS Modules in HTML

CSS Modules itself doing this by a JSON file. But we need to find another way.

First, I tried to build a postprocessor for ERB files just like we do in Sprockets. But I cannot make it (If you know how to, please tell). Fortunately we have Rails, then I created some view helpers to make it possible.

<div class="<%= style_for :login, :title %>">
Do Login!
</div>

To reduce the use :login keyword, we can create a scoped alternative:

<% component :login do |m| %>
<div class="<%= m.style(:title) %>">
Do Login!
<button class="<%= m.style(:close) %>">Close</button>
</div>
<% end %>

This should produce a HTML like that:

<div class="bG9naW4_title">
Do Login!
<button class="bG9naW4_close">Close</button>
</div>

So let’s create the file called app/helpers/css_modules_helper.rb file.

Done!

Using CSS Modules in JavaScript

We modularised CSS, used them in HTML files, but what about JavaScript?

We use jQuery much, and we need to integrate CSS modules into the jQuery to make them easier to use.

Let’s create a file called app/assets/javascripts/css_modules.js

Now we will able to select modules from JavaScript using `$.module` jQuery helper.

$.module("login", ".title .close")

will give you the element `.bG9naW4_title .bG9naW4_close`

That’s all! Now your application has CSS Modules features!

Note: This is very naive implementation of CSS Modules in Rails. Please open Pull Requests.

Note 2: Since I’m not a native English speaker, this article may contain some typos. Please help me to fix them.

You can try the CSS Modules example project on GitHub.