Dynamic Stylesheets: Working with CSS Prepro­cessors

A tool that is indispensable when writing stylesheets — preprocessors such as SASS and LESS offer web designers the ability to write CSS in a nested structure and work with variables to avoid the otherwise repetitive declarations. But that is by no means all.

The CSS Syntax

To explain the syntax and its advantages, let's first look at the "normal case", i.e. how a stylesheet is structured in a browser readable way.

If a nested HTML structure is to be formatted within an ID, you are forced to repeat the ID of the parent elements with each statement. Likewise, colors, margins, CSS animations, ... are declared in each and every spot [Fig. 1].

#main-navigation ul {
    list-style-type: none;
    padding: 1.5rem 0;
}

#main-navigation li {
    display: inline-block;
    margin-right: 1.5rem;
}

#main-navigation li a {
    padding: 4px 10px;
    color: #000;
    -moz-transition: color 0.3s ease-out;
    -ms-transition: color 0.3s ease-out;
    -o-transition: color 0.3s ease-out;
    -webkit-transition: color 0.3s ease-out;
    transition: color 0.3s ease-out;
}

#main-navigation li a:focus,
#main-navigation li a:active,
#main-navigation li a:hover, {
    color: #1e6df6;
}

Fig. 1: Simple, browser-readable CSS, example of a navigation structure

Why LESS is more

What immediately catches your attention is that the code is much leaner [Fig. 2].

With dynamic CSS (here using the LESS syntax) we can not only nest declarations, but also store recurring statements in variables.

But: don't misunderstand – after the code is compiled, the CSS looks just like in [Fig. 1] again.

#main-navigation ul {
    list-style-type: none;
    padding: 1.5rem 0;
        
    li {
        display: inline-block;
        margin-right: 1.5rem;
        
        a {
            padding: 4px 10px;
            color: @dark;
            
            .transition(color);
            
            &:focus, &:active, &:hover {
                color: @blue;
            }            
        }        
    }
}

Fig. 2: The same CSS, but in a much more friendly and readable way for the developer.

Technical Integration

The LESS syntax of course has to be converted – compiled – into regular CSS.

There are several ways to achieve this.

1. Desktop Tools

There are quite a few desktop tools for compliling LESS and SASS files.

Here you can find a selection of those: 10+ Best Tools and Resources to Compile & Manage SASS, LESS, and Stylus – CSS Preprocessors

2. Setup under Node.js

A more elegant way is to use the LESS compiler as a node module [Fig. 3]. Here, a simple terminal command as shown in [Fig. 4] compiles the .less file into regular CSS.

The Syntax is
lessc <input> <output>

The result is a CSS file.

npm install -g less

Fig. 3: Installation on Node.js

 

lessc styles.less styles.css

Fig. 4: Compiling a LESS file to regular CSS

The Watch Command

With the Node module less-watch-compile, which must be installed additionally, the compiling is triggered automatically when saving the LESS file.

We install the Node module less-watch-compile on app root level. The command in [Fig. 5] is based on the fact that we are inside a subfolder with the LESS file and we want to export the target file to the "css" subfolder.

We run this command in the LESS folder to avoid path problems with the @imports inside the LESS files.

npm install less-watch-compile
cd less
node ../node_modules/less-watch-compile --file styles.less -o ../css/styles.css
Watching styles.less
Detected change in '/Applications/XAMPP/xamppfiles/htdocs/my-app/less/screen.less'
Attemping to compile screen.less
Succesfully compiled in 510ms

Fig. 5: The Watch command for automatic compiling, every time the raw file changes

Webpack.js

If you are familiar with package managers, I can recommend Webpack. Here you can bundle your whole project - all your CSS as well as your Javscript into a single CSS/JS file.

Using the example in Fig. 6, the compilation here happens globally automatically when you save any JS or SASS file.

I know this looks quite complex at first, but once this is configured properly and all dependencies are installed, it's super convenient. Especially nice is that all the javascript is also minimized in a (here) app.js.

Just run the command npm run watch - and everything runs by itself.

For some time now I only work with this package manager.

You can find the documentation at https://webpack.js.org/

const webpack = require('webpack');
const path = require('path');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const FixStyleOnlyEntriesPlugin = require("webpack-fix-style-only-entries");

module.exports = {
    entry: {
      app: "./src/js/app.js",
      style: "./src/scss/style.scss",
    },
    output: {
    path: path.resolve(__dirname, 'js'),
    filename: "[name].js"
    },
    plugins: [
        new FixStyleOnlyEntriesPlugin(),
        
        new MiniCssExtractPlugin({
          filename: "../css/[name].css",
          chunkFilename: "../css/[id].css",
        }),
      ],
    module: {
      rules: [
        {
            test: /\.js$/,
            exclude: /(node_modules)/,
            use: "babel-loader?cacheDirectory=true"
        },
        {
          test: /\.s[ac]ss$/i,
            use: [
              MiniCssExtractPlugin.loader,
              "css-loader",
              "sass-loader"
            ],
        },
      ],
    },
    resolve: {
      extensions: [".js", ".scss"],
      modules: ["node_modules"],
      alias: {
        request$: "xhr"
      }
    },
    mode: 'production',
};

Fig. 6: Example of a Webpack config file for automatic bundling of SASS files and Javascript modules in one file each.

3. Client-side Compiling

The LESS compiler is also available as a JS script for client-side execution. I deliberately name this method last, because I can't get used to the idea of making the correct rendering of the page dependent on Javascript.

<link rel="stylesheet/less" type="text/css" href="styles.less" />
<script src="//cdn.jsdelivr.net/npm/less@3.13" ></script>

Fig. 7: Client-side compiling at runtime in browser

LESS Logo

Where does the story continue?

As soon as your dev environment is up and running, you can use global variables like color, font, but also complex format definitions with LESS.

You'll find a compehensive documentation on all Features here.

Comments to this post

Got beef?



More Blog Posts

Back to Top
Navigation ein-/ausblenden