Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

@import styles in angular component's styles with ::ng-deep

Using Angular 5, angular-cli with scss.

I'm creating angular component that uses 3rd party component (angular-tree-component). I need to import styles for the tree. Because of styles isolation in angular (using the default emulated view encapsulation) the only way how to achieve it is using ::ng-deep, like this:

:host ::ng-deep {
    @import '~angular-tree-component/dist/angular-tree-component.css';
}

But this does not work - it looks like the @import is ignored inside the :host ::ng-deep. I workarounded it by copying the content of the css file directly within the brackets but its suboptimal as if the referenced package was upgraded then I would have to manually replace the content with the new styles.

Only other workaround I can think of is changing the view encapsulation to None but it seems even worse as it makes the styles global.

Is there any better option?

like image 452
eXavier Avatar asked Feb 15 '18 11:02

eXavier


People also ask

What is :: ng-deep in Angular?

The ::ng-deep pseudo-class selector So this style will be applied to all h2 elements inside app-root , but not outside of it as expected. This combination of selectors is useful for example for applying styles to elements that were passed to the template using ng-content , have a look at this post for more details.

What does host :: ng-deep do?

::ng-deep is quite powerful and has the capacity to render the styles defined under it as global. Its important to note here that ::ng-deep must be used after the :host selector to ensure that the styles defined will be scoped only to the <app-child-a> component and its descendant component <app-child-b> only.

What can we use instead of NG-deep?

Style encapsulation is one of many great Angular features. Style encapsulation ensures that component styles don't leak out and affect the rest of the page. Thx to style encapsulation; we can safely target a div without affecting other divs on the page.


1 Answers

For me, in an Angular CLI 6 project, all works fine when not including the file's suffix. Like if the actual file is simplemde.min.css:

:host ::ng-deep {
    // For proper scoping, do not include the .css file suffix here
    @import '~simplemde/dist/simplemde.min';
}

So, the above works without the need for encapsulation: ViewEncapsulation.None. And it also makes non-scoped content (typically HTML that is created at runtime outside of Angular, like in my case the HTML generated for the SimpleMDE Markdown editor) be styled as expected.

Some background:

With the suffix, the @import is actually processed as well; whenever my component was instantiated a scoped <style> element was added to <head>:

with file suffix

Note that this yields scoping for _ngcontent, and this does not work well for ::ng-deep, leaving dynamic child content unstyled.

However, without the suffix, one gets:

without file suffix

Above, the scoping is using _nghost.

I wonder if this is a bug, or documented behaviour. (And maybe things are even different for Sass files? Using @import for CSS is non-standard behaviour which will be removed in future versions of LibSass...)

Note that :host is needed. With just ::ng-deep the result with the file suffix is the same. But without the file suffix the styles are not scoped at all when not using :host:

without file suffix, without host

Looking at the rendered web pages I have very much been fooled into thinking this worked too (and one's own styles are still nicely scoped, so this is a partial success). But the third party CSS is effectively imported without any scoping when not using :host.

like image 137
Arjan Avatar answered Oct 08 '22 23:10

Arjan