Hostingheaderbarlogoj
Join InMotion Hosting for $3.49/mo & get a year on Tuts+ FREE (worth $180). Start today.
Advertisement

Practical Tips For Using LESS

by
Gift

Want a free year on Tuts+ (worth $180)? Start an InMotion Hosting plan for $3.49/mo.

Not that long ago we had a look at The Basics of LESS and, while this is a solid reference for beginners, there is a lot more you can do with LESS! The goal of this tutorial is to expand on the knowledge from the previous article and give you some practical tips on how to utilize all the great things about LESS.

The concepts in the previous article will be essential to unserstanding this one. Variables, mixins, functions and the nesting in LESS should all be familiar and you should have at least some hands on knowledge of LESS.

Note: there's a fair amount of subjective advice in this article. Many things we'll be discussing have to do with methodology as opposed to rules and regulations of a language. I will show you how I organize files and create mixins, but there could be other, better, ways of doing things. If you think you use a better structure, or you have some tips and tricks of your own feel free to let loose in the comments.


File Organization

Organizing your files is always extremely important, very much so for LESS as well. I usually create a 'styles' folder in my main project directory where I store all the styles required for that project. So what happens if your project requires you to include css files from multiple locations?

The best way to make your life easy is to use a tool like Winless or CodeKit. These tools allow you to compile different files to different locations. This allows you to keep all your style files in one location while actually compiling them to different folders across your projects.

Codekit Project View

As you can see, in this WordPress project the highlighted 'style.less' file is contained inside the 'styles' folder. Since WordPress requires a 'style.css' file in the main directory we need to compile it there. CodeKit or a similar tool makes this easy since you only need to set it up once and then you can forget it until the end of the project.


External Libraries

Another issue which can arise with CSS files is how to handle third party files. Grid systems, styles for JavaScript sliders, resets and more require the use of (sometimes multiple) CSS files. There are usually two methods for making this happen. You either link the files to your webpage separately, or you place all the code inside one file and minimize it for performace purposes. With a LESS compiler tool this becomes easier again!

Using import rules you can pull all the files into your main LESS stylesheet. You can import less files as well, making their rules, mixins and other elements usable in all the subsequent files.

Importing files

Note: while this method is useful, it is not a universal solution. In some cases you may have to include all files separately, in others it might best to include everything inside one file.


Consistency

The biggest problem with CSS is the extreme lack of consistency in almost all projects. This situation stems mostly from the nature of the language itself, not necessarily from the ineptness of the programmer. CSS is a very loose and forgiving language meaning that it promotes configuration over convention, whereas the other way around would be preferable. Additionally CSS tends to be coded even more procedurally than usual, meaning that global patterns are not always noticed and implemented as simply as they could be.

While LESS is not a cureall, it does allow you to be much more consistent by giving you tools like functions and nesting. Let's take a look at a few examples where you can achieve better consistency with LESS tools.

.radius( @radius: 5px ) {
    -webkit-border-radius( @radius );
     -khtml-border-radius( @radius );
       -moz-border-radius( @radius );
        -ie-border-radius( @radius );
         -o-border-radius( @radius );
            border-radius( @radius );
}

Without LESS you would need to copy paste these rules whenever needed. Many people just write as they go so it is much more likely that you'd forget one of the prefixes, or write them in a different order. While these wouldn't be dealbreakers for your website each little inconsistency adds unnecesary noise to your code.

The nestable nature of rules also gives you a chance to add order to your code. I try and use as few divs and other container elements as possible and I try to target every element as specifically as I can

.commentlist {
    .comment {
        .comment-date {
            .comment-time {
                color: #888;
            }
        }
    }
}

This seems a bit redundant at first and I agree, in some sense it is. However, it makes everything super clear.

  • The location of each element can be determined at a glance
  • General rules for any element can still be specified outside of this structure
  • Overwriting styles is much more straightforward
  • Maintaining rules and finding errors is much easier

The usefulness of this will only be apparent if you use it in a larger project, but here is a quick snippet which shows how a comment is made responsive. Below a specific width the time portion of the comment date is hidden to save space.

Importing files
@media screen and ( max-width : 600px ) {
    .commentlist {
        .comment-container {
            .comment-main {
                .comment-header {
                    .comment-date {
                        .time {
                            display:none;
                        }
                    }
                }
            }
        }       
    }
}

I agree that this looks horrible. However, no thinking went into creating the rule. No thinking means easy backtracking because you don't need to figure out clever tricks you added along the way. Also, you can tell what this rule does just by looking at it.

My last argument for consistency is a more complex one, but I think is worthwile to look into. I build WordPress themes for sale on ThemeForest and one feature is that you can choose any color for your theme. Elements are recolored to your choice. The way this is done is that any time a 'primary color' is defined it is overwritten with dynamic CSS code we output with PHP. This looks something like this:

Contents of our LESS file:

@color-primary: red;
.button {
    background: @color-primary;
    padding: 8px 20px;
}

