dark mode

Organize CSS Preprocessors like Sass or Less in Angular Cli

Organize CSS Preprocessors like Sass or Less in Angular Cli

Angular 4 organizes its styles in a way that can make you fall in love again. Angular simulates encapsulation by default on every component, utilizing the power of attribute selectors. In short, adds a unique attribute on every angular component’s selector.

The problem

There is an issue that surfaces itself when I tried to use Sass variables and partials (the same problem will be and with Less, Stylus, etc.).

I love to have variables in separate files like colors, mixins and so on. But I found myself that can use them only if they are added globally or added separately to every component that I needed.

In the first case, we can import all partials in the global styles.sass file, but we might not want that, it goes against the encapsulation philosophy, and there is no autocomplete.

In the second case, adding every time needed @imports with the correct path was not practical, and honestly, it felt messy.

The struggle continues

I found the holy grail with node-sass and its automated way to add all @imports. But unfortunately, having the opportunity to set different options for Sass, Less, Stylus, etc. is not supported by Angular Cli as "it would be practically unmaintainable."

The solution

The solution is probably the best of both worlds. It’s almost practical, but maintainable by the Angular Cli guys.

The trick is to use stylePreprocessorOptions in the angular-cli.json.

First I’ve moved global styles.scss in a new folder called "style." There created partials like _colors.scss, _mixins.scss, etc. To import for example _colors.scss in some component, we need to open the component’s Sass file and add the following line: @import ‘colors’; As I said, it’s not the best solution, but it’s easy.

To add just that line, skipping the underscore, the path, and the extension, we need to set our stylePreprocessorOptions in angular-cli.json.

In my case:

"stylePreprocessorOptions": {
    "includePaths": [
        "../src/styles/"
    ]
}

If we want to include colors and mixins there will be two lines of code:

@import ‘colors’;
@import ‘mixins’;

To have autocompleted with VSCode we need to install an extension called SCSS IntelliSense.

Finally, we’ve ended with a way to use our variables and had "autocomplete."

Here is a newly generated angular-cli.json file with added Sass and stylePreprocessorOptions:

{
  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
  "project": {
    "name": "styles-are-fun"
  },
  "apps": [
    {
      "root": "src",
      "outDir": "dist",
      "assets": ["assets", "favicon.ico"],
      "index": "index.html",
      "main": "main.ts",
      "polyfills": "polyfills.ts",
      "test": "test.ts",
      "tsconfig": "tsconfig.app.json",
      "testTsconfig": "tsconfig.spec.json",
      "prefix": "app",
      "styles": ["styles.css"],
      "scripts": [],
      "environmentSource": "environments/environment.ts",
      "environments": {
        "dev": "environments/environment.ts",
        "prod": "environments/environment.prod.ts"
      },
      "stylePreprocessorOptions": {
        "includePaths": ["../src/styles/"]
      }
    }
  ],
  "e2e": {
    "protractor": {
      "config": "./protractor.conf.js"
    }
  },
  "lint": [
    {
      "project": "src/tsconfig.app.json"
    },
    {
      "project": "src/tsconfig.spec.json"
    },
    {
      "project": "e2e/tsconfig.e2e.json"
    }
  ],
  "test": {
    "karma": {
      "config": "./karma.conf.js"
    }
  },
  "defaults": {
    "styleExt": "scss",
    "component": {}
  }
}

Related articles

© 2021 All rights reserved.