T4CSS: A T4 Template for .Less CSS With Compression

asp.net, code 0 comments suggest edit

Good news! I have contributed my T4 template to the .less project. You can access it from the big download button on their homepage.

Pain is often a great motivator for invention, unless you become dull to the pain. I think CSS is one of those cases where there’s a lot of pain that we as web developers often take in stride.

Fortunately not everyone accepts that pain and efforts such as LESS are born. As the home page states:

LESS extends CSS with: variables, mixins, operations and nested rules.

Best of all, LESS uses existing CSS syntax. This means you can rename your current .css files .less and they’ll just work.

LESS solves a lot of the pain of duplication when writing CSS. Originally written as a Ruby gem, Christopher Owen, Erik van Brakel and Daniel Hoelbing ported a version to .NET not surprisingly called .less. Here are some examples from the .less homepage:

.Less implements LESS as an HttpHandler you add to your website mapped to the .less extension. I think this is a great approach when combined with the proper cache headers in the response.

However, sometimes I just want to have static CSS files. So I decided to write a T4 template for .less. Simply drop it in a folder that contains .less files and it will generate a .css file for each .less file.

Not only that, I also added a setting to then minimize the CSS using the YUI Compressor for .NET. This allows you to write your CSS using clear readable .LESS syntax, but deploy minified CSS. To turn off minification just edit the T4 file to change the value of the _minified variable.

Usage is very easy. The following screenshot shows a folder containing a .less file, one for each sample on the .LESS homepage. Notice that I don’t actually reference the YUI compression nor .LESS libraries. I just added them to a solution folder so you could see them (and so the T4 template can find them).

solution-without-t4

With this in place, I can simply drop my T4CSS.tt file into the Css directory and voila!

solution-with-t4

You can see the converted CSS files by expanding the T4CSS.tt node in the solution explorer as shown in the screenshot above.

In order to produce multiple output files, I used the approach that Damien Guard did in his post, Multiple outputs from T4 made easy – revisited. Basically I just embedded his T4 in mine.

You’ll notice there’s an extra file, T4CSS.log, that’s generated. Unfortunately using Damien’s approach, it’s not possible to suppress the default file generated by the T4 template, so I used that to log the operations.

Also note that at the time of this writing, there’s a bug in .LESS that causes one of the samples to throw an exception. I reported it to the developers so hopefully that gets fixed soon.

Lastly, there have been T4 changes in Visual Studio 2010. I didn’t try this template with VS10 yet. When importing the assemblies, you may need to either add them to the GAC or reference them with a full path. When I get some time I’ll play around with that to see how to get it to work.

I have contributed this T4 template to the .less project. You can access it from the big download button on their homepage.

Found a typo or error? Suggest an edit! If accepted, your contribution is listed automatically here.

Comments

avatar

