Do more in CSS with LESS

Simplify the writing and maintenance of responsive design styles for modern web pages

Learn how to use LESS to write readable and maintainable Cascading Style Sheets (CSS) for modern websites. CSS makes the terrible old days of layout tricks with tables and invisible images a dim memory. But CSS is still unfriendly, and several initiatives tried to tame it for developers. One of the best is LESS, which extends CSS with dynamic behavior such as variables, mixins, operations, and functions. LESS is a CSS-like language that compiles seamlessly into CSS either on the client side or through server-side preprocessing.

Uche Ogbuji, Partner, Zepheira, LLC

Photo of Uche OgbujiUche Ogbuji is a partner at Zepheira, where he oversees creation of sophisticated web catalogues and other richly contextual databases. He has a long history of pioneering in advanced web technologies such as XML, Semantic Web, web services, and open source projects such as Akara, a platform for web data applications. He is a computer engineer and writer born in Nigeria, living and working near Boulder, Colorado, USA. You can find more about Mr. Ogbuji at his blog, Copia.



18 July 2013

Also available in Chinese Russian Japanese

CSS revolutionized the design of web pages, but CSS technology continues to be static and limited in its syntactical flourishes. These limitations are purposeful and make sense as a way to encourage broad implementation. But developers and designers often find it tedious to work with CSS. Many web frameworks include tools that make it easier to author CSS with more-flexible features and then compile the result to static CSS for deployment to a site. Some recent projects focus more narrowly on creating a language that's designed to be compiled into CSS. LESS, an open source project by Alexis Sellier, is one of the most popular in this genre.

LESS extends CSS basics with features that are familiar to developers, such as variables, mixins, operators, and functions. It's designed to compile into CSS either by using JavaScript in the browser, or through preprocessing with a server-side JavaScript toolkit. LESS is used in various other toolkits, including Twitter's popular Bootstrap project. In this article, I introduce LESS (version 1.4 in particular) as a means of writing readable and maintainable CSS for modern websites. See Download to get the article's sample code.

Getting started

Download the latest version of LESS (1.4 as of the time of writing; see Resources). Then, you're ready to learn its language. The World Wide Web Consortium (W3C) has some materials in its wiki for learning CSS. I largely follow that tutorial's sequence so that, if need be, you can learn basic CSS and LESS in tandem.

Listing 1 reproduces the W3C tutorial's first example:

Listing 1. Basic CSS example (listing1.css)
p {
  color: red;
  font-size: 12px;
  background-color: green;
}

The HTML in Listing 2 puts the CSS in Listing 1 to work:

Listing 2. HTML that refers to Listing 1's basic CSS example (listing2.html)
<head>
    <link rel="stylesheet" type="text/css" href="listing1.css">
</head>
<body>
    <p>This is a paragraph</p>
</body>

Figure 1 shows listing2.html displayed in the Safari browser on Mac OS X:

Figure 1. Browser output that uses the CSS in Listing 1
Screen capture from Safari of listing2.html. It renders as a line of body text that is in red type with a green background.

Removing the magic values

A developer who looks at Listing 1 is likely to notice immediately something that is against the programmer's instinct. The values are hardcoded into the CSS — a practice that is sometimes ridiculed as "magic values." One of the most important features in LESS is variables. Listing 3 is a LESS version of the basic example that uses variables:

Listing 3. Basic CSS example that uses variables in LESS (listing3.css)
@main-text-color: red;
@main-text-size: 12px;
@main-text-bg: green;

p {
  color: @main-text-color;
  font-size: @main-text-size;
  background-color: @main-text-bg;
}

Listing 3 isn't syntactically correct CSS, so you can't replace listing1.css in the HTML with listing3.less. You also must update the host HTML to invoke the JavaScript compiler, as in Listing 4:

Listing 4. HTML that refers to the LESS version of the basic CSS example (listing4.html)
<head>
    <link rel="stylesheet/less" type="text/css" href="listing3.less">
</head>
<body>
    <p>This is a paragraph</p>
    <script src="less.js" type="text/javascript"></script>
</body>

Notice that in Listing 4, I place the script tag at the end of the page body. Traditionally most developers put script tags in the head. But it's legal to put them in the body, which takes advantage of the fact that (to quote the HTML 4 spec) "script elements are evaluated in order as the document is loaded." Many sites these days have scripts near the end so that the main content loads without being delayed by any script processing.


Server-side compilation

