Thursday, January 17, 2013

Using Less to Manage CSS Files


CSS is one of the hardest things to work with in web development. It seems like it should be fairly simple since it seems like you are doing simple stuff, but it is often very hard. One reason is that that layout is complex and there are many rules and often no clear ways of doing things. The other reason is flexibility combined with misuse. Rules apply everywhere and the structure of CSS tends to encourage lots of general global rules. Rules overlap and cascade and can often give unexpected results. It is hard to pin down all the places affected by rules so newer rules tend to always be more specific instead of having more limited rules be the specific ones.

There are a couple tools to help work with CSS and make it suck less. Two of the big ones are Less and Sass. You can use them together, but they have a lot of overlapping functionality. I am currently using Less and a .Net port of it called dotLess. If you work with CSS and you aren't using either Less or Sass then you should start using it immediately. Integrating dotLess into our project is very simple.

So I am not going to go into the syntax, but rather some of the management pieces. The first is that dotLess minifies your files. This means that it strips out unnecessary space and strips out comments. It also responds to the import statement differently. Normally the 'import' is handled on the client and essentially becomes another link element with another connection needed. Less does a much more sensible thing and simple includes the contents into the file and does so on the server.

These two things have impact on how you set up files. One is that you should only be loading a single Less file from your web page. Any other CSS/Less files will be included via imports from  his central file you are loading. Another impact is on files. In many cases people will jam all the CSS into one file since they don't want to incur the penalty of loading a lot of small CSS files. That goes away. You can now have small files with CSS and it will incur no penalty. Heavily commenting your CSS also becomes more attractive because they will be stripped out. Normally I am against excessive commenting, but with CSS I think commenting makes a lot of sense because properties may be added to support one browser or another or odd combinations of properties may be needed for an effect and this might not be obvious.


Migration to this method (some repetition with dotLess instructions):
  1. Use NuGet to install dotless (PM> Install-Package dotless)
NuGet will do load the files, add a needed reference, create some default configuration for itself in your web.config, and it will set up a handler so that your server can handle requests for "*.less" files the the dotLess codes that generates a css file.
  1. Create a Styles.Less file in your directory structure. Reference it like this <link rel="stylesheet" type="text/css" href="~/Content/dndvtt.less">
  1. Remove your CSS links. For each one, in order , do the following:
    1. Change the file name from X.css to X.less.
    1. Remove the link html of the code machinery to add that CSS link.
    1. Add an import statement like @import "X.less" to the bottom of the Styles.less file

Now you will be using Less and your site will perform a little better and your styles will be easier to manage.

Of course, you may have some issues. One is that you use the
<!--[if IE]> <link rel="stylesheet" type="text/css" href="all-ie-only.css" /> <![endif]--> syntax to load CSS for IE only. The way I normally handle this is to include the browser and the browser with major version as classes on the body. So the body would look like <body class="ie ie7"> then you can take your special class and wrap it with ie7 { … } and everything should work fine. I think this is actually a much cleaner and simpler way of doing things since it doesn't use a special syntax. Another problem might be that you have a file that is only used on certain pages. This can be solved the same way as above. Include some class on your body element and then wrap the file with some-class { … }.

One immediate complaint will be that the text coloring goes away because Visual Studio doesn't recognize Less files like it did Css files. To solve this problem I use a free add-in, Mindscape Web Workbench, that I found out about from Scott Hanselman's blog.

So one last thing I want to mention is some potential structuring ideas. I think the following makes a lot of sense:
/* you might use normalize */
@import "reset" 
/* a place to set truly global stuff like making all your fonts Comic Sans */
@import "siteWideDefaults" 
/* stuff like code for setting up common layouts like a three columns under a header */
@import "layoutStructures" 
/* a place to store common repeated UI patterns like a code section */
@import "commonTemplates" 
/* most code should start here and then migrate up to the more general areas */
@import "variousPageSpecificFiles" 

No comments:

Post a Comment