27 responses

  1. Avatar for kelly
    kelly December 2nd, 2009

    hooooooooooooooorayyyyyyyyyyyy

  2. Avatar for Chris Owen
    Chris Owen December 2nd, 2009

    Hi Phil,
    Great work and I'm glad you're enjoying using .Less! We're still beta so there's a few kinks to iron out, but this is a great addition to the project and I'll surely be linking it from our site.
    Chris

  3. Avatar for Damien Guard
    Damien Guard December 2nd, 2009

    Nice tool but it's not my approach that prevents the default T4 output - it's the fact T4 is built on Visual Studio's singlefilegenerator :p
    [)amien

  4. Avatar for Craig Stuntz
    Craig Stuntz December 2nd, 2009

    That's excellent! Thanks!

  5. Avatar for Chris Owen
    Chris Owen December 2nd, 2009

    Its probably also worth noting that dotless.Core.dll has a minifier implementation in there so there's no real need for the yahoo YUI compressor.

  6. Avatar for Dan F
    Dan F December 2nd, 2009

    You rock Phil! This looks to be awesome. Except, I'm having trouble getting it going in my project. It doesn't seem to matter where I put the dotless.core.dll, I keep getting "Compiling transformation: Metadata file 'dotless.Core.dll' could not be found". I've included it in a solution folder like your screenshot above, and your sample solution doesn't give me the same problem, so I'm kinda out of ideas. Anybody got any tips for me?

  7. Avatar for Haacked
    Haacked December 2nd, 2009

    @Dan, copy the DLL into the root of your solution and *then* add it to the Solution folder. It can't just be anywhere on your drive. I think it has to be at the same level as the .sln file.
    The Solution Items folder is a "virtual" folder. It doesn't represent where the actual assembly is on disk.

  8. Avatar for Dan F
    Dan F December 2nd, 2009

    @Phil, Actually, I rescind part of my previous statement. I'm having the same problem with your sample project too. It didn't show up straight away when I opened the project, but when I right click the T4CSS.tt and choose run custom tool, it gives the same error as above. Which is jolly odd! I shall dig some more :-)

  9. Avatar for Dan F
    Dan F December 2nd, 2009

    Ah, Oleg has some handy words about understanding the assembly directive.
    If I put an absolute path in to dotless, or add a folder to the project reference paths, it goes OK. I haven't tried the GAC alternative.
    All's good again :-)

  10. Avatar for Morgan
    Morgan December 13th, 2009

    Nice! Thank you.
    If you want to keep CSS Syntax highlighting (and autoformatting) in VS for now (.less is planning a syntax highglight extension for VS), you can:
    -name original files .less.css
    -mod .tt line 34 to search for *.less.css
    -mod .tt line 266: return Path.GetFileNameWithoutExtension(dotLessFileName.Replace(".less","")) + ".css";

  11. Avatar for Arnis L.
    Arnis L. December 28th, 2009

    And I thought that I will be first that provides solution for syntax highlighting.
    At least i can add that it's a good idea to turn off css error detection in vs settings. :D

  12. Avatar for marius
    marius December 29th, 2009

    wow! less looks like fun...
    but, why oh why not crunch all css toghether an have just one file uploading in a single request;)
    hehe i like damiens manager class so much!
    althought oleg has some serious t4 templates too.

  13. Avatar for Wayne Brantley
    Wayne Brantley December 30th, 2009

    I have created a real less add-in, no template necessary, automatic running and combining!
    blog.waynebrantley.com/...

  14. Avatar for Mike
    Mike February 7th, 2010

    Hopefully one day this stuff will be as easy as:
    gem install less
    Right now, it's quite a lot of work to get these kind of cool add-ons/plugins/gems to work in a typical ASP.NET workflow.

  15. Avatar for Jon Canning
    Jon Canning April 21st, 2010

    $(SolutionDir) is your friend when importing assemblies

  16. Avatar for Francis
    Francis June 1st, 2010

    Watch chirpy (http://chirpy.codeplex.com/).
    Add-in for vs2010 and vs2008 generate on save .css file regular and minified.

  17. Avatar for Dirk Rombauts
    Dirk Rombauts September 29th, 2010

    Hi,


    Thanks for this excellent template. I've been busy "upgrading" my css files to less files.


    When I try to import a file however, I get a FileNotFoundException: could not find file - and then follows the path to the VS IDE, followed by the name of the file I try to import.


    Obviously, the template is looking in the wrong place for import files. Is there a fast way of fixing this? Thanks!


  18. Avatar for Hernan
    Hernan October 20th, 2010

    .css files with @import directive are not correctly parsed, since the imported files are being looked in a completely different directory. It should be looking for files relative to the file being parsed. Any solutions to this? Thanks!
    Hernan

  19. Avatar for Travis Illig
    Travis Illig October 25th, 2010

    FYI, as of about a week ago, the .less site changed domains from .com to .org.
    http://www.dotlesscss.org/

  20. Avatar for Alex Kwok
    Alex Kwok March 9th, 2011

    for those encountered FileNotFound exception for .less files with @import inside. You can add the following line
    System.IO.Directory.SetCurrentDirectory(currentDirectory);
    above "foreach(var cssFile in cssFiles) " around line 58 of T4CSS.tt to fix it.

  21. Avatar for Wil
    Wil October 12th, 2011

    Thanks Alex for the fix of FileNotFound exeption issue

  22. Avatar for Fabrizio
    Fabrizio October 19th, 2011

    Hello everyone, I can not understand why I get this error:
    "Compiling transformation: The name Less does not exist in current context"

  23. Avatar for Eric
    Eric January 23rd, 2012

    For VS 2010 compatibility, change the path to this dependency:
    <#@ assembly name="$(SolutionDir)..\..\Build\DotLess_1_2_2_0\dotless.Core.dll" #>
    And to prevent warning, remove the .Net 3.5 reference:
    <#@ template language="C#" debug="false" hostspecific="true"#>

  24. Avatar for Gregoire Daussin
    Gregoire Daussin January 30th, 2012

    For extend the Eric tips, (you save my day :), if you use Nuggets packages this path dependency should do the work
    <#@ assembly name="$(SolutionDir)packages\dotless.1.2.2.0\lib\dotless.Core.dll" #>

  25. Avatar for Ben Taylor
    Ben Taylor May 27th, 2012

    Hi Phil - your link at the top to dotlesscss is going to the .com, which is a spammy looking add site. The .org looks like the place to link to.

  26. Avatar for haacked
    haacked May 27th, 2012

    @Ben Thanks a lot! I had no idea. Fixed all the links.

  27. Avatar for cha
    cha December 8th, 2012

    Hi,
    I have some trouble making my t4css template work. It creates empty .css files, and had no errors inside the log...
    I don't know what I did wrong!!