Developing and deploying LESS for rapid browser consumption, which I've shown you so far, is convenient but comes with a cost. The JavaScript for compilation runs on users' browsers each time that the page loads, which uses up computing resources and slows page loading a bit. If I load Listing 4 in my browser and check the JavaScript console, I see the message: "less: css generated in 36ms." Thirty-six milliseconds isn't a long time, but it does represent additional unnecessary computing and time. Rapid page loading is important on the web.

After you move into production mode, switch to compiling LESS into CSS by using a server-side JavaScript tool. Node.js is a popular option and the one documented on the LESS site. I prefer to use the Mozilla stand-alone JavaScript project, Rhino. To use Rhino with LESS, download and install Rhino (see Resources). Put js.jar in a convenient location for your build setup. You need a special version of less.js, which you can find in the full download of LESS from GitHub (see Resources). For the version used in this article, it is less.js-master/dist/less-rhino-1.4.0.js. Place less-rhino-1.4.0.js where you saved the Rhino JAR. Now you're ready to compile LESS code into CSS.

To compile listing3.less, change to the directory where listing3.less resides and execute this command:

java -jar js.jar less-rhino-1.4.0.js listing3.less > listing3.css

Compilation places the generated CSS in the listing3.css file. That file's contents is:

p {
  color: #ff0000;
  font-size: 12px;
  background-color: #008000;
}

In listing3.css, the LESS variables are substituted, and color names are replaced by the RGB forms (such as #ff0000 for red). You can now deploy listing3.css to a server in the normal fashion.


LESS alternative comment syntax

One minor enhancement in LESS is a less cumbersome way to write single-line comments. Listing 5 shows an example of a standard comment from the W3C CSS tutorial:

Listing 5. CSS example that uses a comment (listing 5.css)
p {
  color: red;
  /* This is a comment */
  font-size: 12px;
}

The LESS code in Listing 6 is equivalent to Listing 5:

Listing 6. LESS equivalent to Listing 5 that uses a simplified comment (listing6.less)
p {
  color: red;
  // This is a comment
  font-size: 12px;
}

The syntax that Listing 6 uses is a common one for programmers and is a bit easier to type. But, because of the way LESS is processed, such comments don't appear in the generated CSS. If you want comments to be preserved for the browser viewer (for a copyright statement, for example), you must use the standard CSS comment syntax.

The rest of the W3C tutorial concentrates on details of CSS selector syntax and common properties. At this point, I shift focus to a broader use for LESS — one that most web developers are increasingly encountering in practice.


Creating responsive designs

In 2010 many web designers began advocating an approach to pages known as responsive design. From the beginning, you build web pages to be flexible when they're viewed in devices that range from small mobile handsets to displays that are even larger than the usual desktop computer form factor.

At the heart of responsive design are CSS3 media queries, a standard way to invoke CSS rules according to the nature and, especially, size of the user's display. LESS makes it easy to express CSS that uses media queries for responsive design. As a demonstration, I put together a LESS version of the excellent responsive design example by developerWorks blogger Bob Leah. In the article's code package (see Download), it is responsive.less.

Operators

One key technique in responsive.less is to use variables to set up the basic box sizes, and then to scale the box sizes down according to the size of the viewing area. I use LESS operators for scaling. For example, the snippet in Listing 7 uses the multiplication operator to scale the banner image:

Listing 7. Use of multiplication in LESS
#banner img {
  max-width: (@bannerwidth * @scale);
  max-height: (@mainheight * @scale);
}

In Listing 7, @bannerwidth and @mainheight are default values that get reduced by a @scale factor. The current LESS version requires you to enclose all expressions that contain operators in parentheses to avoid confusion in the syntax.

Nested rules

One of the most useful features of LESS is the ability to nest CSS rules. Nested rules help you to organize your code in an easy-to-follow way. In Listing 8 (a modified excerpt from responsive.less), I nest general CSS rules within media queries:

Listing 8. Use of nested rules in LESS
@media (min-width: 401px) and (max-width: 800px) {
  @scale: 0.75
  #banner { width: (@bannerwidth * @scale); }
  #banner img {
    max-width: (@bannerwidth * @scale);
    max-height: (@mainheight * @scale);
  }
  #main { width: (@mainwidth * @scale - @extrabuffer); }
  #main-content {
    width: (@maincontentwidth * @scale * 0.75 - @extrabuffer);
    float: left;
  }
}

The nested rules in Listing 8 are equivalent to the multiple, separate CSS rules in Listing 9:

Listing 9. Equivalent to Listing 8 without nested rules
@scale: 0.75

@media (min-width: 401px) and (max-width: 800px) and #banner {
   width: (@bannerwidth * @scale);
}

@media (min-width: 401px) and (max-width: 800px) and #banner img {
{
  max-width: (@bannerwidth * @scale);
  max-height: (@mainheight * @scale);
}

@media (min-width: 401px) and (max-width: 800px) and #main {
   width: (@mainwidth * @scale - @extrabuffer);
}

@media (min-width: 401px) and (max-width: 800px) and #main-content {
    width: (@maincontentwidth * @scale * 0.75 - @extrabuffer);
    float: left;
}

The version in Listing 9 doesn't provide a natural grouping of these closely related rules, and it also violates the DRY (don't repeat yourself) principle by specifying the media query over and over.

Mixins

Another way in which LESS reduces repetition is to enable you to specify a set of rules that can be added into other rules. In responsive.less, I use this mixin technique to express common rules across two separate media queries, as shown in Listing 10:

Listing 10. Use of mixins in LESS
.media-body (@scale: 0.75) {
  #banner { width: (@bannerwidth * @scale); }
  #banner img {
    max-width: (@bannerwidth * @scale);
    max-height: (@mainheight * @scale);
  }
  #main { width: (@mainwidth * @scale - @extrabuffer); }
  #main-content {
    width: (@maincontentwidth * @scale * 0.75 - @extrabuffer);
    float: left;
  }
  #widget-container {
    width: (@widgetoutwidth * @scale * 0.75 - @extrabuffer);
    float: right;
  }
  .widget-content {
    width: (@widgetinwidth * @scale * 0.75 - @extrabuffer);
  }
}

//Rules for viewing from 401px to 800px
@media (min-width: 401px) and (max-width: 800px) {
  .media-body;
}

//Rules for viewing smaller than 400px
@media (max-width: 400px)  {
  .media-body(0.3);
  //Extra manipulation of some rules
  #main-content { padding: 0px; }
  #widget-container { width: padding: 0px; }
  .widget-content { margin: 5px; }
  .widget-text { display: none; } 
}

Mixins can take parameters — such as the scaling factor for the box sizes in Listing 10. The default scaling factor is 0.75. Listing 10 uses this default in the section for viewing from 401px to 800px. For viewing at less than 400px, the scaling factor changes to 0.3, and some extra rules are added in that section.

Figure 2 shows the browser display of responsive.html, which uses responsive.less. I reduced the browser width to meet the media query for widths smaller than 400px so that you can see how the page might look on small mobile devices.

Figure 2. Low-width browser output of responsive.html
Screen capture of responsive.html in a Safari browser that is reduced in width to simulate the page's appearance on small mobile devices

In Safari on my Mac, the media query for widths that are smaller than 400px is triggered when the browser width is closer to 500px. This behavior brings up an important point. Media queries are based on the viewport concept. The viewport is the amount of viewable browser space, which is defined in CSS pixels and determined by the device and browser. CSS pixels can differ from device pixels; the relationship between pixel models changes, for example, if the user zooms the browser view (see Resources). Also, the viewport size that's set by the device and browser can differ from what appears as the actual window size. That's the case for Figure 2: The window is approximately 500px, but CSS processes it as a 400px-wide viewport. This phenomenon underscores the fact that responsive design requires sound, cross-device testing, as do all web development techniques.


Wrap-up

I am a software architect and developer but by no means a web designer. With LESS, I can take advantage of my programming skills to rapidly develop CSS that I have a better chance of understanding and maintaining. Variables and mixins allow me to make quick tweaks and see their effects without having to drift all over the CSS file to find what I need to make related changes.

Responsive design is well-known as a key technique in affordable and manageable mobile web design. It's also useful in design for accessibility and alternative presentation modes such as print. Because handling the multiple styles that are applied in response to media queries can get cumbersome, LESS's ability to simplify and organize CSS code is all the more valuable.


Download

DescriptionNameSize
LESS, CSS, and HTML code for this articleLessCssCode.zip120KB

Resources

Learn

Get products and technologies

Discuss

  • Get involved in the developerWorks community. Connect with other developerWorks users while you explore the developer-driven blogs, forums, groups, and wikis.

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Select information in your profile (name, country/region, and company) is displayed to the public and will accompany any content you post. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into Web development on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Web development, Open source
ArticleID=937570
ArticleTitle=Do more in CSS with LESS
publish-date=07182013