Sonntag, 24. Mai 2015

Use SASS for CSS!

Ruby On Rails ships with SASS as CSS extension and there is a reason why.
It should be preferred over plain CSS because SASS:
  1. adds very useful features like variables and mixins
  2. allows nesting for reducing selector overhead and increasing readability by mapping the selectors depth
  3. adds properties like control directives and inheritance
  4. provides functions for colors, strings and lists
For example a pure CSS file people.css styles a toggle button and its look switching between the two states CSS based:
.icon:before{
  font-family: "Glyphicons Halflings";
}
.chevron-up:before{
  content: "\e113";
}
.chevron-down:before{
  content: "\e114";
}
#person input.toggle{
  display: none;
}
#person input.toggle:checked + .icon.chevron-down:before{
  content: "\e114";
}
styling the HTML snippet:
suffers from several point of views:
  1. even in that tiny CSS it repeats the DOM selector structure over and over (e.g. "#person input.toggle")
  2. a general style (e.g. content: "\e114";) has to be repeated if it has to be used in different contexts.
  3. styles belonging to the same selector structure are separated (e.g. "#person input.toggle" and "#person input.toggle:checked")
Nesting selectors and inheriting from previous defined classes solve the issues. The exactly same CSS can be generated by a SASS file people.css.scss like:
.icon:before{
  font-family: "Glyphicons Halflings";
}
.chevron-up:before{
  content: "\e113";
}
.chevron-down:before{
  content: "\e114";
}
#person{
  input.toggle{ display: none; }
  &:checked + .icon.chevron-up:before{
    @extend .chevron-down;
  }
}
The #person specific CSS was improved by nesting the selectors below #person and input.toggle. The @extend directive allows chevron-up icons to inherit their content from the more general chevron-down class.
Mixins also are nice. Whenever you want the output of the inherited style to change depending on how you call it, mixins are to be preferred over @extend. For example:
.width25{
  width: 25%;
}
.width50{
  width: 50%;
}
.width100{
  width: 100%;
}
#person .icon{
  display: block;
}
and the HTML:
cries for a inheritance in SASS:
@mixin .width($percent){
  width: $percent;
}
#person .icon{
  @include width(50%);
  display: block;
}
and in result even the HTML can be cleaned up by removing the nasty width class:
Variables not only help to assign parameters, they also help to dry out value repetition. For example:
.icon{
  background-color: #5CB85C;
  color: #A347A3;
}
.icon:first-child{
  background-color: #5CB85C;
  color: #A347A3;
}
which just styles the color and the background-color for icons, but inverting the colors for each first icon. The same with SASS:
$brand-primary: #5CB85C;
$brand-invert: invert($brand-primary);

.icon{
  background-color: $brand-primary;
  color: $brand-invert;
  &:first-child{
    background-color: $brand-invert;
    color: $brand-primary;
  }
}
using the variables $brand-primary and $brand-invert for defining the colors globally. Please note variables should be defined in a separate variables.css.scss
The inverted color code is calculated by the SASS function invert(), which ensures the invert color is always inverted.
SASS offers a lot more for many more use cases. Reading the well written SASS documentation helps to solve them.
Further articles of interest:

Supported by Ruby 2.1.1 and Ruby on Rails 4.1.8