3

I'm creating a brand new Angular 2 project, utilizing the Angular CLI with Webpack. I can't quite seem to figure out how to create a global SCSS file that houses imports for mixins, variables, and specific tags.

Any time I try to target the <body> in any of SCSS files, those styles are nowhere to be found, when I inspect the element. I tried creating an app.css file and including that in the head of the index.html file, but then I run into the issues of not being able to import my mixins or variables, or anything of that sort.

Has anyone been able to create an app.scss file of some sort that all sub-components inherit global styles from, as well as have the ability to target the <body>?

Stevie Star
  • 2,331
  • 2
  • 28
  • 54
  • Possible duplicate of [Integrate Sass in Angular2 - webpack](http://stackoverflow.com/questions/39147082/integrate-sass-in-angular2-webpack) – Brocco Aug 25 '16 at 22:39

3 Answers3

3

There seems to be an error in the latest release of angular-cli with Webpack when it comes to applying global styles. Please refer to this Github issue.

Update: 31 August 2016 Upgrading to the latest version (1.0.0-beta.11-webpack.8) seems to have fixed the issue with angular-cli global styles. To set up global styles, follow the instructions here. The default is to use a global CSS file, if you wish to use a global SCSS stylesheet, you can specify the --style=scss flag when creating your app:

ng new scss-project --style=scss

angular-cli will generate a global style sheet styles.scss and include it in the angular-cli.json file. This indicates to angular-cli that styles declared in styles.scss should be global and applied to the entire application (and not scoped to a specific component). This is the equivalent of including a style sheet via a link statement in your index.html.

For existing projects, you can set the default style using:

ng set defaults.styleExt scss

In your angular-cli.json, extra global styles sheets or scripts can be added to the styles and scripts arrays shown below:

"apps": [
    {
      "root": "src",
      "outDir": "dist",
      "assets": "assets",
      "index": "index.html",
      "main": "main.ts",
      "test": "test.ts",
      "tsconfig": "tsconfig.json",
      "prefix": "app",
      "mobile": false,
      "styles": [
        "styles.scss"
      ],
      "scripts": [],
      "environments": {
        "source": "environments/environment.ts",
        "prod": "environments/environment.prod.ts",
        "dev": "environments/environment.dev.ts"
      }
    }
  ]

Why are styles not being applied to your body tag?

I'm guessing here because you haven't posted any code, but the reason your SCSS styles are not being applied to the <body> tag is because you are using Component Styles. When generating an angular-cli project with the --style=scss flag, it creates a root level component called app.compontent.ts:

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: 'app.component.html',
  styleUrls: ['app.component.scss']
})
export class AppComponent {
  title = 'app works!';
}

It also generates a Component Style called app.component.scss. This is an important point, because component styles are scoped to their component. A component style is set in the component like this:

styleUrls: ['app.component.scss']

Any styles you include in app.component.scss will only be applied to the app.component.ts and its corresponding template app.component.html (as well as its children). The reason the styles aren't applied to the <body> tag is because it lies outside of the root level component's scope in the index.html file generated by angular-cli:

  <body>
    <app-root>Loading...</app-root>
  </body>

I hope that answers your question.

Blake Mumford
  • 17,201
  • 12
  • 49
  • 67
  • Hey Blake, thankyou very much for the explanation, this actually makes a lot of sense. I ended up having to create a global app.css and include it in the index.html file, which is less than ideal, but it'll work for now. Again, thanks for the explanation :D – Stevie Star Aug 30 '16 at 15:47
  • No problem, the bug in angular-cli seems to be fixed in 1.0.0-beta.11-webpack.8. See my updated answer, in particular, follow the instructions in this link for including global SCSS styles: https://github.com/angular/angular-cli#global-styles. You should be able to avoid using a global app.css in your index.html file. – Blake Mumford Aug 31 '16 at 02:19
  • Awesome, thanks for the update! I've updated to 1.0.0-beta.11-webpack.8, but now when I try to run ng serve, I get an error (even after I updated angular-cli.json): `Cannot read property 'length' of undefined TypeError: Cannot read property 'length' of undefined at Object.getWebpackCommonConfig (/Applications/MAMP/htdocs/learnloop/node_modules/angular-cli/addon/ng2/models/webpack-build-common.ts:23:25)` I'm not quite sure what to do with this, as I believe I've done everything correctly – Stevie Star Sep 01 '16 at 17:59
  • but let's say you are using (global) variables.scss and mixins.scss inside of app.component.scss.... if you don't include them on top of the file, linter throws error, thinking the variables don't exist.... but if you include them on top of every component's scss, it would get included every time in the big css file.... how to avoid that? – DS_web_developer Dec 15 '16 at 10:18
0

You must import the file where the variable is from the component file:

@import "XX/XX/XX/_name.scss";

XX are the relative route to your file with variables

MWiesner
  • 8,868
  • 11
  • 36
  • 70
0

Maybe a bit late to the game. For us we have our custom webpack config and leverages the sass-resources-loader to expose the global mixins/variables to components.

{ test: /\.scss$/, loader: ["raw-loader", "sass-loader", { loader: 'sass-resources-loader', options: { resources: ['./styles/global/_common.scss', './styles/global/_mixins.scss', './styles/global/_grid.scss', 'node_modules/bootstrap/scss/_mixins.scss', 'node_modules/bootstrap/scss/_variables.scss'] }, } ] }

LeOn - Han Li
  • 9,388
  • 1
  • 65
  • 59