Bootstrap 3 and CSS / LESS ( Part 2 )

  • 0
In Part 1, we just set up the basic layout using CSS. Now, if we would like to replicate the same using LESS instead of the CSS, First go to the Bootstrap 3 and download the source code with the following option.








Once downloaded,unzip the folder and we need to concentrate on the "less" folder now. Copy and paste the folder itself into our current demo folder, and add a js folder and get the latest of the less js min file from here and include it inside the folder.


I tried the compiling using the WinLESS app, ( you can try on a compiler of your choice based on whether you are in Windows or MAC, or if you are using a paid one or a free compiler like the WinLESS ). To my surprise, the same got compiled. Might be, my Crunch and simpLESS needs to be updated (not sure if thats the reason) .




Click Add Folder > [ Navigate to folder ] > Choose only the bootstrap.less



 Once the compile is success, lets do the thing in a more "LESS" based structure and explore some of the positives that LESS offers to our workflow by taking advantage of the mixins, variables etc.

But before that, first we will make this thing up and running in LESS first, and then shift to the LESS workfow.Let us include the compiled bootstrap.less and our own my_styles.less at the top of the HTML inside the head tag. Include the less.js after bootstrap.less and my_styles.less
<!DOCTYPE HTML>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<title>BS3</title>
    
<!-- LESS FILES -->
<link rel="stylesheet/less" type="text/css" href="less/bootstrap.less" />
<link rel="stylesheet/less" type="text/css" href="less/my_styles.less" />
<script src="js/less-1.7.0.min.js" type="text/javascript"></script> 
      
</head>
<body>
    <div id="left" class="col-xs-3 col-md-6 col-lg-4">Left Portion</div>
    <div id="right" class="col-xs-9 col-md-6 col-lg-8">Right Portion</div>
</body>
</html>
And its LESS setup ( mystyles.less)
/* my_styles.less */

@left-sx-bg:#5F192C;
@left-md-bg:#28B78D;
@left-lg-bg:#E4D5A3;

@right-sx-bg:#6F8A79;
@right-md-bg:#243743;
@right-lg-bg:#C86368;

@white: #fff;
@black: #000;
#left{
     min-height:30px;
     text-align:center;
     font-weight:bold;
     color:@white;
     line-height: 30px;
     
     @media only screen and (min-width:320px){
        background-color:@left-sx-bg;
        color:@black;
     }
     @media only screen and (min-width:992px){
         background-color:@left-md-bg;
         color:@black;
     }
     @media only screen and (min-width:1200px){
         background-color:@left-lg-bg;
         color:@black;
     }
}

#right{
     min-height:30px;
     text-align:center;
     font-weight:bold;
     color:@white;
     line-height: 30px;
     
     @media only screen and (min-width:320px){
       background-color:@right-sx-bg;
     }
     @media only screen and (min-width:992px){
          background-color:@right-md-bg;     
     }
     @media only screen and (min-width:1200px){
         background-color:@right-lg-bg; 
     }
}
LESS offers a cool thing called "Variables" with which we can define the same once , and reuse the same variable in the stylesheets throughout, and in case we need to change the value, we just need to change the same in one place and the change gets reflected in all referenced places. When it comes to "theming" , this is a huge boon instead of "Ctrl + F", bulk replacing them individually, and the chances are, we might miss one or two if the stylesheet is huge. I could have used the variables provided by BS3 for breakpoints, but i just left it like that for demo simplicity ( and the fact that i a lazy ) . Try running the same and we get the exact same result as we obtained when ran using css. ( Refer part 1 )

Now that we got the setup up and running, lets remove the class dependency and decouple the HTML and css so that, all those col-xs-* and stuff comes from the css and our HTML remains nice and clean.

Before that, let us include the my_styles.less file in the same folder as the other less files, and instead of referring the bootstrap.less in the HTML, we just import the bootstrap.less in our my_styles.less and write our own styles inside. In the end, we just need to refer that my_styles.less in HTML. Just tweaking the HTML slightly from the previous ones

