css_modules
css_modules copied to clipboard
Local CSS rules for sass, Rails views and JS
CSSModules
An alternative to "magic string" classnames in Sass or SCSS.
Thanks to Fatih Kadir Akın for his post, "How I Implemented CSS Modules in Ruby on Rails, Easily", which led the way on this idea!
Usage
Add modules to stylesheets
Your .sass or .scss stylesheets can define modules with :module(module_name):
:module(events) {
.header {
font-style: bold;
}
.link:visited {
color: purple;
}
#footer {
font-size: 0.8em;
}
}
Sass requires an extra \:
\:module(events)
.header
font-style: bold
Put modulized names into HTML
To access the contents of a module in a view, you must include the helpers in your controller:
class EventsController < ApplicationController
helper CSSModules::ViewHelper
end
(To use the view helper everywhere, include it in ApplicationController.)
Then, in your view, you can access the module & its contents by name:
<!-- access by module + identifier -->
<h1 id="<%= css_module("events", "main_header") %>">
Events
</h1>
<!-- block helper -->
<% css_module("events") do |events_module| %>
<div id="<%= events_module.selector("footer") %>">
<%= link_to "Home", "/", class: events_module.selector("link") %>
© My company
</div>
<% end %>
Extra classes
You can also provide multiple, space-separated class names and/or extra class names to join without a module:
# Apply "events" to "image-wrapper" and "image", then add "pull-left" without modification
css_module("events", "image-wrapper image", "pull-left")
#=> "events_123_image-wrapper events_123_image pull-left
Null module
If you pass nil as the module name, no transformation is applied to the selectors.
css_module(nil, "media-row")
# => "media-row"
css_module(nil) do |styles|
styles.selector("image image--main", "pull-left")
# => "image image--main pull-left"
end
Use modulized names in JavaScript
In JavaScript, you can include a helper to access module styles:
//= require css_module
// Module + identifier
var headerClass = CSSModule("events", "header")
$("." + headerClass).text() // => "Events"
// Or module helper function
var eventsModule = CSSModule("events")
function header() {
var headerClass = eventsModule("header")
return (
<h1 className={headerClass}>Events</h1>
)
}
Extra classes
You can also provide multiple, space-separated class names and/or extra class names to add without a module:
// Apply "events" to "image-wrapper" and "image", then add "pull-left" without modification
CSSModule("events", "image-wrapper image", "pull-left")
// "events_123_image-wrapper events_123_image pull-left"
Null module
If you pass null as the module name, CSSModule will make no transformation:
CSSModule(null, "item")
// => "item"
var cssModule = CSSModule(null)
cssModule("item")
// => item
Installation
Add this line to your application's Gemfile:
gem 'css_modules'
And then execute:
$ bundle
Or install it yourself as:
$ gem install css_modules
Implementation notes
- The gem outputs shorter names when
Rails.env.production? - Module names are hashed in Ruby and JS, see
transform.rbandcss_module.jsfor the hash function
TODO
- Dead code warning for Development env:
- Warn when not all styles are used?
- Sprockets require CSS to JS?
require_styles?
- Support plain
.css - Check for hash collisions in development
- Fix sprockets cache: a new version of this gem should expire an old cache
License
MIT.