Angular - Shortcut to Importing Styles Files in Components

Jecelyn Yeen
👁️ 6,881 views
💬 comments

In a typical Angular project, you'll have many components. Each components has it own stylesheet (css, scss, less, etc). It's quite often that you might need to include global styling files (especially variables file) in your component.

We've talked on this a bit in our other Angular styles article: Using Sass with the Angular CLI

Let's explore another option for importing style files:

Table of Contents

    A Sass Variables Sample

    Let's say you have a _variables.scss in your src/stylings folder:

    // your folder structure
    - src
        - app
            - app.component.ts
                - hello
                    - hello.component.html
                    - hello.component.scss
                    - hello.component.ts
            - ...
        - stylings
            - _variables.scss
    // your _variables.scss file
    $brand-color: #800000;

    Reference to the Variables file

    Below is our hello.component.html file, let's style the header with our brand-color.

    <!-- hello.component.html -->
    <h1>
      Hello World!
    </h1>

    The $brand-color variable is in stylings/_variables.scss file. We need to import the file in order to use it:

    // hello.component.scss
    @import "../../../stylings/variables"; // this is not cool!
    
    h1 {
        color: $brand-color;
    }

    See the ../../../stylings/ syntax? Do you like it?

    Imagine you need to repeat this ../../../stylings/ in another tens or hundreds of components and you need to remember the relative path. This is not cool. Let's fix this!

    Shortcut with Angular CLI configuration

    If your project is generated with Angular CLI, you can add a configuration stylePreprocessorOptions > includePaths in .angular.cli.json file. This configuration allows you to add extra base paths that will be checked for imports. It tells Angular CLI to look for styling files in the mentioned paths before processing each component style file.

    For example, in our case, let's add ./stylings in the paths. Since the configuration accept an array, you can add multiple paths.

    {
        ...
        "apps": [{
            "root": "src",
            ...
            "stylePreprocessorOptions": {
                "includePaths": [
                  "./stylings"
                ]
            }
    
        }]
    }

    With this, we can update our hello.component.scss to just @import "variables". Sweet!

    // hello.component.scss
    @import "variables"; // change to just variables, say goodbye to ../../../stylings/
    
    h1 {
        color: $brand-color;
    }

    What if you have duplicated file name in paths?

    Imagine you included two styling paths in .angular.cli.json, both have _variables.scss file. Guess what will happen? Will the CLI pick up both files or throw errors?

    Let's test it out together!

    // your folder structure
    - src
        - ...
        - stylings
            - _variables.scss
        - stylings2 // add this
            - _variables.scss

    In stylings2/_variables.scss, you have the following styles,

    // stylings2/_variables.scss
    $brand-color: blue;
    $font-size-large: 40px;

    Update your .angular.cli.json configurations, to include styling2 folder path.

    {
        ...
        "apps": [{
            "root": "src",
            ...
            "stylePreprocessorOptions": {
                "includePaths": [
                  "./stylings",
                  "./stylings2"
                ]
            }
    
        }]
    }

    Update your hello.component.scss file,

    // hello.component.scss
    @import "variables";
    
    h1 {
        color: $brand-color;
        font-size: $font-size-large;
    }

    Restart your dev server. Wait for a while, and you should expect... Error! Error, Undefined variable

    Tell me why!

    Turn out, if there are multiple files with same name, Angular CLI will pick only the first file that match the name. In this case, it will pick the stylings/_variables.scss file. That's why it could not get the variable $font-size-large, because it's in styling2/_variables.scss file.

    But... I really need two files with the same name!

    Well, there are cases where you have multiple files with the same name and you really need it, and you would like to have shortcuts as well. The workaround would be including the parent path. For example, in our case, both stylings and stylings2 folders parent are src.

    We can update the .angular.cli.json configuration to the following:

    {
        ...
        "apps": [{
            "root": "src",
            ...
            "stylePreprocessorOptions": {
                "includePaths": [
                  "."
                ]
            }
    
        }]
    }

    Then, in your hello.component.scss, you can refer to both variables file like the following,

    // hello.component.scss
    @import "stylings/variables";
    @import "stylings2/variables"; 
    
    h1 {
        color: $brand-color;
        font-size: $font-size-large;
    }

    Well, it's not perfect, slightly more words to type, but better than ../../../ right? Also, it might be rare scenario that you have multiple style files with same name in the same project, I guess?

    Another shorter workaround would be including parent path and one styling path:

    {
        ...
        "apps": [{
            "root": "src",
            ...
            "stylePreprocessorOptions": {
                "includePaths": [
                  ".",
                  "./stylings"
                ]
            }
    
        }]
    }

    You can save a few lines in your hello.component.scss.

    // hello.component.scss
    @import "variables"; // shorter, don't need styling/ as it's one of the configured paths
    @import "stylings2/variables"; 
    
    h1 {
        color: $brand-color;
        font-size: $font-size-large;
    }

    What about including paths in node_modules?

    The Angular CLI configuration is applicable to files in node_modules as well. Let's say you are using your custom styling npm package, for example bootstrap-sass module.

    npm install bootstrap-sass --save

    Here is the folder structure of bootstrap-sass:

    - node_modules
        - bootstrap-sass
            - assets
                - stylesheets
                    - bootstrap
                        - ...
                        - _grid.scss
                        - _variables.scss

    Let's say you would like to use the bootstrap's _variables.scss, you can update your .angular.cli.json file to include bootstrap path,

    {
        ...
        "apps": [{
            "root": "src",
            ...
            "stylePreprocessorOptions": {
                "includePaths": [
                  ".",
                  "./stylings",
                  "../node_modules/bootstrap-sass/assets/stylesheets"
                ]
            }
    
        }]
    }

    Then, in your hello.component.scss, you can refer to the bootstrap variables file like the following,

    // hello.component.scss
    @import "variables";
    @import "stylings2/variables"; 
    @impoer "bootstrap/variables";
    
    h1 {
        color: $brand-color;
        font-size: $font-size-large;
        font-family: $font-family-serif;
    }

    Summary

    Let's remove the relative path hell (../../../) with this useful Angular CLI configuration!

    That's it. Happy coding!

    Jecelyn Yeen

    21 posts

    Coder. Diver. Board Game Lover.

    Speak English, Mandarin, JavaScript, Typescript, C# and more.

    GDE | Angular | Web Technologies.