<!-- LESS FILES -->   
<link rel="stylesheet/less" type="text/css" href="less/my_styles.less" />
<script src="js/less-1.7.0.min.js" type="text/javascript"></script> 

<div class="wrap">
   <div class="left">Left Portion</div>
   <div class="right">Right Portion</div>
</div>

Here we have an outer container with the class name of "wrap" which holds the 2 divs.The main classes to look out for in less for grid and its nesting is .make-row() and.make-[]-column(*)where xs/sm/md/lg comes inside the square brackets depending on the device/resolution we are interested in. Rewriting the my_styles.less as shown below.

@import "bootstrap.less";
/* Variables & Colors */

@left-sx-bg:#5F192C;
@left-md-bg:#28B78D;
@left-lg-bg:#E4D5A3;

@right-sx-bg:#6F8A79;
@right-md-bg:#243743;
@right-lg-bg:#C86368;

@white: #fff;
@black: #000;

.wrap{
    .make-row();
    .left{ 
         
         min-height:30px;
         text-align:center;
         font-weight:bold;
         color:@white;
         line-height: 30px;
         background-color:@left-sx-bg;
         color:@black;
         
         .make-xs-column(6);
         .make-md-column(4);
         .make-lg-column(3);
         
        @media only screen and (min-width:320px){
            background-color:@left-sx-bg;
            color:@black;
        }
        @media only screen and (min-width:992px){
             background-color:@left-md-bg;
             color:@black;
        }
        @media only screen and (min-width:1200px){
         background-color:@left-lg-bg;
         color:@black;
        }


    }
    .right{
       
        min-height:30px;
        text-align:center;
        font-weight:bold;
        color:@white;
        line-height: 30px;
        background-color:@right-sx-bg;
        
       .make-xs-column(6);
       .make-md-column(8);
       .make-lg-column(9);
       
       @media only screen and (min-width:320px){
          background-color:@right-sx-bg;
       }
       @media only screen and (min-width:992px){
              background-color:@right-md-bg;     
       }
       @media only screen and (min-width:1200px){
             background-color:@right-lg-bg; 
       }
    }
        
}
Here, take a close look at how we are using the .make-row() inside the wrap class ( we put them at first itself ), and our corresponding .make-[]-column(*) files inside the respective classes, but used before the media query kicks in. Try taking the firefox firebug and we can confirm that the width is indeed applied from the css instead of placing them inside the HTML.


Here, we can see that our HTML is devoid of any bootstrap related classes, but less applies them behind the scene. Try resizing the browser, and we can see that, the  width becomes 33.3333% once it crosses the 991px and 25% once it is over 1199px.

PUSH/PULL/OFFSET

To see how offset works, try introducing the classes as shown below.

Here, Instead of the initial .make-xs-column(6) , we replace it with the two classes shown above, and we made the column, a 4 column layout, and applied an offset of 2 ( margin-left ) .

If we need to float the left div towards right,

Here though the left column spans 6 columns, the same is floated right using "pull-right()" mixin.

For push() example,

Here, i have omitted the right side div.

For the left and right portions floated right:

Here, though the right side spans 2 columns, its floated right.

Example of using pull(),


Here,the right side div spans 2 columns and its floated right with a margin-right that spans 2 columns.

INNER NESTING: 

There is an excellent article again from erik  here

Am sure that the first time readers ( including myself when i tried visualizing the new column concept first ) will have a bit of trouble grasping the trick behind it.

What is different in the grid layout pattern for BS3 with respect to BS2?

Let us build a Bootstrap 2 , two-row layout as below:

<!-- ROW1 -->
 <div class="row-fluid">
    <div class="span12 fixed_header">
     <div class="span6">
        <p class="paragraph2"></p>       
     </div>
     <div class="span6">
        <p class="paragraph2"></p>      
     </div>
    </div>
 </div>
 <!-- ROW1 -->
 
 <!-- ROW2 -->
 <div class="row-fluid">
    <div class="span12">
     <div class="span4">
       <p class="paragraph"></p>      
     </div>
     <div class="span4">
       <p class="paragraph"></p>      
     </div>
     <div class="span4">
       <p class="paragraph"></p>      
     </div>
    </div>
 </div>
 <!-- ROW2 -->

With the CSS:

body{
    background-color:#EDDDCB;
 }
 .fixed_header{
     background:url('bg.jpg') repeat-x top left;
 }
 .paragraph{
    width:100%;
    height:50px;
    background-color:#E8487F;
    margin:0px;
    border:1px solid #fff;
 }
 .paragraph2{
    width:100%;
    height:50px;    
    margin:0px;
    border:1px solid #fff;
 }
 .red{
    border:1px solid #000;
 }

Output:


And if we take a look at how the layout arrangement is done behind:

The fluid row's first child's margin-left is reset to zero and for the successive rows, there is a margin-left of 2.76243%. 

But the problem, as Erik points out in his blog, is that, if we resize to make the layout single column, see the padding getting applied for the body by Bootstrap2. The row-fluid starts after the 20px padding of the body, and so, if our background logo should stretch from end to end of the screen, then it will be a problem. We might need to manually reset the  padding to zero, but then, the content inside the main area also touches the screen edges , unless we specifically set an inner padding to the main container.


 On a Bootstrap 3, Let us create a row , and put two columns that spans 6 columns each, and split the second column again into 6.


The HTML for this :


<div class="fluid-container">
 <div class="wrap">
    <div class="left">       
    </div>
       <div class="right">     
    <div class="inner-fluid-container">
        <div class="inner-left"></div>
         <div class="inner-right"></div>
     </div>      
    </div> 
 </div>
</div>

 If we take a look at what is happening behind:


The fluid container class is having a 15px padding on either side so that the edges doesnt touch the viewport edges , thereby giving a breathing space for the contents inside.

When we apply a row ( class= "wrap" ), it applies a -15px margin on either side so that the row spans 100% of the viewport.

When we apply columns inside, each column has a 15px padding on either side. So, if we take 2 columns, it will have a 15px padding on left side, the gutter, in total spans 30px ( 15px padding-right of the first column and 15px  padding-left of the second column ) , and then, the 15px padding-right of the second column.

If we split the right side container again, for inner nesting, ( inner-fluid-container ), the same procedure continues just like we inserted a row (class="wrap" ), Ideally, the second column starts from the gray area ( just opposite to the dark brown area ), but because the row applies a  -15px margin on either side,  and the inner columns applying a padding 15px on either side, in effect, what we again have is a 15px gap on the left edge of the row, a 30px gutter ( 15px made by the negative margin and 15px made by the padding of the inner column ). If we put some contents into it, we can see how the layout spaces itself :


Here also, the 15px gap (made by the padding), followed by a 30px gutter gap(15px margin and 15px padding ), followed by a 15px gap ( padding ).

 Thats pretty much about nesting and the POC.

Whether or not to use this method or two stick with the classes mentioned in HTML itself, depends on individual requirements and comfort level. I personally like it more when the HMTL is more of the declarative styles, offers semantic meaning  (like the directives in AngularJS ) indicating the various classes there itself thereby becoming more self explanatory .  Its good to have a fair idea about who is who and what is what from the HTML itself rather than adding a CSS Preprocessor restriction along with its learning curve. For a person who doesnt know about pre-processors, it might be tough to get a grasp of what is happening as we have decoupled the styles and moved them inside the LESS.

I would definitely love to post another blog regarding Responsive Web Design, and after that, the "Mobile First" and its know hows. Myself is learning the same only and as and when i have the stuff with a quality hands on example, i will post the same here itself.

No comments:

Post a Comment