Solvedangular cli Q: How to use bootstrap-sass with @extend and mixins

I tried to ask this on Stackoverflow, but did not get any response yet. My question:

I'm trying to use Twitter Bootstrap with Angular 2, SCSS and the scaffold generated by angular-cli

I want to apply the best practice to not litter my markup with Bootstrap-specific CSS classes. Instead I want to apply/use them via @extend or as mixins:

.mybutton {
   @extend .btn;
}

My problem:

  • The SASS compiler throws an error, because it does not know about .btn
  • If I add @import "bootstrap"; to my .scss-File, it will render the full Bootstrap-CSS in every component css

Any clues for me how this can be matched with the Angular 2 / Angular-CLI approach of handling styles?

What I've done so far

  1. add @import "bootstrap"; to my app.component.scss

  2. Apply ViewEncapsulation.None to the AppComponent, so Angular 2 does not apply Shadow DOM emulation and the Bootstrap CSS applies to the whole application

     @Component({
        encapsulation: ViewEncapsulation.None
     })
    
  3. Include the following block into angular-cli-build.js, so relative @import will work

    sassCompiler: {
      cacheExclude: [/\/_[^\/]+$/],
      includePaths: [ 'node_modules/bootstrap-sass/assets/stylesheets' ]
    },
    vendorNpmFiles: [
        ...
        'bootstrap-sass/assets/**/*'           
    ]
    
34 Answers

✔️Accepted Answer

@spongessuck There are two issues here, the simpler of these was the explicit imports, to which @zurie was referring :

If anything we need a global mixin file we can put variables and mixins that will be available to all components but not need reimporting over and over.

But yes, the more complicated is the issue of bloat. However, as I said initially, mixins do not contribute anything to css. And Bootstrap separates the mixins from rules. So, if you import:

@import '~bootstrap/scss/functions';
@import '~bootstrap/scss/variables';
@import '~bootstrap/scss/mixins';

instead of:

@import '~bootstrap/scss/bootstrap';

you will get no css generated (unless you actually use a mixin, and then you get what you used). I just tried it to confirm.
On the other hand, if you want to extend a rule, you have to import the file containing the rule, and that will, of course, pull in that rule (which we want) and any others (which we don't want). So, if you want encapsulation without bloat, prefer mixins. And maybe write your own if the the vendor doesn't provide one. I think. As I said, I'm still puzzling through this.

Other Answers:

The problem isn't importing bootstrap into an app; the problem is described by the OP:

If I add @import "bootstrap"; to my .scss-File, it will render the full Bootstrap-CSS in every component css.

This means if you don't want a new copy of bootstrap included with every component you need its variables/mixins for, you need to define bootstrap-dependent parts of your component styles in the global stylesheet.

Ideally, the bootstrap SCSS would be imported once globally, and then its variables/mixins would be available to any component without having to re-import the whole thing.

@spongessuck You nailed it. I always wondered what's so special about my wish to keep my code clean from Bootstrap classes that nobody else stumbles over it. Seems that most people are happy with directly using and assign Bootstrap. I would like rather to follow "Please stop embedding Bootstrap classes in your HTML!"

@Brocco why did you close this issue? It is a real problem that should be reopened and fixed.
Having an ugly work around that is not maintainable is not a solution.

Any news on this?

I would love to use the bootstrap mixins while using the CSS encapsulation and without having to import the same files over and over.

More Issues: