Styles in component for D3.js do not show in angular 2
you can use
::ng-deep
.bar {
fill: red;
}
Here you can read perfect article explaining the approach.
And... information from the Angular documentation
Update
Angular and SASS agreed on supporting ::ng-deep
(instead of >>>
or /deep/
) a while ago until ::slotted
or whatever makes it into browser standards becomes available in all browsers.
ViewEncapsulation.Emulated (default)
That's by design. Angular adds class names unique to components and rewrites the added styles to only apply to the components where they were added.
D3 generates HTML dynamically without Angulars knowledge and Angular can't apply the classes to make the styles apply on the generated HTML.
If you add the styles at the entry point HTML file, Angular also doesn't rewrite the styles and the added helper classes don't take effect.
ViewEncapsulation.None
With encapsulation: ViewEncapsulation.None
Angular doesn't do this rewriting, therefore the result is similar to adding the HTML to the index.html
.
"Shadow-piercing"
Alternatively you can use the recently introduced shadow piercing CSS combinators >>>
, /deep/
and ::shadow
(::shadow
is just replaced by a
and thus very limited). See also https://stackoverflow.com/a/36225709/217408 and the Plunker
:host /deep/ div {
color: red;
}
SASS
/deep/
works fine with SASS but the alias >>>
doesn't.
The shadow-piersing CSS combinators are rewritten by Angular and they don't need to be supported by the browsers. Chrome supported them for a while but they are deprecated - but as said, that doesn't matter, because Angular rewrites them to use its encapsulation emulation.
ViewEncapsulation.Native
Angular doesn't support any way to style such components from the outside. Only if the browser provides support like CSS variables then these can be used.
View Encapsulation
This is because of the view encapsulation in Angular 2. By default, all the HTML and CSS is transformed so that it's only applied locally. In other words, if you add this style in your component's CSS:
h2 { color: red; }
It will only affect h2 elements inside the component, not every h2 element in your whole app. You can read more about this mechanisms in Angular documentation on View Encapsulation.
Why does it affect you?
Angular transforms your styles but since the C3 graph is not yet drawn, it can't transform HTML/SVG too. Because of that, component styles won't match elements inside of C3 graph.
What should I do?
External stylesheet
External stylesheets are not transformed by the View Encapsulation mechanisms, so effectively they will affect your C3 chart (and any other element for that matter).
If you're using Angular CLI, adding external stylesheet is really simple.
Edit your angular-cli.json
file and inside of apps
property find styles
array. Add another stylesheet here:
{
…
"apps": [
{
…
"styles": [
"styles.scss",
"c3.scss" // <---- add this or any other file
],
}
],
…
}
In case you're not using Angular CLI, there must be some way to add external stylesheets. Probably the simplest one is adding another <link …>
inside of <head>
in your index.html
file.
ViewEncapsulation.None
Your first option is: Create a component with the chart (and only chart) and turn off View Encapsulation inside of it. It's a good idea to do that also because of obeying the Single Responsibility Principle. Your chart, by design, should be encapsulated in a separate component. Turning of View Encapsulation is as simple as adding another property to your @Component
decorator:
@Component({
…
encapsulation: ViewEncapsulation.None
})
/deep/
CSS selector
If, for some reason, you don't want to do that, there's another possibility. You can try using /deep/
selector inside of your CSS which forces styles down into all child components views. Effectively, this breaks the encapsulation and should affect your C3 chart. So, for example, you can do that in your component's CSS file:
/deep/ .c3-chart-arc path {
stroke: white;
}
Either way, I recommend reading the aforementioned documentation on View Encapsulation in Angular 2 in order to understand why this happens and how it works. This feature is supposed to help you write code, not cause troubles :) This article might help you understand how it works: View Encapsulation on blog.thoughtram.io
ViewEncapsulation
will fix your problem.
import {Component,ViewEncapsulation} from 'angular2/core'
@Component({
selector: 'my-app',
encapsulation: ViewEncapsulation.None,
providers: [],
styles: [`
.bar {
fill: red;
}
`],
template: `
<div>
<svg class="chart"></svg>
</div>
`,
directives: []
})