Brackets-SASS Plugin setup

  • 22
Brackets is a cool , superb and free IDE with a ton of useful plugins! One such is the Brackets SASS plugin.

On a personal laptop, its a straight forward stuff. Go to the Install extensions, search for Brackets SASS, Click install. But from a proxy, we will be forced to do the Manual Installation most times.
Once installed, we need Brackets to auto compile the required sass files and provide the css output at a folder we want.

Running SASS behind corporate proxy

NOTE: The steps mentioned below are for windows only. ( Tried from a Windows 7, 32 Bit PC )

Well, shit happens! and it happens quite a lot of times. 
 Node, SASS, gem, everything is awesome, but its just that these thing remain a showcase item inside a corporate proxy as 9 times out of 10, we wont be able to use it because of proxy restrictions.

Sass tools - Chapter 14

  • 0
If you are my kind (who hates command line for unknown reasons ),there are more tools available for sass. Check out this collection of tools for LESS & SASS.

Wrapping up with this 14 chapter blog collection for sass with the steps to compile sass from your command line.

Pre - requisites for command line sass
  1. Make sure you have admin rights. If you are behind a proxy, then your corporate office's proxy might block command line based installations.
  2.  Node JS
  3. Ruby installer
  4. Once you have the above two, you can install sass with the gem command.  
 
Checking the version to make sure that sass and ruby are installed.

Once that is ready, lets move to the root of the directory inside of which you have placed your project files, and type the following command.

Here we are asking sass to take the input from sass/app.scss and output them to css/app.scss.
Along with that, it has created the source maps as well.

And the last piece would be to ask sass to watch for changes.

Now every time we make a change in any of the partials, it auto compiles, creates the css and corresponding source maps!

Now there are other frameworks like Compass that does the compilation too. This is just one option among the various other cool stuffs!

TODO: ( future posts )
  1. Another blog post utilizing the features of Compass 
  2. A detailed analysis of SASS frameworks that includes Bourbon, Neat, Bitter, Refill!  
Thats it from the SassyVilla for the time being... :)
Cheers!





workspace - Chapter 13

Another hidden feature that is interesting is the ability to change the values in the browser and the same gets saved permanently in the stylesheets ( as long as the source is in your local system and not in a server ).

We need to create a workspace, and once that workspace is mapped to our folder, any change on our partials in the browser debugging will be saved back in the original partial stylesheets.


Select the "Enable CSS Source maps" along with the "Auto reload generated css" feature.
Once done, select the workspace tab on the left. Click "Add folder" & Navigate to the local path where your application folder exists and select them. Click Ok.


Once done, it will be asking for a confirmation. Click Allow.

Then go to the "Sources tab" , Select the app.scss which is the scss that is converted to css, Right click and select "Map to File system resource"..


And then it will pop up the name of the scss ( app.scss ) once more. Hit the Enter key.
Thats it!

Now go to your browser debugging, change the values there and see that the change is reflected in the browser as well as the latest is updated back in the scss partial.



Cool indeed! But wait..there is a problem. CHeck the app.css stylesheet and we can see that the css is updated with the new color "Goldenrod". But the scss stylesheet is still the old initial color.

To avoid this confusion, take the corresponding scss file in the Sources tab, and make the required changes.


Now, if we go back to the scss file, the same, as well as the compiled css will be in sync.


Source maps - Chapter 12

One silent , but very handy feature when it comes to debugging is the source mapping.
We write a pre-processing language- scss, but thats alien to browsers. It understands only css stylesheets. Our compiler converts the scss into css.

But what about debugging?
When we take our browser debugging tools, it points to our css file only right? But then with pre-processors, we are not touching css at all. So there is no point in knowing the line corresponding to css, but would have been awesome it pointed out to "this particular line in this partial." . That is what source maps does for us.

The command line based options, or a pre-processing complier, all provides the corresponding css source maps when the scss file is compiled. Usually both will be in the same folder, same name, but with a .map extension.


We get a css file, along with its map file when we compile the scss. ( Here, i have used the "Prepros" tool which compiled my scss to create the map as well as css stylesheet )

See the difference in the below figure.

With the source map, it pointed out the exact line number along with the corresponding partial name. (header.scss ) instead of the app.css which we see without sourcemap.





Highlighting codes

  • 0
This was done with : http://markup.su/highlighter/

.hero{
   width:100%;
   height:auto;
   overflow:hidden;   
   .banner{
      max-width:100%;   
   }
}
.main-section-wrapper{
    background-color:$white;
    padding: 10px 70px;
    padding-bottom: 30px;
}
.banner-description{    
    margin-bottom: 20px;        
     h2{
       @extend .caps-heading;
    }
    p{
       color:$black;
    }
}

Media Query and Retina Devices - Chapter 11

  • 0
I have kept the best for the last! And I must admit, the confusing one among the lot. Especially the part where we will be using media query along with mixins for conditional calls. To start with, SASS provides the ability to write nested media queries inside classes/ids.

/*Input scss nested media query*/

.header{
    min-height:50px;    
    
    @media only screen and (min-width:320px){
      background-color: red;
    }
    
    @media only screen and (min-width:768px){
      background-color: blue;
    }
    
    @media only screen and (min-width:1024px){
      background-color: green;
    }
}

/*And the same is outputted in css as:  */

.header {
  min-height: 50px;
}

@media only screen and (min-width: 320px) {
  .header {
    background-color: red;
  }
}

@media only screen and (min-width: 768px) {
  .header {
    background-color: blue;
  }
}

@media only screen and (min-width: 1024px) {
  .header {
    background-color: green;
  }
}

Here, we can see that, we were able to write the media query for required breakpoints inside the same element / class itself. So as and when we write, we exactly  know , where to make a change in case we need to tweak the style.  The sass compiler does the task of unwinding the queries and making them separate queries which comes one below the other in the css stylesheet.

C0oo000L  right !..

Hold on...more cool stuffs coming on..

Now, there are chances that there might be 20-30 partials, and each partial containing a ton of media query when we are planning to develop using this style. What if, we need to tweak the breakpoint slightly, say from 768px to 769px? We need to go to individual partials and change all the 768s to 769s, or based on the editor you are in , do a Replace all. Still, its messy.

We can set the breakpoint as a variable.
/* Variables.scss */
$mobile:320px;
$tablet: 768px;
$desktop: 1024px;

.header{
   min-height:50px;   
    
   @media only screen and (min-width:$mobile){
      background-color: red;
   }    
   @media only screen and (min-width:$tablet){
      background-color: blue;
   }    
   @media only screen and (min-width:$desktop){
      background-color: green;
   }
}

Now, if we need to change the breakpoint at a later point of time, we dont need to touch the other partials at all. The only place we need to change is the variable only and the new value gets reflected in all partials. Even better than previous ones right!

Lets explore more.

Some people like making everything short. If we look again, writing the same lengthy declaration of "@media only screen and (min-width: $mobile/$tablet/$desktop) " is boring right. Lets make that a variable too. And along with that, there is something called a "variable interpolation" technique with which we will put a placeholder for the breakpoint using " #{} " .
/* Variables.scss */

$mobile:320px;
$tablet: 768px;
$desktop: 1024px;

$mobile-mq: "only screen and (min-width: #{$mobile})";
$tablet-mq: "only screen and (min-width: #{$tablet})";
$desktop-mq: "only screen and (min-width: #{$desktop})";

.header{
    min-height:50px; 
    
    @media #{$mobile-mq}{
      background-color: red;
    }   
    @media #{$tablet-mq}{
      background-color: blue;
    }   
    @media #{$desktop-mq}{
      background-color: green;
    }
}
Now, the whole thing looks a bit more cleaner and sleek? And more importantly, maintainable ?

The breakpoint value, as well as the entire media query is now fully controlled from inside the variables.scss. So this becomes the only place where we need to make the query/breakpoint chnages for it to be reflected across the application.  Next time, if we need to make all the max-widths to max-device-widths, or min-width to min-device-width, we can do it with ease without polluting all the partials. A one line change is all that is needed ( along with a variable change if the breakpoint changes )

Now lets go for more! Lets introduce mixins along with media queries. This time, we will be writing a mixin which holds all 3 media queries and respond to each based on the viewport width! We will be introducing conditional logics into our scss stylesheet which was not possible on our normal css.

/* Variables.scss */

$mobile:320px;
$tablet: 768px;
$desktop: 1024px;

$mobile-mq: "only screen and (min-width: #{$mobile})";
$tablet-mq: "only screen and (min-width: #{$tablet})";
$desktop-mq: "only screen and (min-width: #{$desktop})";

/* Mixin that holds the queries */

@mixin change-header-color($device){
   @if $device == mobile{
       @media #{$mobile-mq}{
          background-color: red;
       }  
   }
    @else if $device == tablet{
        @media #{$tablet-mq}{
          background-color: blue;
       }  
   }
    @else if $device == desktop{
        @media #{$desktop-mq}{
          background-color: green;
       }  
   }   
}

