On Github likedaang / sass-compass
Follow this presentation erinwilbur.com/sass-compass
Githubs: github.com/likedaang/sass-compass
Old
New
It allows you to use variables, nested rules, mixins, inline imports, and more, all with a fully CSS-compatible syntax.
Sass keeps you organzied and gets you up and running quickly with the Compass style library.
Still looks like CSS3 - more typing
// .scss
table.hl {
margin: 2em 0;
td.ln {
text-align: right;
}
}
li {
font: {
family: serif;
weight: bold;
size: 1.2em;
}
}
less typing - more getting used to
// Sass
table.hl
margin: 2em 0
td.ln
text-align: right
li
font:
family: serif
weight: bold
size: 1.2em
Either syntax can import files written in the other. Files can be automatically converted from one syntax to the other using the sass-convert command line tool:
# Convert Sass to SCSS $ sass-convert style.sass style.scss # Convert SCSS to Sass $ sass-convert style.scss style.sass
Sass can be used in three ways:
as a command-line tool as a standalone Ruby module as a plugin for any Rack-enabled frameworkIf you are feeling adventurous check out tools for managing multiple ruby environments: rvm & rbenv
gem install sass
or
sudo gem install sass
(windows : may need to install Ruby first)
To run Sass from the command line, just use:
sass input.scss output.css
You can also tell Sass to watch the file and update the CSS every time the Sass file changes:
sass --watch input.scss:output.css
If you have a directory with many Sass files, you can also tell Sass to watch the entire directory:
sass --watch app/sass:public/stylesheets
Use sass --help for full documentation
Compass runs on any computer that has ruby installed.
gem update --system
gem install compass
For terminal newbies have a look a this.
Create your compass project:
compass create sass-demo
creates:
directory sass-demo/
directory sass-demo/sass/
directory sass-demo/stylesheets/
create sass-demo/config.rb
create sass-demo/sass/screen.scss
create sass-demo/sass/print.scss
create sass-demo/sass/ie.scss
create sass-demo/stylesheets/ie.css
create sass-demo/stylesheets/print.css
create sass-demo/stylesheets/screen.css
You must compile your sass stylesheets into CSS when they change. This can be done in one of the following ways:
To compile on demand:compass compile [path/to/project] To monitor your project for changes and automatically recompile:compass watch [path/to/project](Also remember to import your newly compiled css files in your html doc)
If this sort of thing frightens you...
Compass.app from Handlino.
Scout from Mutually Human.
Nesting
SCSS
nav {
ul {
margin: 0;
padding: 0;
list-style: none;
}
li { display: inline-block; }
a {
display: block;
padding: 6px 12px;
text-decoration: none;
}
}
CSS
nav ul {
margin: 0;
padding: 0;
list-style: none;
}
nav li {
display: inline-block;
}
nav a {
display: block;
padding: 6px 12px;
text-decoration: none;
}
Everyone is happy!
Proceed with caution - before you know it you could have yourself a CSS Selector Nightmare
Suppose someone gives you this lovely bit of HTML:
<div class="container">
<div class="content">
<div class="articles">
<div class="post">
<div class="title">
<h1><a href="#">Hello World</a>
</h1></div>
<div class="content">
<p></p>
<ul>
<li>...</li>
</ul>
</div>
<div class="author">
<a href="#" class="display"><img src="..."></a>
<h4><a href="#">...</a></h4>
<p>
<a href="#">...</a>
</p><ul>
<li>...</li>
</ul>
<p></p>
</div>
</div>
</div>
</div>
</div>
Hey! I'll totally use my cool nesting skillz!
body {
div.container {
div.content {
div.articles {
& > div.post {
div.title {
h1 {
a {
}
}
}
div.content {
p { ... }
ul {
li { ... }
}
}
div.author {
a.display {
img { ... }
}
h4 {
a { ... }
}
p {
a { ... }
}
ul {
li { ... }
}
}
}
}
}
}
}
oh......
body { ... }
body div.content div.container { ... }
body div.content div.container div.articles { ... }
body div.content div.container div.articles > div.post { ... }
body div.content div.container div.articles > div.post div.title { ... }
body div.content div.container div.articles > div.post div.title h1 { ... }
body div.content div.container div.articles > div.post div.title h1 a { ... }
body div.content div.container div.articles > div.post div.content { ... }
body div.content div.container div.articles > div.post div.content p { ... }
body div.content div.container div.articles > div.post div.content ul { ... }
body div.content div.container div.articles > div.post div.content ul li { ... }
body div.content div.container div.articles > div.post div.author { ... }
body div.content div.container div.articles > div.post div.author a.display { ... }
body div.content div.container div.articles > div.post div.author a.display img { ... }
body div.content div.container div.articles > div.post div.author h4 { ... }
body div.content div.container div.articles > div.post div.author h4 a { ... }
body div.content div.container div.articles > div.post div.author p { ... }
body div.content div.container div.articles > div.post div.author p a { ... }
body div.content div.container div.articles > div.post div.author ul { ... }
body div.content div.container div.articles > div.post div.author ul li { ... }
Don't go more than four levels deep.
Try to improve your understanding of the required CSS through contexts, objects and interaction states.
Context:
SCSS:
cart {
#sidebar { width: 150px; }
#content { width: 850px; }
}
CSS:
cart #sidebar {width:150px;}
cart #content {width:850px;}
Objects:
#sideabr #content #footer .blog-post .comment .widget .logo .user .button
Interaction:
a {
font-weight: bold;
text-decoration: none;
&:hover { text-decoration: underline; }
body.firefox & { font-weight: normal; }
}
SCSS
.content {
border: 1px solid #ccc;
padding: 20px;
h2 {
font-size: 3em;
margin: 20px 0;
}
p {
font-size: 1.5em;
margin: 15px 0;
}
}
CSS
.content {
border: 1px solid #ccc;
padding: 20px;
}
.content h2 {
font-size: 3em;
margin:20px 0;
}
.content p {
font-size: 1.5em;
margin:15px 0;
}
SCSS
.btn {
text: {
decoration: underline;
transform: lowercase;
}
}
CSS
.btn {
text-decoration: underline;
text-transform: lowercase;
}
References the parent selector
SCSS
.content {
padding: 20px;
.callout {
border-color: red;
}
&.callout {
border-color: green;
}
}
CSS
.content {
padding:20px;
}
.content .callout {
border-color:red;
}
.content.callout {
border-color: green;d
}
So, what if I wanted to style all my h3 headings a certain way, but for this one h3, that is also a child of a certain selector, I need it different
SCSS
h3 {
font-size: 20px;
margin-right: 10px;
.some-parent-selector & {
font-size: 24px;
margin-bottom:20px;
}
}
CSS
h3 {
font-size: 20px;
margin-bottom: 10px;
}
.some-parent-selector h3 {
font-size: 24px;
margin-bottom: 20px;
}
SCSS
$base: #999999;
.sidebar {
border: 1px solid $base;
p {
color: $base;
}
}
CSS
.sidebar {
border: 1px solid #999999;
}
.sidebar p {
color: #999999;
}
SCSS
// Colors // ------------------------- $emerald: #2ecc71; $carrot: #e67e22; $silver: #bdc3c7; // Typography // ------------------------- $font-base: "Lato", Helvetica, Arial, sans-serif; $font-demo: "Helvetica Neue", Helvetica, Arial, sans-serif; $font-monospace: Monaco, Menlo, Consolas, "Courier New", monospace; $font-size-base: 18px; $line-height-base: 1.72222; // 31/18 // Components // ------------------------- $border-radius-base: 4px; $border-radius-large: 6px; $border-radius-small: 3px; // Forms // ------------------------- $input-height-small: 35px; $input-height-base: 41px; $input-height-large: 45px; $input-height-huge: 53px; $input-border-radius: $border-radius-large; $rounded: false; $shadow: true; $authors: nick, dan, aimee, drew; $module-margin: 40px 0 20px 100px;
*Keep scope in mind: Variables are only available within the level of nested selectors where they’re defined
Don't Repeat Yourself: Use Mixins
CSS
.btn-a {
background: #777;
border: 1px solid #ccc;
font-size: 1em;
text-transform: uppercase;
}
.btn-b {
background: #ff0;
border: 1px solid #ccc;
font-size: 1em;
text-transform: uppercase;
}
SCSS
@mixin button {
border: 1px solid #ccc;
font-size: 1em;
text-transform: uppercase;
}
.btn-a {
@include button;
background: #777;
}
.btn-b {
@include button;
background: #ff0;
}
*Make sure your @include mixin comes before the @include
So we have our normal mixin and use it for h1 tags.
@mixin large-text {
font: {
family: Arial;
size: 20px;
weight: bold;
}
color: #ff0000;
}
h1 {
@include large-text;
margin-bottom: 0.5em;
}
Let's say you have a need to separate out typography and design elements - at times you need both:
@mixin compound {
@include highlighted-background;
@include header-text;
}
@mixin highlighted-background {
background-color: #fc0;
padding: 0.5em;
}
@mixin header-text { font-size: 20px; }
.main-content{
@include highlighted-background;
h1 {
@include header-text;
}
}
.sub-footer h1 {
@include compound;
}
Remember mixin recursion is forbidden: you may not include mixins within itself directly or indirectly
SCSS
@mixin wacky-border($color, $width: 1in) {
border: {
color: $color;
width: $width;
style: dashed;
}
}
p { @include wacky-border(blue); }
h1 { @include wacky-border(blue, 2in); }
CSS
p {
border-color: blue;
border-width: 1in;
border-style: dashed; }
h1 {
border-color: blue;
border-width: 2in;
border-style: dashed; }
*Make sure your optional args come last
It is possible to pass a block of styles to the mixin for placement within the styles included by the mixin. The styles will appear at the location of any @content directives found within the mixin. This makes is possible to define abstractions relating to the construction of selectors and directives.
SCSS
@mixin apply-to-ie6-only {
* html {
@content;
}
}
@include apply-to-ie6-only {
#logo {
background-image: url(/logo.gif);
}
}
CSS
* html #logo {
background-image: url(/logo.gif);
}
Method 1:
@mixin respond-to($media) {
@if $media == handhelds {
@media only screen and (max-width: 479px) { @content; }
}
@else if $media == wide-handhelds {
@media only screen and (min-width: 480px) and (max-width: 767px) { @content; }
}
@else if $media == tablets {
@media only screen and (min-width: 768px) and (max-width: 959px) { @content; }
}
}
#sidebar {
float: left;
width: 300px;
@include respond-to(handhelds) { float: none; }
@include respond-to(wide-handhelds) { float: none; }
@include respond-to(tablets) { width: 240px; }
}
Compiles out:
#sidebar {
float: left;
width: 300px;
}
@media only screen and (max-width: 479px) {
#sidebar {
float: none; }
}
@media only screen and (min-width: 480px) and (max-width: 767px) {
#sidebar {
float: none; }
}
@media only screen and (min-width: 768px) and (max-width: 959px) {
#sidebar {
width: 240px; }
}
// and for every instance inside a selector
#content {
width: 960px;
}
@media only screen and (max-width: 479px) {
#content {
width: 200px; }
}
@media only screen and (min-width: 480px) and (max-width: 767px) {
#content {
width: 300px; }
}
@media only screen and (min-width: 768px) and (max-width: 959px) {
#content {
width: 600px; }
}
Method 2:
@mixin bp($point) {
@if $point == papa-bear {
@media (max-width: 1600px) { @content; }
}
@else if $point == mama-bear {
@media (max-width: 1250px) { @content; }
}
@else if $point == baby-bear {
@media (max-width: 600px) { @content; }
}
}
@include bp(baby-bear) {
#sidebar {
width:100%;
}
}
@include bp(medium) {
#sidebar {
width:50%;
}
#content {width: 70%;}
}
Compiles out:
@media (max-width: 480px) {
#sidebar {
width: 100%;
}
}
@media (min-width: 800px) and (max-width: 1000px) {
#sidebar {
width: 50%;
}
#content {
width: 70%;
}
}
Mind sufficiently melted? Check out more:
SCSS
@mixin highlight($color, $side) {
border-#{side}-color: $color;
}
.btn-a {
@include highlight(#f00, right);
}
CSS
.btn-a {
border-right-color: #ff0;
}
*Make sure your optional args come last
<div class="error seriousError"> Dummy! </div>
CSS
.error {
border: 1px #f00;
background-color: #fdd;
}
.seriousError {
border-width: 3px;
}
CSS
.error {
border: 1px #f00;
background-color: #fdd;
}
.seriousError {
@extend .error;
border-width: 3px;
}
*Keep in mind if you are @extending a selector that has nested selectors, things could get ugly!
Always think: How can I make this more efficient?
SCSS
%btn {
background: #777;
border: 1px solid #ccc;
font-size: 1em;
text-transform: uppercase;
}
.btn-a {
@extend %btn;
}
.btn-b {
@extend %btn;
background: #ff0;
}
.sidebar .btn-a {
text-transform: lowercase;
}
CSS
.btn-a,
.btn-b {
background: #777;
border: 1px solid #ccc;
font-size: 1em;
text-transform: uppercase;
}
.btn-b {
background: #ff0;
}
.sidebar .btn-a {
text-transform: lowercase;
}
Sass control directives add a ton of power to scaling and reuse of your code.
SCSS
$authors: nick, aimee, dan, drew;
$colors: green, blue, red, yellow;
$author-style: zip($authors, $colors);
@each $a in $author-style {
.author-#{nth($a,1)} {
background: nth($a, 2);
}
}
CSS
.author-nick {
background: green;
}
.author-aimee {
background: blue;
}
.author-dan {
background: red;
}
.author-drew {
background: yellow;
}
...and finally
gem update --system gem install compass @import "compass"; // This goes at the top of your main.scss file
Imports
Non Imported Modules
Box-shadow
HTML
<div class="box-shadow-example"> <div id="box-shadow-default"></div> <div id="box-shadow-custom"></div> <div id="box-shadow-custom-multiple"></div> </div>
SCSS
@import "compass/css3";
.box-shadow-example div {
width: 40px;
height: 40px;
background: #eeeeee;
margin: 20px;
float: left; }
// Default single box shadow
#box-shadow-default {
@include single-box-shadow; }
// Box shadow with custom settings
#box-shadow-custom {
@include box-shadow(red 2px 2px 10px); }
#box-shadow-custom-multiple {
@include box-shadow(rgba(blue, 0.4) 0 0 25px, rgba(green, 0.2) 0 0 3px 1px inset); }
scale-lightness shortcuts the sass scale_color use:
SCSS
.content {
color: scale_color(#eee, $lightness: 7%);
}
with Compass
@import "compass"; // top of main.scss
.content {
color: scale-lightness(#eee, 7%); // or use a negative value to darken
}
There's also shade, saturation, tint...
Using opposite-position
SCSS
@mixin caret($point) {
$opposite: opposite-position($point);
border: 100px solid transparent;
border-#{$opposite}: 100px solid #000; // makes border-bottom
border-#{$point}: 0; // makes border-top
height:0;
width:0;
}
.arrow-up {
@include caret(top);
}
.arrow-over {
@include caret(right);
}
@function button-text($bg) {
@return contrast-color($bg, #333, #eee, 50%);
}
.btn-a {
background: #222;
color: button-text(#222); // outputs #eee
}
.btn-b {
background: #aaa;
color: button-text(#aaa) // outputs #333
}
@import "compass/layout";
.content {
height:400px;
position: relative;
width: 400px;
}
.sidebar {
background: #be9947;
@include stretch(5px, auto, 5px, 5px);
width:100px;
}
stylesheets/ | |-- modules/ # Common modules | |-- _all.scss # Include to get all modules | |-- _utility.scss # Module name | |-- _colors.scss # Etc... | ... | |-- partials/ # Partials | |-- _base.sass # imports for all mixins + global project variables | |-- _buttons.scss # buttons | |-- _figures.scss # figures | |-- _grids.scss # grids | |-- _typography.scss # typography | |-- _reset.scss # reset | ... | |-- vendor/ # CSS or Sass from other projects | |-- _colorpicker.scss | |-- _jquery.ui.core.scss | ... | `-- main.scss # primary Sass file
SCSS
@import "compass";
.logo {
background: image-url('jeffrey.png');
height: image-height('jeffrey.png');
width: image-width('jeffrey.png');
}
CSS
.logo {
background: url('/images/jeffrey.png');
height: 236px;
width: 236px;
}
* You can also use inline-image('img.png') to base64 embed images into CSS.
But I am a designer! This is all very complicate
Fully grasp organizing your CSS first:
Make them less painful
Any time you update a code block or change the 'experience':