- Syntactically Awesome Style Sheets
- Written and maintained by Zurb, who also own the Foundation framework
- Sass is a pre-processor for CSS, which means you write code in Sass and let Sass manage your CSS for you.
- Adds the power of math, variables, logic and more
- There are 2 syntaxes available (.sass and .scss with Compass)
- Makes writing CSS even MORE fun than it already is!
To begin, we need to cd
into the directory where we want to work. Navigate to your development directory of choice and let's set things up there:
mkdir sass-practice
cd /sass-practice
There are many different ways to install Sass. In this cohort we've already learned a bit about Twitter's Bootstrap framework (Yes, Twitter owns Bootstrap...) and we haven't looked at Ruby yet, so we're going to use a tool called bower
to install. (Bower is a package manager that will help us install Sass with Bootstrap. We'll be using bower more in the coming weeks.)
Bootstrap maintains an open-source GitHub repository with instructions to create a bootstrap-sass
starter project in a few different development environments. You can read about it on Bootstrap's website, or visit the repo if you want, but all we have to do to get the code today is run this from the Terminal:
bower install bootstrap-sass
This will create a bower_components
directory with a bunch of contents in it, including jquery and bootstrap.
Now all we need is a webpage. Let's create an index.html
at the root level.
(This is basically the bootstrap-snippets HTML5 template, with a few important adjustments)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Title Page</title>
<!-- Custom CSS -->
<link href="bootstrap-sass/assets/stylesheets/app.css" rel="stylesheet">
</head>
<body>
<h1 class="text-center">Hello World</h1>
<!-- jQuery -->
<script src="jquery/dist/jquery.min.js"></script>
<!-- Bootstrap JavaScript -->
<script src="bootstrap-sass/assets/javascripts/bootstrap.min.js"></script>
</body>
</html>
This won't look like much yet if you open it in the browser.
Before we start coding, we need to create a custom Sass file and a CSS file for it to write to.
cd bower_components/bootstrap-sass/assets/stylesheets
touch stylesheets/app.scss
touch stylesheets/app.css
Making sure you're in the stylesheets
directory, we're ready to start Sass!
sass --watch app.scss:app.css
>>> Sass is watching for changes. Press Ctrl-C to stop.
Open the file app.scss
and add the following line of code:
@import "bootstrap";
If this runs with no errors you should now be able to see the Bootstrap CSS written out in app.css. Refresh your browser to confirm the font has changed and the text is now centered.
Great! Now let's get some more content so we can start playing with it.
Follow this link to Bootstrap's Jumbotron sample code and inspect source opt + cmd + U
Copy all the code beginning with <nav class="navbar navbar-inverse navbar-fixed-top">
and ending with </div> <!-- /container -->
--at the time this module was written, that would be lines 36 through 95-- and paste it into our index.html
file instead of <h1 class="text-center">Hello World</h1>
The following examples were taken from Zurb's own training classes, which I took a few years ago. Surely their lessons have evolved, but I've found the examples below to be useful both for learning and for setting up a cool development environment.
The following examples were written targeting Zurb's own framework, Foundation, which uses different class names, etc, etc. So as we walk through these examples one at a time, let's figure out how to take the information given and try to apply it to our own codebase. It's not about a right or wrong way of doing things-- it's about the struggle!
- Nesting
- Variables
- Mixins
- Functions
- @extend
- Math
- Color Functions
- @import
- Makes style sheets more readable
- No longer rewrite selectors over and over again
- Be careful not to over-nest
.class-name {
background-color: #eee;
h1 {
font-size: 1.4em;
color: #333;
a {
color: #02f;
text-decoration: underline;
}
}
}
.class-name {
background-color: #eee;
}
.class-name h1 {
font-size: 1.4em;
color: #333;
}
.class-name h1 a {
color: #02f;
text-decoration: underline;
}
.class-name {
> h2 {
line-height: 1.5em;
}
+ h4 {
padding: .5em;
}
* {
color: #01f;
}
}
.class-name > h2 {
line-height: 1.5em;
}
.class-name + h4 {
padding: .5em;
}
.class-name * {
color: #01f;
}
a {
color: #01f;
display: block;
&:hover {
color: #051;
}
.callout & {
color: #f00;
}
}
a {
color: #01f;
display: block;
}
a:hover {
color: #051;
}
.callout a {
color: #f00;
}
header {
margin: 24px;
@media only screen and (min-width: 768px) {
margin: 20px;
}
}
header {
margin: 24px;
}
@media only screen and (min-width: 768px) {
header {
margin: 20px;
}
}
- Make code easier to change because they reduce duplication
- Name things by their intent and be more semantic
- Simple examples seem to take more code, but they become more valuable with more code
/* Sass Variables syntax: */
$my-variable: value;
$main-color: #1d96bc;
a {
color: $main-color;
}
a {
color: #1d96bc;
}
$blue: #1d96bc;
$main-color: $blue;
h1 {
color: $main-color;
}
a {
color: #1d96bc;
}
$font-stack: "Helvetica Neue", Helvetica, Arial, sans-serif;
body {
font-family: $font-stack;
}
body {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}
$small: "only screen and (max-width: 768px)";
@media #{$small} {
a {
font-size: 16px;
}
}
@media only screen and (max-width: 768px) {
a {
fonx-size: 16px;
}
}
- The equivalent of Macros from other programming languages
- Generates code at compile
- Can use logic
/* Sass Mixin Syntax: */
@mixin mixin-name($option) {
/* ...css code... */
}
a {
@include mixin-name;
}
@mixin border-radius($radius) {
-webkit-border-radius: $radius;
-moz-border-radius: $radius;
-ms-border-radius: $radius;
border-radius: $radius;
}
.button {
background: black;
color: white;
padding: 10px 20px;
@include border-radius(5px);
}
.button {
background: black;
color: white;
padding: 10px 20px;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
-ms-border-radius: 5px;
border-radius: 5px;
}
@mixin btn($bg:#f00, $pad:10px) {
background: $bg;
padding: $pad;
font-size: $pad - 2px;
}
.button {
@include btn(#00f,20px);
}
.button {
background: #00f;
padding: 20px;
font-size: 18px;
}
@mixin btn($bg) {
$bg-lightness: lightness($bg);
background-color: $bg;
@if $bg-lightness > 70% { color: #333333; }
@else { color: #ffffff; }
}
.button {
@include btn(#0000ff);
}
.button-alt {
@include btn(#dddddd);
}
.button {
background-color: blue;
color: #ffffff;
}
.button-alt {
background-color: #dddddd;
color: #333333;
}
- Instead of outputting code, they output value
- Reusable logic
- Great for calculating things, like grid percentages
/* Sass Function Syntax */
@function name($num,$num2) {
@return $num + $num2
}
.my-module {
padding: name($num,$num2);
}
$em-base: 16px;
@function emCalc($px-width) {
@return $px-width / $em-base * 1em;
}
h1 {
font-size: emCalc(14px);
}
h1 {
font-size: .875em;
}
@function grid-calc($col,$total-col) {
@return percentage($col/$total-col);
}
@function gc($col,$total-col) {
@return grid-calc($col,$total-col);
}
.panel {
width:gc(3,12);
}
.panel {
width: 25%;
}
- A powerful means of class inheritance
- Reduces code bloat that mixins can create
- Uses the cascade instead of works around it
- They should do one thing, and do it well
/* @extend Syntax: */
%placeholder {
// Styles
}
.class { @extend %placeholder; }
.class2 {
@extend %placeholder;
// Unique styles
}
%clear-fix {
*zoom:1;
&:before, &:after {
content: " ";
display: table;
}
&:after { clear: both; }
}
.row {
@extend %clear-fix;
}
.hero {
@extend %clear-fix;
color: #f00;
}
.row, .hero {
*zoom:1;
}
.row:before, .row:after,
.hero:before, .hero:after {
content: " ";
display: table;
}
.row:after, .hero:after {
clear: both;
}
.hero {
color: #f00;
}
- Power and control over the value in your CSS
- Make relationships easier
- Use with the power of Variables and built-in functions
/* Sass Math Operators: */
1px + 1px /* 2px */
10em - 2em /* 8em */
6px * 4 /* 24px */
100 / 10 /* 10 */
18 % 5 /* 3 */
((10 * 2) / 5) + 4px /* 8px */
$page: 960px;
$main: 680px;
$gutter: 30px;
#sidebar {
width: $page - $main - $gutter;
}
#sidebar {
width: 250px;
}
percentage(13/25) /* 52% */
round(2.4) /* 2 */
ceil(2.2) /* 3 */
floor(2.6) /* 2 */
abs(-24) /* 24 */
p {
color: rgba(blue, .75);
}
body a {
color: rgba(#ffa, .25);
}
p {
color: rgba(0,51,255,0.75);
}
body a {
color: rgba(255,255,170,0.25);
}
- Separate stylesheets by type, components, etc.
- Keep CSS organized
- Compiles into a single stylesheet
Syntax for our .scss file:
@import “stylesheet”;
@import “stylesheet2”;
@import “stylesheet3”;
If we have the following file structure, where parts/
is a directory containing a number of partial stylesheets and app.scss
is a sibling to the parts/
directory...
parts/
_global.scss
_buttons.scss
_forms.scss
_grid.scss
_mobile.scss
_orbit.scss
_reveal.scss
_type.scss
_ui.scss
app.scss
...we would write the following in our app.scss
in order to pull in all our partial stylesheets:
/* app.scss */
@import "parts/global";
@import "parts/buttons";
@import "parts/forms";
@import "parts/grids";
@import "parts/mobile";
@import "parts/orbit";
@import "parts/reveal";
@import "parts/type";
@import "parts/ui";
In conclusion, Sass is a great tool to help manage your CSS and make it more dynamic and powerful. Although it is not a requirement of this class to learn Sass, I hope some of you love it as much as I do. At very least, you've got this documentation to develop one more tool in your kit.
All content is licensed under a CCBYNCSA 4.0 license. All software code is licensed under GNU GPLv3. For commercial use or alternative licensing, please contact legal@ga.co.