/* Applying the mixin with the custom parameter passed */

.header{
    min-height:50px;
    
    @include change-header-color(mobile){
        background-color: red;
    }
    @include change-header-color(tablet){
        background-color: blue;
    }
    @include change-header-color(desktop){
        background-color: green;
    }    
}

The parameter passed ( Here, the string "mobile", "desktop" , "tablet" etc ) can be anything of your choice. Its just that it should match the "@if , @else if " clause in the mixin specified.

Thats quite a handful i guess! But yes, sass is powerful..and like Spiderman says, "With power, comes responsibilities.."!  So use it wisely.

Retina Devices: 
With apple being the pioneer of this whole "retina" revolution ( and along with that, stabbed a dagger into the ordinary developers chest :) .. lol.. already the poor webbie is smoking his head trying to figure out the right breakpoints, queries etc, and on top, another stuff that cannot be ignored.)  There are so much devices ( reference here at Viewport widths ) that needs to be considered, and when we commit on saying that "Our app or website is responsive, it pretty much mean that it should work in all these devices" ...( listed in the site is just a few in number..the tip of the iceberg...), it should work as we have promised.

The layout is something that will work thanks to the meta tag and its width=device-width that sets the width of the viewport to whichever device's viewport width or height. ( does it sounds confusing already? )

The simplest explanation is something like this. Consider a matrix of 1024 jugs. Each jug can contain a glass of water. To fill that we need 1024 glasses of water.  Now what if we increase the matrix to 2048 jugs? Can we fill the 2048 jugs with 1024 glasses of water? If we try to , then we need to pour half a glass on each jug instead of the full glass right? Thats more or less the retina stuff Vs the normal pixel stuff. [ Without peeping into a css pixel or a device pixel or its complications! ]. The problem is highlighted especially w.r.t images. When we say an image is 100px X 100px, its like saying 1024 jugs on a normal scenario, and if we take the same 100px X 100px in a retina scenario, ie the 2048 jugs, the image looks blurry. Why? Thats coz its half filled! Just like the half filled jugs which we mentioned previously.

To view the same image with same clarity, now we need a 200px X 200px image instead of a 100px X 100px.

We target the retina devices using device pixel ratio. To consider a device as retina, the value should be at-least greater than 1.5 whereas the normal device's value is 1.

In SASS, we can write a mixin to target retina devices. We can write a small example where, we have 2 images,  eg: facebook.png ( 30px X 30px ) and another image facebook-2x.png (60px X 60px ). The normal convention is to name the 2X image with an underscore or a hiphen along with the same name as that of the normal one.

We are going to write a parameterized mixin and along with the help of the ampersand operator, we will provide 1X image to normal devices and 2X images to those which is termed as retina.
@mixin retinize($file, $type, $width, $height) {
    background-image: url('../img/' + $file + '.' + $type);
    
    @media  (-webkit-min-device-pixel-ratio: 1.5),
            (min--moz-device-pixel-ratio: 1.5),
            (-o-min-device-pixel-ratio: 3/2),
            (min-device-pixel-ratio: 1.5),
            (min-resolution: 1.5dppx) {
    & {
          background-image: url('../img/' + $file + '-2x.' + $type);
          -webkit-background-size: $width $height;
          -moz-background-size: $width $height;
          background-size: $width $height;
      }
   }
}
Here, we have a mixin that accepts 4 parameters.
  1. The name of the file. ( whatever the name is )
  2. The  type of the file ( is it a png or jpg )
  3. Its dimensions ( width and height )
And the mixin says, on a normal flow, let the background image be that of a 1x image , and if that device is a retina, then overwrite the background image to that of a 2x image using &.
@mixin retinize($file, $type, $width, $height) {
    background-image: url('../img/' + $file + '.' + $type);
    
    @media  (-webkit-min-device-pixel-ratio: 1.5),
            (min--moz-device-pixel-ratio: 1.5),
            (-o-min-device-pixel-ratio: 3/2),
            (min-device-pixel-ratio: 1.5),
            (min-resolution: 1.5dppx) {
    & {
          background-image: url('../img/' + $file + '-2x.' + $type);
          -webkit-background-size: $width $height;
          -moz-background-size: $width $height;
          background-size: $width $height;
      }
   }
}

/* Applying the mixin with the custom parameter passed */

