Marc Freeman
Marc Freeman

Reputation: 753

Angular - Child components inheriting parent styles (opacity)

I'm wondering if there's a way to stop Angular Child components inheriting the parents styles, mainly opacity.

I have a form wrapper that sits on top of the page like so:

import {Component, EventEmitter, Output} from "@angular/core";

@Component({
  selector: 'new-student-form-wrapper',
  templateUrl: './new-student-form-wrapper.component.html',
  styleUrls: ['./new-student-form-wrapper.component.scss']
})
export class NewStudentFormWrapperComponent {

  @Output() public onNewStudentFormClose: EventEmitter<void> = new EventEmitter<void>();

  public newStudentFormCloseClicked(): void {
    this.onNewStudentFormClose.emit();
  }

}

::ng-deep {
  .student-details-form {
    opacity: 0;
  }
}

.new-student-form-wrapper {
  z-index: 50;
  height: 100vh;
  width: 100vw;
  position: absolute;
  background-color: white;
  opacity: 0.8;

  .c-pointer {
    cursor: pointer;
  }
}

<div class="new-student-form-wrapper p-4">
  <mdb-icon class="c-pointer d-flex close-icon" (click)="newStudentFormCloseClicked()" fas icon="times"></mdb-icon>
  <new-student-form></new-student-form>
</div>

With a child component that will actually contain the form behaviour:

import {Component} from "@angular/core";

@Component({
  selector: 'new-student-form',
  templateUrl: './new-student-form.component.html',
  styleUrls: ['./new-student-form.component.scss']
})
export class NewStudentFormComponent {

}

.student-details-form {
  opacity: 1;
  background-color: purple; /** Just to test opacity*/
}

<div class="student-details-form md-form input-group d-flex flex-column">
  <div class="form-header">
    <h1>Hello</h1>
  </div>
</div>

However, despite actually explicitly declaring that new-student-form.component to have an opacity of 0, it is still picking up the container's 0.8 opacity rule.

enter image description here

I'm definitely using ng-deep wrong, what is the best way to remove the opacity for the child? Is there an encapsulation rule I can use to stop the styles leaking into another component?

Upvotes: 1

Views: 1269

Answers (1)

Poul Kruijt
Poul Kruijt

Reputation: 71961

Opacity applies to the element as a whole, including its contents, even though the value is not inherited by child elements. Thus, the element and its children all have the same opacity relative to the element's background, even if they have different opacities relative to one another.

Not entirely sure if it will provide you with result you expect, but to define a transparent background, you can use the rgba on the background:

.new-student-form-wrapper {
  z-index: 50;
  height: 100vh;
  width: 100vw;
  position: absolute;
  background-color: rgba(255, 255, 255, 0.8);
}

Because it looks like you are using scss, you can also use the transparentize utility function:

background-color: transparentize(white, 0.2)

This way the form-wrapper is still a bit transparent, but any child content will be clearly visible


On a sidenote, that's indeed not the right way to use ::ng-deep. Although it's one way to use it. How you wrote it now will target any element in your document with the class .student-details-form. To only target descendants of the current component, you need to add the :host selector:

:host ::ng-deep {
  .student-details-form {
    // style here
  }
}

To explain ::ng-deep a bit better, I'll just use some examples. Basically what ::ng-deep does is that it does not add the _ngcontent-xxx-xxxx attribute selector to the emitted css. (This happens when you use ViewEncapsulation.Emulated and thus only does something in a component stylesheet).

Soo, if you have the following in your component scss:

::ng-deep {
  .form0 {
    opacity: 0;
  }
}

:host ::ng-deep {
  .form1 {
    opacity: 0.1
  }
}

:host {
  .form2 {
    opacity: 0.2;
  }
}

.form3 {
  opacity: 0.3;
}

.form-wrapper ::ng-deep {
  form4 {
    opacity: 0.4;
  }
}

This will result in something like this:

.form0 {
  opacity: 0;
}

[_nghost-xxx-xxxx] .form1 {
  opacity: 0.1;
}

[_nghost-xxx-xxxx] .form2[_ngcontent-xxx-xxxx] {
  opacity: 0.2;
}

[_ngcontent-xxx-xxxx].form3 {
  opacity: 0.3;
}

.form-wrapper[_ngcontent-xxx-xxxx] .form4 {
  opacity: 0.4;
}

As you can see, if you use ::ng-deep on the root it is css without (emulated) encapsulation. Encapsulation is emulated through the host and content attribute selectors

Upvotes: 2

Related Questions