Wikipedia says about CSS:
CSS is a style sheet language used to describe the presentation semantics (the look and formatting) of a document.
CSS is designed primarily to enable the separation of hte document content from the document presentation,
including elements such as the layout, colors, and fonts.
CSS has a very simple syntax, and there are no variables in CSS
Let's say you need to design a web-site (Ruby on Rails application), and you decide on a Color Scheme -- but later you have to change the Color Scheme either because your customer changed his mind, or because you decided your initial pick of colors wasn't good.
Changing all colors consistently throughout your CSS files can be a huge pain.. Sure, you can run multiple search-replace operations on your CSS files, but how do you know that the resulting CSS files are really consistent, and that you didn't accidentially change a color code somewhere where you didn't really intended to?
When Rails 3 starts up, it does all kinds of nice things in the background to set-up the application.. How about we use that to our advantage?
Your default ./config/environment.rb file in Rails 3 looks like this:
# Load the rails application
require File.expand_path('../application', __FILE__)
# Initialize the rails application
PilotLogs::Application.initialize!
Wouldn't it be nice if we could load some site-wide settings (Constants) beforehand, so we can use them throughout our Rails application?
Let's do just that! Let's put those settings in a file ./config/site_settings.rb , and modify our environment.rb file to load the settings before anything else:
# Load site-wide Constants / Settings
require File.join( Rails.root.to_s, 'config', 'site_settings' ) # or use Dir.pwd
# Load the rails application
require File.expand_path('../application', __FILE__)
# Initialize the rails application
PilotLogs::Application.initialize!
Now we have a place to define our site-wide settings -- very nice!
Did you ever have to re-brand a web site? Having one place for your site-wide settings can come in very handy, for example we can define several ways how we want to refer to our sitename, and can use those constants later throughout our site, e.g. for titles, for consistently spelling the site's legal name in the terms of service, etc...
# Site-Wide Settings File ./config/site_settings.rb # This file defines Modules and Constants which should be used consistently throughout the application ... module Site Name = NameShort = 'YourSite' NameCom = NameLong = 'YourSite.com' NameLegal = 'YourSite Inc.' ... end ...
You can now consistently refer to your site name as Site::Name and to the legal company name as Site::NameLegal throughout your Rails application, e.g. you can use those variables in your view files.
If you ever need to change your site name (maybe you got a hold of a better domain name down the road), or the company's legal name changes, you can simply change the constants in the ./config/site_settings.rb file, and restart your server - est voila, you rebranded your whole site with one edit!
Let's say you used ColorSchemeDesigner.com to design your color scheme.
And after adjusting your colors, you end up with this (not quite optimal) color scheme:

We can now use the same settings file to store our beloved color scheme, e.g. let's add the following to our ./config/site_settings.rb file:
... # Your Color Scheme: e.g. you might get this from http://colorschemedesigner.com/ # # DO NOT use these Constants directly! module ColorScheme # Module to tuck-away all the color-definitions that make up our color scheme PrimaryColor_1 = '#99B8FF' # lightest PrimaryColor_2 = '#407AFF' # light PrimaryColor_3 = '#305BBF' # light shade PrimaryColor_4 = '#0032A6' # dark shade PrimaryColor_5 = '#004DFF' # fullest / base-color for your color scheme PrimaryColor_6 = '#001442' # very dark, almost black (maybe you need an additional shade... define it here SecondaryColorA_1 = '#FBFF73' # lightest SecondaryColorA_2 = '#FAFF40' # light SecondaryColorA_3 = '#BCBF30' # light shade SecondaryColorA_4 = '#A2A600' # dark shade SecondaryColorA_5 = '#F8FF00' # fullest SecondaryColorB_1 = '#FF737A' # lightest SecondaryColorB_2 = '#FF4049' # light SecondaryColorB_3 = '#BF3037' # light shade SecondaryColorB_4 = '#A60008' # dark shade SecondaryColorB_5 = '#FF000D' # fullest # other colors: (try to avoid defining too many here) # Defining some colors here can come in handy if you suddenly want to use any "off" colors later: White = '#FFFFFF' Black = '#000000' Yellow = '#FFFF65' Green = '#00FF00' DarkRed = '#C00000' LightGray = '#F0F0F0' MediumGray = '#CCCCCC' Gray = '#808080' GrayText = '#777777' MedGray = '#666666' DarkGray = '#333333' end ...If you ever have to change your color scheme, just replace the color codes in the module
ColorScheme!
So far so good, but if we would use these constants above directly in our CSS files, we would end up in a similar mess as if we were using color codes directly in the CSS files.
Let's add a level of indirection..
We will now de-couple the definition of the colors (color scheme) from the usage of the colors by adding a separate module which defines/describes how the colors are used in respect to your site layout and where they are refered to throughout our CSS files. This practically describes the structure of your color usage throughout your application layout file and your other view files.
When you do your application layout, you typically decide how the structure of your page looks like in terms of page sections and elements.
You then decide on how the different sections or elements are contrasted in respect to the fonts or images you use in them. At that point, you don't have to mention a particular color (although it helps if you have one color scheme in mind) it's more about which colors are lighter, which colors are darker, and where you use the same colors -- all you really need to do is to assign names for each of the use cases of color (we'll stick those in a module Site::Color). Now you have a concise description of how color is used on your page!
To keep things simple, I am just defining Constants in the Site::Color module below -- this makes the automatic generation of our CSS files later on much easier.
Instead, we could define Hashes, e.g. Header = {:background => :PrimaryColor_1 , :font => PrimaryColor_6, ... } , but this would need more post-processing when doing the automatic generation of the CSS files.
...
# some application-wide constants, including the Site Name(s) and the
# Logical Mapping translating the Color-Scheme in the way the colors are used on our site:
module Site
# some frequently used constant throughout the site
Name = NameShort = 'YourSite'
NameCom = NameLong = 'YourSite.com'
NameLegal = 'YourSite Inc.'
module Color # ColorUsage
# DO NOT use Color Codes in here, define them in the ColorScheme module instead!
include ColorScheme # mixin color scheme..
# this defines all the symbolic color names we need to use in our CSS file(s):
# instead of Constants we could also use hashes.. but Constants are easier to replace during preprocessing
# Colors by Function:
#--------------------
Highlight = Yellow
Error = SecondaryColorB_5
Info = SecondaryColorA_1
Warning = SecondaryColorA_5
Confirmation = Green
# Colors by Page Section or Class: (of course you would want to change the names to reflect YOUR document structure)
#---------------------------------
BodyBg = PrimaryColor_1 # body background color
BodyFont = PrimaryColor_6 # normal writing font color inside body of page # NOTE HOW BodyFont IS RE-USED LATER!
BodyLink =
BodyLinkVisited = BodyFont # no special highlighting
BodyLinkHover = SecondaryColorA_5
HeaderBg = PrimaryColor_5
HeaderLogo = White # white on dark background
HeaderFont = BodyFont # some text in the header is very dark (not to stand out too much)
HeaderLink = White # white on dark background
HeaderLinkVisited = White # no special highlighting
HeaderLinkHover = SecondaryColorA_2
FooterBg = PrimaryColor_5
FooterFont = White
FooterLink =
FooterLinkVisited = FooterFont # no special highlighting
FooterLinkHover = SecondaryColorA_2
TzFont = PrimaryColor_4
TabSelected = PrimaryColor_1
TabSelectedFont = BodyFont
TabNormal = PrimaryColor_3
TabNormalFont = White
TabHover = PrimaryColor_4
TabHoverFont = SecondaryColorA_1
TableWhite = White
TableGray = LightGray
end
...
end
...
Please Note:
ColorScheme module.
All you need to do now, is to use these constants consistently throughout your CSS files... and to define a little helper method to generate the CSS files.
This will be pretty straight-forward.. We will create CSS input files which are templates, and in which we can use the symbolic names we defined earlier. From these CSS input files, we will automatically generate the real CSS files during startup.
'*.css.in' extension. Now edit those file(s),..
site_settings.rb file under the module ColorScheme
Site::Color
e.g. instead of using color codes like #030303, use the Constants you defined in module Site::Color , and write them between #-signs.
Your CSS input file(s) might now look something like this:
/* NOTES: */
/* - THIS FILE IS AN INPUT FILE ONLY, the real .css file is generated during start-up of the Rails Application */
/* - this file uses references to Constants defined in module Site::Color */
/* - references are written #SomeConstant# and will be replaced with the appropriate color code during application startup */
...
body {
font-family: "Droid Sans", helvetica, arial, sans-serif;
color: #Black#;
background-color: #BodyBg#;
margin: 0;
padding: 0;
font-size: 0.8em;
min-width: 800px;
}
a:link, a:visited {
color: #BodyFont#;
}
#header h1 {
font-size: 42pt;
margin: 0;
display: inline;
padding: 0;
font-weight: normal;
color: #HeaderLogo#;
}
#global_links a:link{ color: #HeaderLink#; }
#global_links a:visited { color: #HeaderLinkVisited#; }
#global_links a {
color: #HeaderLink#;
font-weight: bold;
text-shadow: 2px 2px 7px #111;
}
...
After you replaced all color codes in the CSS files with constants of the form #YourColorConstant#, we will use a little pre-processor, which we write in Ruby, to automatically transform our '*.css.in' CSS Input Files into regular '*.css' CSS files.
...
module Site
...
# Module Method which generates an OUTPUT CSS file *.css for each INPUT CSS file *.css.in we find in our CSS directory
# replacing any mention of Color Constants , e.g. #SomeColor# , with the corresponding color defined above
#
def self.generate_CSS_files
# assuming all your CSS files live under "./public/stylesheets"
Dir.glob( File.join( Rails.root.to_s , 'public' ,'stylesheets', '*.css.in') ).each do |filename_in|
filename_out = filename_in.sub(/.in$/, '')
# if the output CSS file doesn't exist, or the the input CSS file is newer than the output CSS file:
if (! File.exists?(filename_out)) || (File.stat( filename_in ).mtime > File.stat( filename_out ).mtime)
# in this case, we'll need to create the output CSS file fresh:
puts " processing #{filename_in}\n --> generating #{filename_out}"
out_file = File.open( filename_out, 'w' )
File.open( filename_in , 'r' ).each do |line|
if line =~ /^\s*\/\*/ || line =~ /^\s+$/ # ignore empty lines, and lines starting with a comment
out_file.print(line)
next
end
while line =~ /#(\w+)#/ do # substitute all the constants in each line
line.sub!( /#\w+#/ , Site::Color.const_get( $1 ) ) # with the color the constant defines
end
out_file.print(line)
end
out_file.close
end # if ..
end
end # def self.generate_CSS_files
...
and to add one line to our ./config/application.rb file:
... Site.generate_CSS_files # generate CSS files on start-up ...Est voila! Freshly generated CSS files after each Rails App restart. If you want to change your color scheme, just edit the color definition in the module
ColorScheme , in the ./config/site_settings.rb file, and restart your app!
Complete File ./config/environment.rb
Download: environment.rb
# Load site-wide Constants / Settings
# see: http://unixgods.org/~tilo/Ruby/Using_Variables_in_CSS_Files_with_Ruby_on_Rails.html
#
require File.join( Rails.root.to_s, 'config', 'site_settings' ) # or use Dir.pwd
Site.generate_CSS_files # generate CSS files during start-up
# Load the rails application
require File.expand_path('../application', __FILE__)
# Initialize the rails application
PilotLogs::Application.initialize!
Complete File ./config/site_settings.rb
Download: site_settings.rb
# Site-Wide Settings File , see: http://unixgods.org/~tilo/Ruby/Using_Variables_in_CSS_Files_with_Ruby_on_Rails.html
#
# This file defines Modules and Constants which should be used consistently throughout the application
# e.g. in your view files and partials (HTML files), and in your CSS files
#
# Your Color Scheme: e.g. you might get this from http://colorschemedesigner.com/
#
# DO NOT use these ColorScheme Constants in your code / CSS!
module ColorScheme # Module to tuck-away all the color-definitions that make up our color scheme
# see ColorScheme at: http://unixgods.org/~tilo/Ruby/images/ColorSchemeDesigner_3.jpg
PrimaryColor_1 = '#99B8FF' # lightest
PrimaryColor_2 = '#407AFF' # light
PrimaryColor_3 = '#305BBF' # light shade
PrimaryColor_4 = '#0032A6' # dark shade
PrimaryColor_5 = '#004DFF' # fullest / base-color for your color scheme
PrimaryColor_6 = '#001442' # very dark, almost black (maybe you need an additional shade... define it here
SecondaryColorA_1 = '#FBFF73' # lightest
SecondaryColorA_2 = '#FAFF40' # light
SecondaryColorA_3 = '#BCBF30' # light shade
SecondaryColorA_4 = '#A2A600' # dark shade
SecondaryColorA_5 = '#F8FF00' # fullest
SecondaryColorB_1 = '#FF737A' # lightest
SecondaryColorB_2 = '#FF4049' # light
SecondaryColorB_3 = '#BF3037' # light shade
SecondaryColorB_4 = '#A60008' # dark shade
SecondaryColorB_5 = '#FF000D' # fullest
# other colors: (try to avoid defining too many here)
# Defining some colors here can come in handy if you suddenly want to use any "off" colors later:
White = '#FFFFFF'
Black = '#000000'
Yellow = '#FFFF65'
Green = '#00FF00'
DarkRed = '#C00000'
LightGray = '#F0F0F0'
MediumGray = '#CCCCCC'
Gray = '#808080'
GrayText = '#777777'
MedGray = '#666666'
DarkGray = '#333333'
end # module ColorScheme
# some application-wide constants, including the Site Name(s) and the
# Logical Mapping translating the Color-Scheme in the way the colors are used on our site:
#
# USE the constants defined in the Site module throughout your code + CSS:
module Site
# some frequently used constant throughout the site
Name = NameShort = 'YourSite'
NameCom = NameLong = 'YourSite.com'
NameLegal = 'YourSite Inc.'
# email addresses for contacts might go here as well..
module Color # ColorUsage
# this module is an abstract description how colors are used throughout your site's sections, classes, divs, etc..
#
# DO NOT use Color Codes in here, but define them in the ColorScheme module instead!
include ColorScheme # mixin color scheme..
# this defines all the symbolic color names we need to use in our CSS file(s):
# instead of Constants we could also use hashes.. but Constants are easier to replace during preprocessing
# Colors by Function:
#--------------------
Highlight = Yellow
Error = SecondaryColorB_5
Info = SecondaryColorA_1
Warning = SecondaryColorA_5
Confirmation = Green
# Colors by Page Section or Class: (of course you would want to change the names to reflect YOUR document structure)
#---------------------------------
BodyBg = PrimaryColor_1 # body background color
BodyFont = PrimaryColor_6 # normal writing font color inside body of page # NOTE HOW BodyFont IS RE-USED LATER!
BodyLink =
BodyLinkVisited = BodyFont # no special highlighting
BodyLinkHover = SecondaryColorA_5
HeaderBg = PrimaryColor_5
HeaderLogo = White # white on dark background
HeaderFont = BodyFont # some text in the header is very dark (not to stand out too much)
HeaderLink = White # white on dark background
HeaderLinkVisited = White # no special highlighting
HeaderLinkHover = SecondaryColorA_2
FooterBg = PrimaryColor_5
FooterFont = White
FooterLink =
FooterLinkVisited = FooterFont # no special highlighting
FooterLinkHover = SecondaryColorA_2
TzFont = PrimaryColor_4
TabSelected = PrimaryColor_1
TabSelectedFont = BodyFont
TabNormal = PrimaryColor_3
TabNormalFont = White
TabHover = PrimaryColor_4
TabHoverFont = SecondaryColorA_1
TableWhite = White
TableGray = LightGray
end # module Site::Color
# Module Method which generates an OUTPUT CSS file *.css for each INPUT CSS file *.css.in we find in our CSS directory
# replacing any mention of Color Constants , e.g. #SomeColor# , with the corresponding color code defined in Site::Color
#
# We will only generate CSS files if they are deleted or the input file is newer / modified
#
def self.generate_CSS_files
# assuming all your CSS files live under "./public/stylesheets"
Dir.glob( File.join( Rails.root.to_s , 'public' ,'stylesheets', '*.css.in') ).each do |filename_in|
filename_out = filename_in.sub(/.in$/, '')
# if the output CSS file doesn't exist, or the the input CSS file is newer than the output CSS file:
if (! File.exists?(filename_out)) || (File.stat( filename_in ).mtime > File.stat( filename_out ).mtime)
# in this case, we'll need to create the output CSS file fresh:
puts " processing #{filename_in}\n --> generating #{filename_out}"
out_file = File.open( filename_out, 'w' )
File.open( filename_in , 'r' ).each do |line|
if line =~ /^\s*\/\*/ || line =~ /^\s+$/ # ignore empty lines, and lines starting with a comment
out_file.print(line)
next
end
while line =~ /#(\w+)#/ do # substitute all the constants in each line
line.sub!( /#\w+#/ , Site::Color.const_get( $1 ) ) # with the color the constant defines
end
out_file.print(line)
end
out_file.close
end # if ..
end
end # def self.generate_CSS_files
end # module Site