.header{
    min-height:50px;
    
    .logo{
         width:30px;
         height:30px;
         color:#fff;
         display:inline-block;
         @include retinize('facebook', 'png', 30px, 30px);
    } 
}

Here we said, we are calling the retinize mixin with the name of the image ( facebook ), the type ( png ) and its width and height ( 30px, 30px ).

Lets take a look at the output:

Here, on the left side, we can see on a normal desktop that it takes the 1x image (the black one ), and if we take a device that supports retina resolution, we can see that the 1x image is overridden (with a blue one ) . The background image url is changed in the Apple iPad browser simulator as shown in the right.





RWD bookmarklets - Chapter 10

SASS and RWD can be a deadly combo. And to help us explore more on the RWD side, there are free handly plugins and bookmarklets available. I will post more here as and when i encounter.

Bookmarks.

  1. RWD Bookmarklet ( drag and drop to the bookmark toolbar )
  2. Viewport resizer
  3. Media Query bookmarklet
  4. Breakpoint tester
  5. freebies
  6. responsive design checker
  7. Responsinator
  8. Browserstack
  9. Screenfly
  10. Studiopress
  11. Responsive typecast
  12. Screenqueries

Placeholders - Chapter 9

Apart from the mixin and extend, there is one thing called placeholders too.  They are represented using %. Unlike the mixin, placeholders are extended using "@extend" .  The difference being, mixin accepts parameters, whereas placeholders doesnt. The compiler will throw an error in that case. Like mixin, this will also be present in the output only if it used.

Like the extend, this will also group the common properties and isolate the unique properties separately in another class.
%btn {     
  font-family: Arial;
  color: #ffffff;
  font-size: 28px;
  padding: 10px 30px 10px 30px;
  text-decoration: none; 
  color: white; 
}
.one{
   @extend %btn;
   background-color:red;
}
.two{
   @extend %btn;
   background-color:gold;
}
.three{
   @extend %btn;
   background-color:aqua;
}

The HTML would be :



Here the css output will be:


What if we create a parameterized placeholder?

I deliberately added a parameter. The compiler throws error as we have discussed earlier.



Extend - Chapter 8

There is a subtle but important difference between using mixins and extends.

First, its usage. I remember it like this...
Import the mixin
Extend the class
When mixin only does the copy paste stuff, there by duplicating the same code time and again, extend does the grouping of common styles and wite them as one single class followed by the individual classes with respective unique properties.

.btn {     
  font-family: Arial;
  color: #ffffff;
  font-size: 28px;
  padding: 10px 30px 10px 30px;
  text-decoration: none; 
  color: white; 
}
.one{
   @extend .btn;
   background-color:red;
}
.two{
   @extend .btn;
   background-color:gold;
}
.three{
   @extend .btn;
   background-color:aqua;
}
.four{
   @extend .btn;
   background-color:blueviolet;
}
.five{
   @extend .btn;
   background-color:chocolate;
}

Here we created a normal css class called button and we are "@extend" ing it rather than "@include" ing.



And the css output will be:


Note that the repeating properties has been grouped and written as one single class. Only the background color has been written separately.

What if the same is done via a MIXIN?
Then the same properties will be repeated inside all classes .
@mixin btn {     
  font-family: Arial;
  color: #ffffff;
  font-size: 28px;
  padding: 10px 30px 10px 30px;
  text-decoration: none; 
  color: white; 
}
.one{
   @include btn;
   background-color:red;
}
.two{
   @include btn;
   background-color:gold;
}
.three{
   @include btn;
   background-color:aqua;
}
.four{
   @include btn;
   background-color:blueviolet;
}
.five{
   @include btn;
   background-color:chocolate;
}

The output will be :

See the difference? Getting it?

Multiple extends:
We can extend more than one classes at a time along with the "@extend" command.
.message {
  padding: .5em;
}
.important {
  font-weight: bold;
}
.message-error {
  @extend .message, .important;
}

We can chain extends:
.message {
  padding: .5em;
}
.message-important {
  @extend .message;
  font-weight: bold;
}
.message-error {
  @extend .message-important;
}

Its like B extends A, and C extends B.
So in-effect, C gets everything that A offers and B offers.

Note about Extend and Nested extending:

If we have a nested class ( instead of a plain class ) which we would like to extend, for the record, yes we can do it, but it is not at all recommended as the kind of css specificity that it would be unwinding will make it quite difficult to manage.

We can extend a class, but not a nested selector inside of it.
.header {
  h3 {
    color: red; 
  }
}

