Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Load external CSS into component

Tags:

angular

import {Component} from 'angular2/core';  @Component({     selector: 'my-app',     template: '<div></div>',     styleUrls: [         'http://example.com/external.css',         'app/local.css'     ] }) export class AppComponent {} 

The external.css does not load.

Is there any way to load the external CSS in an Angular 2 Component?

like image 471
CallMeLaNN Avatar asked Dec 31 '15 06:12

CallMeLaNN


People also ask

How do I load an external CSS?

CSS can be added to HTML documents in 3 ways: Inline - by using the style attribute inside HTML elements. Internal - by using a <style> element in the <head> section. External - by using a <link> element to link to an external CSS file.

How do I import an external CSS file into angular components?

You can include css and js file in your angular project using npm command or direct insert link into src/index. html.

How do I import CSS into another CSS?

The @import rule allows you to import a style sheet into another style sheet. The @import rule must be at the top of the document (but after any @charset declaration). The @import rule also supports media queries, so you can allow the import to be media-dependent.

How do you add external CSS to lightning component?

You can add CSS to a lightning component bundle by clicking the STYLE button in the Developer Console sidebar. after click on the STYLE button on component bundle, new CSS file is create with . css ext.


2 Answers

See also https://angular.io/docs/ts/latest/guide/component-styles.html

View encapsulation

To allow external styles to affect the content of components you can change view encapsulation (that's what prevents styles to "bleed into" components).

@Component({     selector: 'some-component',     template: '<div></div>',     styleUrls: [         'http://example.com/external.css',         'app/local.css'     ],      encapsulation: ViewEncapsulation.None,  }) export class SomeComponent {} 

View encapsulation fulfills a purpose. The better way is to add styles directly to the component they should affect. ViewEncapsulation is set per component and may come handy in some situations.

"shadow piercing"

You can also use shadow piercing CSS combinator ::ng-deep (>>> and /deep/ are deprecated) to build selectors that cross component boundaries like

:host ::ng-deep .ng-invalid {   border-bottom: solid 3px red; } 
  • update ::slotted is now supported by all new browsers and can be used with `ViewEncapsulation.ShadowDom
    https://developer.mozilla.org/en-US/docs/Web/CSS/::slotted

which styles all tags with a class ng-invalid in the current component or any descendant with a red underline no matter if encapsulation is None or Emulated. It depends on browser support whether /deep/ works with Native (as far as I know this is not supported by any browser anymore).

Note

The shadow piercing CSS combinators are similar to the ones from the shadow DOM spec where they are deprecated since quite a while.

With the default ViewEncapsulation.Emulated Angulars own /deep/ and ::shadow implementation are used and they will work even when Chrome removes native support.

With ViewEncapsulation.Native Angular uses Chromes shadow DOM CSS combinators (only Chrome supported them at all anyway AFAIK). If Chrome finally removes them, then they won't work in Angular as well (again ViewEncapsulation.Native only).

Global styles

Styles added globally (index.html) don't consider component boundaries. Such styles are not rewritten by Angular2 and ViewEncapsulation.Emulated doesn't apply to them. Only if ViewEncapsulation.Native is set and the browser has native shadow DOM support, then global styles can't bleed in.

See also this related issue https://github.com/angular/angular/issues/5390

like image 137
Günter Zöchbauer Avatar answered Oct 02 '22 16:10

Günter Zöchbauer


First of all - The styles/styleUrls should only be used for any css rules that directly affect the style of the element from your template.

The reason your external.css doesn't get to applied to your component is because when you load these rules in external.css from styleUrls or styles, upon compiling, angular2 will append a unique component identifier like attribution selector to your original selectors.

For example, in your external.css, if there is a rule like div.container { /*some rules*/ }, it will become div.container[_ngcontent-cds-2] { /*some rules*/ }. So no matter how hard your try to force your rules become priority rules e.g. add !important tag, it is not going to work -- all selectors in your external.css have been restricted down one level to attribute selector, only the component element carries the same attribute. This is how angular2 restrict the styles to only current component.

Of course there is always a workaround.

Here is my solution -- I will add a external resource service, for all the js script, it will be using SystemJS to load either AMD or Globally, for all the css files, it will be using plain javascript to create a <link> element and append it to <head> element.

Here is a piece of my code for you consideration:

loadCSS(url) {    // Create link    let link = document.createElement('link');    link.href = url;    link.rel = 'stylesheet';    link.type = 'text/css';        let head = document.getElementsByTagName('head')[0];    let links = head.getElementsByTagName('link');    let style = head.getElementsByTagName('style')[0];        // Check if the same style sheet has been loaded already.    let isLoaded = false;      for (var i = 0; i < links.length; i++) {      var node = links[i];      if (node.href.indexOf(link.href) > -1) {        isLoaded = true;      }    }    if (isLoaded) return;    head.insertBefore(link, style);  }
like image 23
Downhillski Avatar answered Oct 02 '22 18:10

Downhillski