skip to Main Content

I’m asking this question for an Angular application but I believe this relates to CSS in general.

I have an Angular component with a number of child components, and each has the standard view encapsulation. As an example, I want to change the line-height of all p tags within the parent component, including children components, to a different value.

Something like the following works for this (SCSS):

:host {
    ::ng-deep {
        p {
            line-height: 2em;
        }
    }
}

However, I don’t want to change this style to effect a certain child component, let’s call it foobar. So I hoped something like the following would work:

:host {
    ::ng-deep {
        :not(foobar) {
            p {
                line-height: 2em;
            }
        }
    }
}

I understand this doesn’t work because the p element can be descendants of other elements and so the rule is still applied.

I also know I can do the following:

:host {
    ::ng-deep {
        p:not(foobar p) {
            line-height: 2em;
        }    
    }
}

However, if I want to override a number of elements/classes etc. then this becomes rather unmanageable.


So question is; is there a good/modern way to do this using SCSS or more modern selectors? Anything on the Angular side that can help (aside from turning off viewEncapsulation)?

2

Answers


  1. Chosen as BEST ANSWER

    I resolved this by using a SCSS mixin:

    @mixin not-foobar {
        &:not(foobar #{nth(nth(&, 1), length(nth(&, 1)))}) {
            @content;
        }
    }
    

    with example usage:

    :host {
        ::ng-deep {
            p {
                @include not-foobar {
                    line-height: 2em;
                }
            }    
        }
    }
    

    The mixin basically creates the p:not(foobar p) { selector but means I only need to include the mixin where it's needed, rather than using the selector and possibly setting it incorrectly.

    The #{nth(nth(&, 1), length(nth(&, 1)))}) part of the mixin basically selects the immediate parent. Using just & set the whole parent which led to unwanted side effects in my case.


  2. I don’t know exactly how deeply you want to customize the overall styles of the parent and some child components from the parent component but, you could handle that by creating another stylesheet and adding it to the parent’s styles array like the following:

    parent component

    <p>Parent paragraph</p>
    <child-one></child-one>
    <child-two></child-two>
    

    child one

    <p>Child one paragraph</p>
    

    child two

    <p>Child two paragraph</p>
    

    extra-styles.scss

    :ng-deep {
      child-one {
        p {
          color: green;
        }
      }
    
      child-two {
        p {
          color: blue;
        }
      }
    }
    

    parent.styles.scss

    p {
      color: cyan;
    }
    

    parent.component.ts

    @Component({
      selector: 'parent',
      template: './parent.html',
      styles: ['./parent.styles.scss', 'extra-styles.scss']
    })
    export class ParentComponent {}
    

    Demo

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search