.special-header {
  /* Error: can't extend nested selectors */
  @extend .header h3;
}
A good read here.
Avoid sass extends? A different thought here.
Best Practices - Extend

Commenting - Chapter 7

Although sounds silly, there are people who takes these things seriously! Especially when your code is under a review. The first remark would be, "Remove unnecessary comments and make the style-sheets more concise"

No worries, we can have our SCSS commented heavily, but along with that , make sure that it doesnt get flown to the output css. In that way, we can have lots of info included for other developers which will come in quite handly in a huge projects, especially, if a particular developer has marked a fix for an issue and he has commented the  same clearly.
.btn {     
  font-family: Arial;
  color: #ffffff;
  font-size: 28px;
  padding: 10px 30px 10px 30px;
  text-decoration: none; 
  background-color: red;  
  
  /*This comment will be outputted in the css */
  body#green &{
    background-color: green;  
  }
  
  //This comment wont be outputted. 
  //This is internal to sass and so will be ignored while compiling
    
  body#blue &{
    background-color: blue;  
  }  
}
Any comments made inside the /* */ will be present in the output.
Any comments made using the // will get ignored in the css compiling.
Try giving both and see which one comes and which one doesnt if you would like to check them out in the final css stylesheet.






Conditional styles- Chapter 6

This will be quite handy when we are in a responsive web development project wherein, if we need to tweak the style based on devices, whether it is a tablet or a mobile, or show/hide certain components, we can make use of this.

Especially, if we are using, jQuery to attach certain classes or IDs dynamically, we can target them as well.

Eg: If the body has an ID called green, make the button green. ( may be for a mobile )
If the body has an ID called blue, make the button blue ( may be for a tablet )
Else, if no ids are attached, let that be default red button and gets applied for desktop.
.btn {     
  font-family: Arial;
  color: #ffffff;
  font-size: 28px;
  padding: 10px 30px 10px 30px;
  text-decoration: none; 
  background-color: red; 
  
  /*Conditionally target element styles */
  body#green &{
    background-color: green;  
  }
  body#blue &{
    background-color: blue;  
  }  
}

Here, we dont have any IDs for the body.

If we apply an ID, see how the rest of the conditions get applied accordingly.



Couple it with your responsive logic, and you will feel the power of SASS! Boy we can write quite a dynamic style-sheet with this! Just like the McDonalds, "Am loving it...!"

Next time, if you need to show or hide selected areas or components based on the device, try this! Its becoming more clear as and we write. "For this element, if the body has an id of this, lets show, else hide.".. We are dictating things on a more declarative manner and your sass helps you write such logics with ease.

Mixins - Chapter 5

  • 0
Let me remind you, you will be hearing this term "mix-ins" a 1000 times from now onwards, and another ten thousand times if you are in an actual sass implementation project.
Sounds like an alien term, but actually isnt.

Just like we create functions in javascript, and cut paste reuseable chunks of logics inside the function, and call it from some part of the code, Mixins also does a similar thing.
  /*Create a function*/
  function Calculate(){
    var a = 20;
    var b = 10;
    var sum = a + b;
    return sum;
  }
  /*Call a function*/
  var cost = Calculate();
  
  /*Functions that accepts parameters */
  function CalcumateSum(param1, param2){
    var total = parseInt(param1) + parseInt(param2);
    return total;
  }
  
  var newCost = CalcumateSum(10,20);

We can have parameterized functions. So does parameterized mixins.
The vendor prefixes, the box shadows, the border-radiuses, list-item-styles, bulleted lists, non-bulletted lists , clearfix, etc are perfect choices to be placed as mixins and called from various part of the application.

