Dynamic Stylesheets: Working with CSS Preprocessors



Category
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
Successfully 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
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.
Got beef?
Comments for this entry have not been activated.
Comments to this post