First of all, let’s get Sass up and running. To get it, get Ruby and run
gem install haml
To compile a Sass file into CSS, run
sass style.sass style.css
If you’re using a Ruby framework like Rails or Merb, you can set Sass up to compile automatically. If you aren’t - Sass works great with non-Ruby stuff - you can use the Compass Sass framework to do the same thing.
You can convert your existing CSS files to Sass using the css2sass utility:
css2sass style.css style.sass
css2sass knows about several neat Sass tricks, so it’s usually a good idea to start off your conversion using it. For this tutorial, though, open up a brand new Sass file so you can follow along.
Syntax
The first thing to learn about Sass is the syntax. Sass uses indentation and line breaks rather than curly braces and semicolons to define rules and divide up properties. This may take a little getting used to at first, but give it a try; you might find that you end up liking it (if you really hate it, Sass 2.4 will support braces and semicolons as well).
// Sass .important color: red font-weight: bold
/* CSS */
.important {
color: red;
font-weight: bold; }
Nesting
Often when writing CSS, you’ll have several selectors that all begin with the same thing. For example, you might have “#main p”, “#main .notice”, and “#main .notice h2”. It’s a pain to repeat the beginning over and over again, especially when it’s long.
Sass allows you to avoid this by nesting the child selectors within the parent selector.
// Sass
#main
p
padding-left: 1.5em
margin: 0.5em 0
.notice
font-size: 1.2em
background-color: #fff
h2
font-size: 0.8em
/* CSS */
#main p {
padding-left: 1.5em;
margin: 0.5em 0; }
#main .notice {
font-size: 1.2em;
background-color: #fff;
#main .notice h2 {
font-size: 0.8em; }
Notice how the output is formatted as much like the Sass code as possible. This is the default output mode, but there are other modes for all sorts of CSS formatting styles. There’s even one for compressing the CSS as much as possible!
You can also nest properties, so you don’t have to repeat stuff like border-left- all the time.
// Sass
.fakeshadow
border:
style: solid
left:
width: 4px
color: #888
right:
width: 2px
color: #ccc
/* CSS */
.fakeshadow {
border-style: solid;
border-left-width: 4px;
border-left-color: #888;
border-right-width: 2px;
border-right-color: #ccc; }
Parent Reference
What about pseudo-selectors, like :hover? There isn’t a space between them and their parent selector, but it’s still possible to nest them. You just need to use the Sass special character &. In a selector, & will be replaced verbatim with the parent selector.
// Sass
#main
width: 97%
a
color: #0000ff
&:hover
color: #ff0000
&:visited
color: #00ff00
/* CSS */
#main {
width: 97%; }
#main a {
color: #0000ff; }
#main a:hover {
color: #ff0000; }
#main a:visited {
color: #00ff00; }
Variables
Sass allows you to declare variables that can be used throughout your stylesheet. Variables begin with ! and can be colors, strings of text, true/false, or numbers (with units!). To use a variable in a property, just use = instead of :.
// Sass
!main_color = #ce4dd6
!style = "solid"
#header
border-bottom:
color = !main_color
style = !style
a
color = !main_color
/* CSS */
#header {
border-bottom-color: #ce4dd6;
border-bottom-style: solid; }
a {
color: #ce4dd6; }
Variables allow you to re-use colors, sizes, and other values without repeating yourself. This means that changes that should be small - tweaking the coloring or the sizing - can be done in one place, not all over the stylesheet.
Operations
In addition to just using variable values as they’re defined, you can also use operations on them. This allows you to compute element sizing and even coloration dynamically.
The standard math operations (+, -, *, /, and %) are supported for numbers, and units will be converted if possible. The same operations work for colors, where the operation is performed on the red, green, and blue components in turn.
// Sass
!sidebar_width = 150px
!main_color = #ce4dd6
#main
border:
color = !main_color
style: solid
background-color = !main_color * 1.1
padding-right = !sidebar_width + 20px
#sidebar
width = !sidebar_width
/* CSS */
#main {
border-color: #ce4dd6;
border-style: solid;
background-color: #e254eb;
padding-right: 170px; }
#sidebar {
width: 150px; }
Interpolation
Variables can be used for more than just property values. You can use #{} to insert them into property names or even selectors.
// Sass
!border_side = "left"
!border_class = "nifty"
.#{!border_class}
border-#{!border_side}:
style: solid
color: blue
/* CSS */
.nifty {
border-left-style: solid;
border-left-color: blue; }
Mixins
Mixins are one of the most powerful aspects of Sass. They allow re-use of styling - properties or even entire rules - without having to re-write them or move them into a non-semantic class.
To define a mixin, just write =mixin-name with some Sass nested underneath. To use it, write +mixin-name where you want it to be expanded.
// Sass =float-left display: inline float: left #sidebar +float-left #content img +float-left
/* CSS */
#sidebar {
display: inline;
float: left; }
#content img {
display: inline;
float: left; }
Arguments
The real power of mixins comes when you pass them arguments. Arguments are declared as a parenthesized, comma-separated list of variables. Each of those variables is assigned a value each time the mixin is used.
Mixin arguments can also be given default values by following them with = and the value. Then the user of the mixin can choose not to pass that argument and it will be assigned the default value.
// Sass
=replace-text(!img, !x = 50%, !y = 50%)
text-indent: -9999em
overflow: hidden
background:
image = image_url(!img)
repeat: no-repeat
position = !x !y
#header h1
+replace-text("/images/logo.png")
li#overview
+replace-text("/images/overview.png", 20%)
/* CSS */
#header h1 {
text-indent: -9999em;
overflow: hidden;
background-image: image_url(/images/logo.png);
background-repeat: no-repeat;
background-position: 50% 50%; }
li#overview {
text-indent: -9999em;
overflow: hidden;
background-image: image_url(/images/overview.png);
background-repeat: no-repeat;
background-position: 20% 50%; }
@import
Stylesheets can get pretty big. CSS has an @import statement that allows you to break your styles up into multiple stylesheets, but each stylesheet is a separate (expensive) HTTP request. That’s why Sass’s @import statement pulls in Sass files directly. Not only that, but any variables or mixins defined in @imported files are available in the file that imported them.
Sass has a naming convention for Sass files that are meant to be imported: they begin with an underscore. You can import these files without using the underscore, and they won’t get rendered as CSS.
// Sass: _defines.sass
!main_color = #ce4dd6
=float(!side)
display: inline
float = !side
// style.sass
@import defines.sass
#main
color = !main_color
#sidebar
+float("right")
/* CSS : style.css */
#main {
color: #ce4dd6; }
#sidebar {
display: inline;
float: right; }