Mastering Component Styling: Elevate Your CSS with Layering and Dynamic Class Management, No ng:deep needed!

Mastering Component Styling: Elevate Your CSS with Layering and Dynamic Class Management, No ng:deep needed!

Introduction

In this blog, we will explore two powerful concepts used by PrimeNg to customize component styles without affecting other components: CSS Layering and Dynamic Class Management. These techniques allow developers to efficiently tweak the appearance of PrimeNg components within their own component library, while maintaining a clean separation between styles and the consumer application.

Layering

One of the key strategies employed by PrimeNg is CSS Layering. All component styles are placed within the @layer primeng rule. This approach ensures that when styling the components in our component library, the styles defined in our library take precedence over the styles defined in PrimeNg.

To facilitate this, encapsulation in PrimeNg is set to None. By setting encapsulation to none, it allows the PrimeNg components to be styled from our component library, enabling greater customization options.

Dynamic Class Management

Another important concept employed by PrimeNg is Dynamic Class Management. Without this concept, any CSS changes made for one PrimeNg component within our component library would inadvertently affect another component in the consumer application if the same PrimeNg component is used.

To address this issue, Dynamic Class Management introduces a new input attribute called styleClass, which is bound to the class of the component. The component is then wrapped in a <div> element with the attributes [class]=”styleClass” and [ngClass]=”‘parent-component-class'”. When the styleClass attribute is provided by the user, it overwrites the styles defined in the parent-component-class. This allows for the coexistence of both classes, with the styles specified in the styleClass attribute taking precedence over the ngClass.

Since ng:deep is deprecated and no longer recommended, using Dynamic Class Management is a more modern and maintainable approach to styling components without affecting other components in the consumer application.

By utilizing the bStyleClass attribute with specific styling attributes, it is possible to override attributes defined in the parent class (ngClass). Both [class] and [ngClass] will be applied, but the styles defined in [class] will take precedence over ngClass. Any styles not specified in [class] will be inherited from the class defined in [ngClass].

Example: In the case of the button component, the styles specified in our component library were overridden by the styles in the consumer apps (App 1 and App2). However, other attributes (such as text and size) from our library were applied since there was no override in button.

Steps to Adopt Layering and Dynamic Class Management in the Component Library

To implement layering and dynamic class management in our component library, follow these steps:

Layer all the CSS in the component library using @layer component-library{}.
Introduce a new input attribute, let’s say, bStyleClass.
Wrap the component template in a <div> element with the following attributes: <div [class]=”bStyleClass!” [ngClass]=”‘parent-component-class'”>…</div>.
Set Encapsulation to None for all components in the component library.

Steps to Adopt Layering and Dynamic Class Management in the Consumer Application

To implement layering and dynamic class management in the consumer applications, follow these steps:

Set encapsulation to None for all components in the consumer application.
Add the bStyleClass attribute to the components and assign a className.
In the component’s CSS, style the component with the given className as the parent-component-class.

It is important to note that if we use the @layer, the behavior of @layer changes when !important is used. The style precedence of attributes with !important reverses the concept of precedence in layers.

Additionally, when styling consumer applications, it is advisable to focus on application-specific attributes rather than core-specific attributes. Application-specific attributes include padding, margin, color, width, height, etc. By leveraging the use of !important on core-specific attributes and avoiding it on application-specific attributes, we can maintain better control over style precedence. When mentioning !important in the component library, it is important to specify if it has been used on a core attribute that should not be changed in the consumer application.

Conclusion:

By employing CSS Layering and Dynamic Class Management, developers can effectively customize component styles without impacting other components in their component library. These techniques, as demonstrated in PrimeNg, provide a robust approach to component styling and enable greater flexibility and control over the appearance of applications.

To further enhance component styling, concepts like [style] and [ngStyle] can be utilized to programmatically change inline CSS in the consumer application.

Remember, with CSS Layering and Dynamic Class Management, developers can create visually appealing and highly customizable applications while maintaining a clean and organized codebase.

Attributions

PrimeNg
PrimeNg GitHub
Angular Style Precedence
CSS Layering

Leave a Reply

Your email address will not be published. Required fields are marked *