Contents of a PHP included at the end of the HTML header:

<?php
    $primary_color = get_option( 'primary_color' );
?>
<style type='text/css'>
.button {
    background: #<?php echo primary_color ?>;
}   
</style>

Basically, whenever there is a reference to '@color-primary' in the LESS file we need to create a PHP rule to make sure that colors chosen by the user are reflected on the site. This can take a while and more importantly is extremely boring. To battle the boredom we are creating a script which parses our LESS file and creates the PHP code which we can just copy-paste in one go. This is a bit diffcult because there are some dynamic rules with functions and whatnot, but in order to pull this off our LESS file must be well structured and consistent.


Creating Libraries of Rules

A great timesaver and a way to increase consistency across projects is to use a common library of rules. Previously I asked; why write out all the border radius rules when we can use a mixin? Now we can jump a level higher. Why rewrite the border radius mixin for each project when you can just use the same one?

There are some mixins (especially ones which tackle vendor-specifics ) which will be the same across all projects. These can be separated out into a 'mixins.less' file which you can use anywhere you like. Here are some examples of mixins which are always handy to have around.

Opacity

.opacity( @opacity: 0.8 ) {
    @ieopacity: @opacity * 100;
    filter: ~"alpha(opacity = @{ieopacity} )";
    
    -khtml-opacity: @opacity;
      -moz-opacity: @opacity;
           opacity: @opacity;
}

Gradients

.gradient( @start, @end ) {
    background: @start;
    filter: ~"progid:DXImageTransform.Microsoft.gradient( startColorstr='@start', endColorstr='@end',GradientType=0 )";
    background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,@start), color-stop(100%,@end)); 

    background: -webkit-linear-gradient(top,  @start 0%, @end 100%); 
    background:    -moz-linear-gradient(top,  @start 0%, @end 100%);
    background:     -ms-linear-gradient(top,  @start 0%, @end 100%); 
    background:      -o-linear-gradient(top,  @start 0%, @end 100%); 
    background:         linear-gradient(top,  @start 0%, @end 100%);    
}

Dynamic Coloring

.element-color( @color ) when ( lightness( @color ) >= 60% ) {
    color: @color - #888;
} 

.element-color( @color ) when ( lightness( @color ) < 60% ) {
    color: #fff;
}

This last one is especially cool. If the background color is light, the text color will be a very dark version of the same color.


Project-Specific Rules

I suggest always thinking about the placement of the rule you are writing. Are you sure it is globally used for all projects? It might be tempting to put a whole lot of rules in there, but in reality it could be better to create a project specific file as well.

Remember the image of the comment earlier? The container of that element has a specific format. It has a white border and a gray outline. Many other elements across this theme share this pattern. This could be created with a rule like so:

    .box {
        border:1px solid #fff;
        outline:1px solid #dedede;
    }   

    .comment {
        .box;
        background:#eeeeee;
    }

While this is used all over the place here, it won't be the same across multiple projects. Therefore it would be better to create a file like 'mytheme.less' which contains these widely used, but theme-specific rules. If you really want to use something like in the global file you could expand on it like this:

.box-bordered( @border-color: #fff, @outline-color: #dedede ) {
    border:1px solid @border-color;
    outline:1px solid @outline-color;   
}

This rule will allow you to create the same box style just as easily, but you can also add parameters to create differently colored box borders. You can take this one step further by abstracting things even more and creating a 'bootstrap.less' file; this brings us nicely into our next topic, creating a framework for ourselves.

Defined in our bootstrap file

@border-box-border-color: #fff;
@border-box-outline-color: #dedede;

In the cross-project 'mixins.less'

.box-bordered( @bc: @border-box-border-color, @oc: @border-box-outline-color ) {
    border:1px solid @bc;
    outline:1px solid @oc;  
}

Roll Your Own Framework

Creating your own framework is usually a no-no, unless you're very advanced in your main field (and 5-6 others ) and you have very good reason to. With CSS and LESS it is a bit different; you can start creating your own frame from day one. Since LESS is a superset of CSS anything you do fits neatly into existing code. Since CSS is forgiving and cascading you can't do any permanent damage that cannot be undone.

I suggest creating a main 'mixins' file to start with. You can always remove things from it or add to it as needed. Later you can add project specific files, third party files, a bootstrap file and so on. Here's how my framework is organized.

  • A bootstrap file is used to set up variables needed
  • The main framework file is included. This file imports various files:
    • The mixins file
    • Reset styles
    • Grid system
  • Project specific rules are included
  • Third party styles are added

Conclusion

As with any language, the practicalities of coding contain many different challenges and techniques which cannot be discovered and overcome by just looking at documentation. To use LESS to its full extent you should read suggestions and try and take in the logic, but ultimately you'll have to gain experience. Consistency, logic and simplicity should be your guiding words and LESS gives you all the tools to accomplish this.

Finally, I would welcome your input and I would enjoy hearing how you organize LESS and how you implement it into your projects. Thanks for reading!

Advertisement