Pablo Quemé
Pablo Quemé

Reputation: 1554

Styling child elements using global CSS in Angular 2

I'm starting to use Angular 2 and I am using an admin template from Themeforest for styling. I want my component to take the styles defined on the index.html, which should be global. The problem is that the elements inside a components html file are not finding these styles, and I think that it is because somehow the parent-child relationship is broken. Here's an example:

In the index.html file, I have the following:

...
<!-- This is my Component -->
<sidebar-menu></sidebar-menu>

<!-- This is coded directly on the index.html -->
<li class="m-t-30">
    <a href="#" class="detailed">
        <span class="title">Page 1</span>
        <span class="details">234 notifications</span>
    </a>
    <span class="icon-thumbnail "><i class="pg-mail"></i></span>
</li>
...

My <sidebar-menu> component has this on it's .html file:

<li class="m-t-30">
  <a href="#" class="detailed">
    <span class="title">Page 1</span>
    <span class="details">234 notifications</span>
  </a>
  <span class="icon-thumbnail "><i class="pg-mail"></i></span>
</li>

Which is exactly the same as what is present on the index.html file. So, I should see the two items displayed in the same way. But this is what I see:

enter image description here

Clearly, the styling is broken, even though that both the component's html and the element's html are the same. Using the inspector, I can see that the component's html is not using the same styling as the second element:

Component's inspected title: Component's inspected title

Second element's inspected title: enter image description here

I tried defining encapsulation: ViewEncapsulation.None on my Component, but it doesn't do anything. Any ideas on how to solve this? Thanks!

Upvotes: 2

Views: 1735

Answers (3)

Pablo Quem&#233;
Pablo Quem&#233;

Reputation: 1554

The way I managed to work around this limitation was to change the way my component's directive is called. Normally, you would define the selector like this:

@Component({
  moduleId: module.id,
  selector: 'sidebar-menu',
  ...
})

And call it using <sidebar-menu></sidebar-menu>. Instead, I defined the selector like this:

@Component({
  moduleId: module.id,
  selector: '[sidebar-menu]',
  ...
})

And call it as a directive inside a div, a li or any DOM element for that matter.

<ul class="menu-items" sidebar-menu></ul>

This way, I can still use the styling from my Themeforest template and use components. I figured that it broke because normally I would have something like this:

<div class="parent-class">
    <div class="child-class">
        ... styles applied to ".parent-class.child-class"
    </div>
</div>

And with components, I got something like this:

<div class="parent-class">
    <sidebar-menu>
        <div class="child-class">
            ... CSS can't find ".parent-class.child-class" anymore, as it has a sidebar-menu element in the middle!
        </div>
    </sidebar-menu>
</div>

With the workaround, you end up with this:

<div class="parent-class">
    <div class="child-class" sidebar-menu>
        ... CSS can still find ".parent-class.child-class", all good!
    </div>
</div>

Hopefully this will help someone. Thanks for your answers!

Upvotes: 0

Ben Richards
Ben Richards

Reputation: 3575

Just set the view encapulation to "none":

@Component({
    ....
    encapsulation: ViewEncapsulation.None
})

Upvotes: 0

muzurB
muzurB

Reputation: 317

I use the styles metadata to add all the css files I need for a given component. If you have access to the admin template css, you can reference it with a relative path to your component. An example:

@Component({
    selector: 'my-selector',
    template: require('./my-template.html'),
    styles: [
        require('./my-style.css'),
        require('../some-other-folder/some-other-style.css')
    ]
})

Due to view encapsulation being Emulated by default, other styles to do not bleed into your component this way and you have to explicitly declare the css files you want to be included for this component.

FYI, another way to have a style exposed globally is by adding :host >>> to the beginning of the style that's in the external css file. Example:

:host >>> .no-margin {
    margin: 0;
}

(As you said you can't change the admin template, this option wouldn't work for you but I'm putting it out here for anyone interested). With this approach, you do not have to include the style in your styles array.

Yet another thing to look at is the different types of view encapsulation: Emulated (default), Native, and None. https://angular.io/docs/ts/latest/guide/component-styles.html#view-encapsulation

Upvotes: 2

Related Questions