Lets go to css3 button generator and create  a button with a ton of features.
.btn {
  background: #3498db;
  background-image: -webkit-linear-gradient(top, #3498db, #2980b9);
  background-image: -moz-linear-gradient(top, #3498db, #2980b9);
  background-image: -ms-linear-gradient(top, #3498db, #2980b9);
  background-image: -o-linear-gradient(top, #3498db, #2980b9);
  background-image: linear-gradient(to bottom, #3498db, #2980b9);
  -webkit-border-radius: 28;
  -moz-border-radius: 28;
  border-radius: 28px;
  font-family: Arial;
  color: #ffffff;
  font-size: 28px;
  padding: 10px 30px 10px 30px;
  text-decoration: none;
}

.btn:hover {
  background: #3cb0fd;
  background-image: -webkit-linear-gradient(top, #3cb0fd, #3498db);
  background-image: -moz-linear-gradient(top, #3cb0fd, #3498db);
  background-image: -ms-linear-gradient(top, #3cb0fd, #3498db);
  background-image: -o-linear-gradient(top, #3cb0fd, #3498db);
  background-image: linear-gradient(to bottom, #3cb0fd, #3498db);
  text-decoration: none;
}
We can see that the class itself is a mix of a lot of properties, vendor prefixes etc.
This is a good example of introducing the mixins concepts to create something that can be reused.

One section is for the background gradient, the other for border radius, and the other for hover if we can split the class accordingly. rather than mixing them up like a spaghetti sauce, separate them so that we get more opportunity to reuse them.

We can visualize mixin more or like a "Ctrl + C " followed by "Ctrl + V". It just copy pastes some chunk of styles from one area to other. Thats it. So keep in mind that the code will be duplicated as many times as the mixin is called. What all styles written inside the mixin, will be

To create a mixin, all we need to do is use "@mixin" followed by the name of the mixin.



Here we have created three mixins.
In the sass section at left, we can see , At Line 5, 13, and 18, we have created three mixins.

To use a mixin, we should use the "@include" along with the name of the mixin.
At lines 27, 28, 35, we can see that the three mixins has been included in our scss styles.
Check out the compiled css styles in the middle section.

The problem with this is that, the mixin is only useful if and only if we need a blueish button having a linear gradient and  with 28px border-radius.  What if we need to tweak the color of the gradient a bit? What is we need a flat button, what of we need a different hover style altogether?

We need to keep coming back at the mixin and change them continuously, or copy paste and create more and more mixins. ( Both doesnt help the principle of DRY - Or "Do not Repeat Yourselves" ).
We are trying to optimize the scss styles to the maximum possible extend. So as far as we can, Write less, and reuse more.

If we take a closer look, the linear gradient style and its corresponding hover style are same, but just that it accepts two different set of parameters only right? So could we have reused it rather than duplicated the same?

We can have a 100 mixins, but only those which are used will be reflected in our final output css.
Thats good news! So no unnecessary bloating of styles. If we use it , it will be in the output css, else wont. As simple as that.

PARAMETRIC MIXINS
Just like function accepts parameters, as we have discussed before, mixins too can accept parameters
/*Parametric mixins */
@mixin linear-gradient($posn,$start,$stop) {
    background: $start;
    background-image: -webkit-linear-gradient($posn, $start, $stop);
    background-image: -moz-linear-gradient($posn, $start, $stop);
    background-image: -ms-linear-gradient($posn, $start, $stop);
    background-image: -o-linear-gradient($posn, $start, $stop);
    background-image: linear-gradient(to bottom, $start, $stop);     
}
@mixin border-radius($radius){
    -webkit-border-radius: $radius;
    -moz-border-radius: $radius;
    border-radius: $radius;     
}

.btn {
  
  @include linear-gradient(top, #3498db, #2980b9);
  @include border-radius(28px); 
  font-family: Arial;
  color: #ffffff;
  font-size: 28px;
  padding: 10px 30px 10px 30px;
  text-decoration: none;
  
  &:hover{
      @include linear-gradient(top, #3498db, #2980b9);
      text-decoration:none;
  }
}

Here, our mixins accepts parameters.
To pass in a parameter, just use the braces right after the mixin name and pass the required ones as needed, making sure that we prefix the parameters with $.
eg: @include border-radius(28px);

Similarly the gradient colors too and its position is passed in as an argument.

We can see that we have removed the hover specific mixin from the previous example and reused the linear-gradient mixin by passing different set of params for the hover class as well.

PARAMETRIC MIXIN WITH DEFAULT VALUES:

We can pass in default values in case if we like to just use the mixin name only and only pass in parameters if we need to alter a default set of values.
/*Parametric mixins with default values */
@mixin linear-gradient($posn:top,$start:#3498db,$stop:#2980b9) {
    background: $start;
    background-image: -webkit-linear-gradient($posn, $start, $stop);
    background-image: -moz-linear-gradient($posn, $start, $stop);
    background-image: -ms-linear-gradient($posn, $start, $stop);
    background-image: -o-linear-gradient($posn, $start, $stop);
    background-image: linear-gradient(to bottom, $start, $stop);     
}
@mixin border-radius($radius:28px){
    -webkit-border-radius: $radius;
    -moz-border-radius: $radius;
    border-radius: $radius;     
}

.btn {  
  @include linear-gradient; /*no params passed here*/
  @include border-radius; /*no params passed here*/
  font-family: Arial;
  color: #ffffff;
  font-size: 28px;
  padding: 10px 30px 10px 30px;
  text-decoration: none;  
  &:hover{
      @include linear-gradient(top, #3498db, #2980b9);
      text-decoration:none;
  }
}

The linear-gradient and border-radius mixin are called as such without the brackets. And the same mixin is called with custom parameters  for the hover.

Feel free to play around the same at the sassmeister code above and see instant changes.

So bottom-line:
  1. Mixins is more or less copy pasting the code .
  2. You have a mixin with 10 lines, and call it in 3 different classes, that makes 30 lines of css in your final css output.
  3. It doesnt help duplication or redundancy
  4. What we would ideally want is to group the styles so that common ones are written only once followed by the specific property separately in a different class. That is what "Extend" does, and will take a look at that soon.

Ampersand - Chapter 4

We can reference the parent selector using ampersand.
Hover the link and see that it gets a red background with white foreground color.

Here, check on the sass section, Line 27, how we have used the &:hover inside the 'a' tag. This is same as saying a:hover in our normal css. This is an easy way of attaching pseudo classes.

We will see some of the benefits of the ampersand in the next chapter when we discuss the responsive web based style changes when there will be requirements like, if the body contains an ID called this, then certain elements should have certain styles. Else not.


Nesting - Chapter 3

Next in comes nesting. Just like the HTML hierarchy being written one inside the other, we can nest classes one inside the other which was not possible with normal css. The task of unwinding the nested hierarchy and creating the suitable classes is taken up by the compiler. Below is a live playground. Drag and re-size the handles to check out the sass code, the HTML and the compiled css that it generates. Copy paste the same to your favorite text editor if you would like to see them more clearly as well.


The above embed is a live playground. Note the HTML and the scss. Both follow the same hierarchy.
Thats nesting for you! But beware of the nesting hell. Its not adviceable to nest more than 4 levels deeper as the specificity will becomes too much at one point of time.

In the sass section of the code, notice on Line 29, where we have again nested properties that share the same namespace, ie name. ( font-weight, font-size etc shares the namespace of "font")

The same is unwinded accordingly and check the middle column of css to see how the output is turned out. As far as possible, look for opportunities where in we can isolate a piece of code, convert to a mixin or placeholder and reuse them in the maximum places rather than writing 10 level deep nesting thereby making the css really scary and tangled. Always KISS :).. ( Keep It simple Silly! )






Variables - Chapter 2

Lets jump to the next feature - variables.
Just like we have variables in Javascript, we can use variables to hold colors, font sizes, margins, paddings, image urls, media query break-points, and what not, an entire media query itself.

A very handy site which we can use quickly to verify the css output corresponding to out .scss partials would be : Sassmeister.

In SASS, a variable is defined using a DOLLAR symbol.
  /* _home.scss */
  $main-body-color: #004c70;
  html{
    height:100%;
  }
  body{
    min-height:100%;
    background-color:$main-body-color;   
  }
  header{
    border:1px solid $main-body-color; 
  }

Here, we have created a variable, and the same variable is being used in multiple places so that a change in the variable will cascade the value at all places the same is referred. This becomes extremely handy when there is a theming requirement and all we need to do is update the variables with new set of color combos and boooom! we have a brand new look and feel of an existing site.

Few other usages includes:
 /* Variables*/
 $main-body-color: #004c70;
 $main-font-size: 16px;
 $container-gap:20px;
 $placeholder-url: "img/thumbnails/";
 $tablet-breakpoint: 768px;
 $mobile-breakpoint: 480px;
 $tablet-mq: "screen and (max-width: 980px)";
 $mobile-mq: "screen and (max-width: 480px)";

That concludes the variables section.


Partials-Chapter 1

Most people starts with variables, but for me , if there is one feature that i needs to pick, i will choose "Partials". Why? Because of the fact that the code becomes more clean, precise, modular, and maintainable. Just like the concepts of partial HTML in AngularJS wherein, we create a partial folder and cut paste chunks of code into individual HTML files without needing the head, body tag etc, and later include them via ng-include where angular behind the scenes use the Ajax call to get the partial at the specified area in the HTML , pretty much the same idea has been applied here as well.

In our normal approach, we keep on writing css in one single stylesheet. And for a normal project, the lines can range anywhere between 4000 - 10,000 lines of CSS.
So what if i have , say a:

  • Home page, 
  • landing page, 
  • contact us page, 
  • grid-view items page, 
  • list-view items page 
And we need to divide the work among our team mates , assuming 5 people are working in parallel.
We might come up with an approach where, we use a common reset.css or a normalize.css and then, assign each page to each person, where each page is created in a seperate css stylesheet and then cut-pasted into a single my-styles.css stylesheet ( risky, and chances of missing styles or overwriting the classes someone has written..not recommended ) or referring the individual stylesheets as an external stylesheet using link attribute. ( This too is not recommended as the best practices says, reduce the number of requests that a browser need to make inorder to render your HTML at the fastest possible time. Each css stylesheet means browser needs to send that much request to download the assets that it requires to render the page properly. But the advantage being, once downloaded, the same is cached and so next time onwards, the page loads faster as the file is being accessed from the browser cache. Best practice says, reduce the number of HTTP requests as much as possible. If there is 10 css files, 20 img files, 15 javascript files , then the browser has to send out 45 request in effect.   )

What if we could club the advantages only?

We could divide the stylesheets and keep it separately based on individual pages being created by individual developer , but in the end, import it all together so that the end result is a single css stylesheet ( which can be a collection of N number of sass partials.. May it be 10 or 100, it doesnt matter since the pre-processor doesnt care about the number, it takes the partials, combines it in the order specified and outputs one single css stylesheet.

The way we define a partial is by using the "underscore at the start" of the filename. The dot extension is optional as well. The underscore tells the compiler that this is a partial and so the compiler should not create a separate css, instead, this will be imported inside a main scss stylesheet (app.scss ) We can copy paste a normal css into an scss file and the same will still be fully valid.

So if we take our above example, then our folder structure will look like:



Here, inside the sass folder, we have an app.scss ( without the underscore ) and at the same level, we have a partials folder inside of which we hold a series of partials with an _{filename}.scss format.

The app.scss is the only file that will be compiled by the sass compiler and the corresponding app.css stylesheet will be generated dynamically inside the css folder. ( Provided the path is pointed correctly ). Its a good practice, only to use the app.scss as a container of partials where they are imported one after the other. We dont write any styles inside of it.

  /*app.scss*/
  @import "partials/reset";
  @import "partials/home";
  @import "partials/landing";
  @import "partials/contact-us";
  @import "partials/grid-view";
  @import "partials/list-view";

Now that we have the app.scss set up, we need a compiler that will compile the scss file and give us a css file with the same name.

If you are using a tool like Prepros, ( Paid, but awesome ! simply awesome, go for a 30 day trial and explore the features ) or Scout  ( free ), then feel free to sit back and relax. The headache of installing node, sass, ruby, gem and the horror & fear of using command line can be totally eliminated.

To make it simple, we will use the scout for demo, but will also include the command line steps which would come in handy as well ( Note that if you are inside a proxy of your company network, then Node.JS, ruby, gems, etc may not install correctly unless you by pass it using the correct port and userid / password combo. Just downlaod the scout which inturn contains the gem and ruby inbuilt  )


Here, lets point the right folders to the right inputs as shown above. Set the environment as "Development" since we are currently creating the css output for ourselves. If we need to generate a css aimed at production, then choose "Production"

The output style defines how the end css should look like.
The expanded will be our regular css style with one property per line.
The Nested will be pretty much the same, but the brackets alignment will be a bit different.
The Compact will be one css class per line with properties stacked one after the other( like float:left )
The Compressed will be the entire css in one single line ( This will be having the smallest size, ideal for production builds , but least readability )


Hit the Play button to the right of the project name and compiles the sass files and creates the corresponding css styles. Click the image below to see its enlarged version.



Note that the css is generated by the compiler. Not us.

To see the thing in action, lets write a bare minimum style in our _home.scss partial.
 
  /* _home.scss */
 html{
   height:100%;
 }
 body{
   min-height:100%;
   background-color:#004c70;   
 }


And the moment we click Ctrl + S, we can see that the Scout detected the change and auto-compiled  and logged in the same.



Lets refer the app.css ( and not the app.scss ) as an external stylesheet and run the same and see the output being reflected in the browser.



Note that the order in which the css will be created, is the same order which we imported the partials in the app.scss. That is, if we had written the normalize/reset styles, it will come first, followed by the home, landing, contact, grid-view and list-view styles .



The final app.css output will be as shown above.

The number of partial files can be hundreds. Its just that we need to import it as needed in the app.scss accordingly.

References:

  1. Optimize CSS delivery
  2. External stylesheets are slower