20

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

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/**/*'           
    ]
    

1 Answer 1

9
+50

The newest version of the angular-cli works with webpack, and it has no angular-cli-build.js, so you can dismiss that if you upgrade.

I would also not disable the view encapsulation. If you need global styles, add them to a global stylesheet. (angular-cli creates one in your src folder, normally its a css file, so create your app with the -style=scss flag or change it in your angular-cli.json).

So, if you have the newest cli version, you can just import the bootstrap-sass mixins. E.g in your app.component.scss:

// core
@import '~bootstrap-sass/assets/stylesheets/bootstrap/variables';
@import '~bootstrap-sass/assets/stylesheets/bootstrap/mixins';
// buttons
@import '~bootstrap-sass/assets/stylesheets/bootstrap/buttons';

The 'core' imports are needed for sass to be able to compile your bootstrap. You probably should move these to their own mixin.

If you also want to use glyphicons, you also have to set the $icon-font-path bootstrap variable relative to the used scss file it´s used in. (e.g. $icon-font-path: '../node_modules/bootstrap-sass/assets/fonts/bootstrap/';)

Sign up to request clarification or add additional context in comments.

4 Comments

The problem is that you will be able to use mixins only in the global scss file but not in the scss files of your components. See github.com/angular/angular-cli/issues/1261
You can use mixins in every scss file, but you have to add the needed references in each. It's like every component has its own "global" scss file, which is translated to CSS.
This doesn't address the original poster's need of not having the styles being injected into the page once per component. If he wants to use @extend on certain stuff (say buttons) in each one of X components in a page, then that css will be imported X times on the page with each one overwriting the other. This is a terrible solution, but seemingly can't be improved until angularCLI/Webpack makes a better solution
You´re right that it´s not an ideal solution. It is still the only working solution for the OPs question. What i also pointed out in my answer is the possibility to use global stylesheets, what you probably should do when using a monolith css library like bootstrap. Angular also lets you import mulitple stylesheets for a single component, so you can create e.g a button.scss stylesheet for all your components which use the buttons. Please don´t call this terrible when you can´t provide something better.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.