Skip to content

Can't access Sass Global Variables in components scss #3700

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
paramsingh88 opened this issue Dec 22, 2016 · 29 comments
Closed

Can't access Sass Global Variables in components scss #3700

paramsingh88 opened this issue Dec 22, 2016 · 29 comments

Comments

@paramsingh88
Copy link

I have a habit of importing my _variables.scss and _mixins.scss into my root src/style.scss file

@import 'styles/base/_variables.scss';
@import 'styles/base/_mixins.scss';
@import 'styles/helpers/flexbox.scss';
* {
    padding: 0;
    margin: 0;
}

body{
	padding: 4%;
	font-family: sans-serif;
}

But when I'm trying to access the variables in my components.scss, it's giving me an error
color: $primary-color;

Isn't there a way I can achieve this simply? Please Help.

@grizzm0
Copy link
Contributor

grizzm0 commented Dec 22, 2016

You need to include styles/base/_variables.scss in each and every file where you need to use variables. Same goes for mixins. The actual content of those files will not be included in the final build and wont impact the build size in any way.

@filipesilva
Copy link
Contributor

For now the solution is as @grizzm0 says.

Dupe-ish of #1791, work in progress in #2747.

@JustasKuizinas
Copy link

Seriously there is no better way for this?

@ciel
Copy link

ciel commented May 9, 2017

This is how SCSS has always worked. It really has nothing to do with the Angular CLI. The component's CSS is being compiled by itself - the other files aren't there. There's no reason for them to be there.

This is not only how it works, this is how you should WANT it to work. You don't want coupling with monolithic styles. You WANT each component to be a COMPONENT. They are isolated, encapsulated pieces of logic.

@rossanmol
Copy link

Add this to .angular-cli.sjon (change includePath to your path):

"stylePreprocessorOptions": {
        "includePaths": [
          "../node_modules/bootstrap/scss/"
        ]
      },

@dewwwald
Copy link

dewwwald commented Jun 12, 2017

@JustasKuizinas if you want you can:

  • Ditch SASS and use css vars.

  • write a service that create css variables in style element in the head.

  • Get variables for the head style service from a js config

  • reuse same ts config in your template / ts code

  • When building your project with webpack use pure css with autoprefixer
    or

  • use the same approach as mentioned above with no variables for color / sizes configured if you van the benifits of the pre processor

More on this here:
https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_variables

As mentioned above this is not an angular issue but more of a seed (project base that use angular) issue (with all the build processes and pre-processing pre-dictated by the author).

@AlexanderKozhevin
Copy link

Looks like we just need to duplicate in every component.

@import "~style/variables";

@grizzm0
Copy link
Contributor

grizzm0 commented Sep 26, 2017

@AlexanderKozhevin Exactly. Just like you need to import anything you use in typescript you also need to import anything you use in SCSS.

@dewwwald
Copy link

I can make another recommendation on this.

I am buzzy building a framework that will have no classes, only placeholders, mixins and variables. You can import this in the tag and write your sass as per usual but for the component.

My afore mentioned solution has some problems, for example css has not loops and ifs. Therefore it is better to just use sass.

You can then import base styles like import grid or responsive-grid in you app component (root component).

@GuskiS
Copy link

GuskiS commented Dec 19, 2017

Well, there is this loader that could resolve all our problems - https://github.com/shakacode/sass-resources-loader
I've been using it in one of the ejected projects, but will be nice if we could do this directly from CLI.

@jsonberry
Copy link

@GuskiS Yep, sass resources loader is great, but out of the box ng cli karma config will fail with it. SASS vars will not get picked up, but during a build and development it will work.

...Currently trying to figure out to get my tests to pass with it 🤔

@dewwwald
Copy link

@GuskiS that looks like the best option, combining that with importing sass modules using angular's styleUrls: [] has turned out to be my solution to the problem.

Again, as always, setup usually depends on your project.

@aoakeson
Copy link

My current solution is to turn off ViewEncapsulation for the component, but I dont like this at all. I wish there was a clean solution for this.

@component({
selector: 'app-admin',
templateUrl: './admin.component.html',
encapsulation: ViewEncapsulation.None,
styleUrls: ['./admin.component.scss']
})

@dewwwald
Copy link

@aoakeson, form my understanding, that is based on experience and not the actual algorithm, view encapsulation only applies when styling is applied to a class specific to that component. I haven't had to turn on viewEncapsulation for any of my component. The global stylesheets just seem to apply.

I am curious to know why this is different for you.

@aoakeson
Copy link

@dewwwald I think I figured out my problem. It turns out the elements that I was trying to access using these global variables were outside the scope of the main angular app. As my app is comprised of multiple modules, and apps it was not able to access these. I moved things around and am now able to have my components keep ViewEncapsulation on.

@LastDragon-ru
Copy link

LastDragon-ru commented Jun 28, 2018

@grizzm0:

You need to include styles/base/_variables.scss in each and every file where you need to use variables.

@AlexanderKozhevin

Looks like we just need to duplicate in every component.

You should never do this because #8431 :( Thus component.scss is totally unusable in real projects now...

@grizzm0
Copy link
Contributor

grizzm0 commented Jun 28, 2018

@LastDragon-ru As explained in that issue you should never import files that actually render CSS more than once. You can import files that contain variables and mixins as many times as you want as they do not affect the output.

@LastDragon-ru
Copy link

LastDragon-ru commented Jun 28, 2018

@grizzm0, For example with bootstrap sometimes more simply and better to use something like &.disabled {@extend .form-control:disabled;} or @extend .is-valid than redefine(copy) this styles. because after copying we will need to check it after each bootstrap update :( So this feature/issue can be useful.

@kkuzmina
Copy link

I prefer creating index.scss in the components folder (lets say you have a folder Search that lives under components). Then, import all the .scss files used in this folder into your newly created index.scss. Then, include @import "../components/Search/index"; in App.scss or wherever all your global partials are stored. Now all the .scss files inside components/Search will have access to global variables.

@yuriirud1
Copy link

@kkuzmina I know that it`s not right thing to do, but helped me as well 👍

@ManuelGraf
Copy link

This is how SCSS has always worked. It really has nothing to do with the Angular CLI. The component's CSS is being compiled by itself - the other files aren't there. There's no reason for them to be there.

This is not only how it works, this is how you should WANT it to work. You don't want coupling with monolithic styles. You WANT each component to be a COMPONENT. They are isolated, encapsulated pieces of logic.

how does importing a static path fit to that cool isolation idea of yours? I call BS. Duplication of declarations is what really sucks. Thats why there are things like tree-shaking and module systems. But its not like i can create style modules (singletons) in angular which I can inject somewhere.

@grizzm0
Copy link
Contributor

grizzm0 commented Feb 27, 2019

This is how SCSS has always worked. It really has nothing to do with the Angular CLI. The component's CSS is being compiled by itself - the other files aren't there. There's no reason for them to be there.
This is not only how it works, this is how you should WANT it to work. You don't want coupling with monolithic styles. You WANT each component to be a COMPONENT. They are isolated, encapsulated pieces of logic.

how does importing a static path fit to that cool isolation idea of yours? I call BS. Duplication of declarations is what really sucks. Thats why there are things like tree-shaking and module systems. But its not like i can create style modules (singletons) in angular which I can inject somewhere.

If you need to use a variable you need to import the file the variable is declared in. A variables file does not produce any output while imported and wont affect the build size.

For the variables to work application wide angular would have to include your global application SCSS in each component SCSS which would produce duplicated CSS.

If you import the variables file where you need it each component will have it's own "isolated" CSS while it actually "borrows" variables from a shared SCSS file. Just as you would do with a shared module in typescript/angular.

This way there's no need to declare the variable multiple times. But if you want to you could skip the import and redeclare the same variable over and over again, which seems a bit annoying to me.

@ManuelGraf
Copy link

Does that also hold for mixins and placeholders?
I actually had the same issue with Vue CLI and fxed it by using webpack loader oprions.

    loaderOptions: {
      sass: {
        data: `
          @import "@/assets/styles/vars.scss";
          @import "@/assets/styles/mixins.scss";
        `
      }
    }

I personally don't like scoped css (which Vue OFFERS and doesnt REQUIRE), I also don't really care that i have to import my mixins, vars, placeholders etc. I just want to be sure none of those will be printed (multiple times) in my final output.

@dewwwald
Copy link

@ManuelGraf only css classes, id's and statements get printed in the final result. Mixins are reuse-able statements that print nothing until they are used. Same holds for placeholders, mixins and scss vars.

@grizzm0
Copy link
Contributor

grizzm0 commented Feb 27, 2019

@ManuelGraf Variables nor mixins produces any output while imported. Comments in those files will (the last time I checked) however be printed multiple times. But the CLI should strip all comments when building anyhow.

@ManuelGraf
Copy link

Okay I am going to use it as proposed. But for some reason the ~/... doesnt work for me. What is ~ exactly in a multi-project angular 7 CLI environment?

@sandgupta23
Copy link

@ManuelGraf try this: @import ~src/variables in component.scss.

@dewwwald
Copy link

dewwwald commented Mar 8, 2019

This topic has been over explained, no one reads the thread before posting. Could we lock the topic?

@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Sep 9, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests