Lighten or Darken a CSS Colour in Ruby on Rails
Lightning or darkening a given color is a common requirement in user interface development. For example we will have a button with a box-shadow
property that is darker than the button background-color
. Most of such styles will go bundled with the the primary stylesheets. It also comes handy to have ways to dynamically generate CSS in cases of user configurable themes. Here are few ways you can lighten and darken a given HEX color in Ruby.
Note: While HEX is sued as an example, you can use any color definition in y understanding.
Static Usage - Stylesheets
If your needs are static and it doesn't change by any user configuration (ie: styles stored in a database) you can use the Sass lighten
and darken
helpers.
Ex: app/assets/stylesheets/themes/default.sass
$default-color: #4f99a6
.btn
.btn-defeault
background-color: $default-color
box-shadow: 0 3px 0 darken($default-color, 15%)
Dynamic Usage - Views & Helpers
There are times when we need to dynamically generate styles. For example assume a SaaS web application. It would need to allow its tenants to custom choose backgrounds, button colors, alert styles etc. In such cases we can't rely on compiled assets as they are compiled deploy time. Instead we need to generate them on the fly. As a result if you are doing this, it would be good to keep in mind to cache to save compute in repeated requests.
Saas in Haml Views
HAML supports inclusion of Sass styles in views. It also supports ruby variable interpolation. As a result you can inject Ruby variables easily in to Saas blocks effortlessly.
Ex: app/views/layouts/tenant.html.haml
sass:
$default-color: #{current_tenent.theme.colors.default}
.btn
.btn-defeault
background-color: $default-color
box-shadow: 0 3px 0 darken($default-color, 15%)
Slim
Unfortunately the way Slim integration with Saas works, it doesn't support injecting variables. How ever it does support variable injection in markdown, textile and rdoc. Hopefully they will support it in the future.
The approach I take in projects with Slim templates is different. It is...
- Have an ERB template to generate the necessary Sass (ex:
app/layouts/tenant/_theme.erb
) - A helper method to render the template and covert it to CSS
Ex ERB template app/views/layouts/tenant/_theme.erb
$default-color: <%= theme.colors.default %>
.btn
.btn-default
background-color: $default-color
box-shadow: 0 3px 0 darken($default-color, 15%)
Ex Helper method
def render_tenant_theme
sass = render 'layouts/tenant/theme', theme: current_tenant.theme_data
SassC::Engine.new(sass, syntax: :sass).render
end
Plain Ruby
If for some reason you don't like to use views, you can use Ruby to calculate darkened and lightened colours. You don't need any fancy code as Ruby color gem does most of the heavy lifting for you.
Check the Github Repo to know all its options. Its easy to follow and documented.
def darken(html_code, percentage = 85)
Color::RGB
.from_html(html_code)
.darken_by(percentage)
.html
end
Conclusion
This article is in response to the article Lighten or darken a hexademical color in Ruby on Rails by Joel Friedlaender. The article is almost 10 years old and i find junior developers still referring it and making PRs reinventing the wheel. When I checked out why, it turns out that it comes as the first result when you search for some thing like ruby color darken
.
I took some time to write an article with the hope of updating the topic to make it more relevant to today. If you a better way, I would like to know your thoughts. Leave a comment or send me an e-mail. If you have already written a post I can link it to this page.
About the Author
Ziyan Junaideen -
Ziyan is an expert Ruby on Rails web developer with 8 years of experience specializing in SaaS applications. He spends his free time he writes blogs, drawing on his iPad, shoots photos.