In Angular, the appearance and behavior of elements can be dynamically controlled using attribute directives. Unlike structural directives (like *ngIf
or *ngFor
) which change the DOM structure, attribute directives modify the appearance or behavior of existing elements.
Dynamic styling is a key aspect of creating interactive and responsive web applications, allowing developers to change classes, styles, and behaviors based on component logic or user interaction.
In this guide, we will cover:
- Using
[ngClass]
and[ngStyle]
for dynamic styling - Creating custom attribute directives
- Practical examples for toggling classes and adjusting styles dynamically
- Best practices for maintainable and scalable styling
What Are Attribute Directives?
Attribute directives in Angular are classes that modify the behavior or appearance of elements, components, or other directives. Angular provides some built-in attribute directives such as:
- [ngClass] → dynamically add or remove CSS classes
- [ngStyle] → dynamically set inline styles
- [disabled],
[hidden]
→ bind boolean values to HTML attributes
Attribute directives are typically applied using square brackets or by creating custom directive selectors.
Using [ngClass] for Conditional Styling
[ngClass]
allows developers to conditionally apply or remove CSS classes on HTML elements based on component state.
Syntax
<div [ngClass]="{ 'active': isActive, 'highlighted': isHighlighted }">
Content goes here
</div>
'active'
→ CSS class nameisActive
→ Boolean property in the component that controls the class
Example: Toggling Classes
import { Component } from '@angular/core';
@Component({
selector: 'app-toggle-class',
template: `
<button (click)="toggleActive()">Toggle Active</button>
<div [ngClass]="{ 'active': isActive, 'highlighted': isHighlighted }">
Dynamic Styled Div
</div>
`,
styles: [
.active { color: white; background-color: green; padding: 10px; }
,
.highlighted { font-weight: bold; border: 2px solid blue; }
]
})
export class ToggleClassComponent {
isActive = false;
isHighlighted = true;
toggleActive() {
this.isActive = !this.isActive;
}
}
- Clicking the button toggles the
'active'
class. 'highlighted'
class remains static until changed programmatically.
Using Array Syntax with [ngClass]
You can also use an array of class names:
<div [ngClass]="['class1', 'class2', isActive ? 'active' : '']">
Content with multiple classes
</div>
- Combines static and conditional classes dynamically.
Using [ngStyle] for Dynamic Inline Styles
While [ngClass]
manipulates CSS classes, [ngStyle]
allows you to set individual CSS properties dynamically.
Syntax
<div [ngStyle]="{ 'color': fontColor, 'font-size.px': fontSize }">
Dynamic Styled Text
</div>
- Property names are strings (
'color'
,'background-color'
) - Numeric values can include units (
.px
,.em
)
Example: Dynamic Font Styling
import { Component } from '@angular/core';
@Component({
selector: 'app-ngstyle-demo',
template: `
<p [ngStyle]="{ 'color': color, 'font-size.px': fontSize }">
This text is dynamically styled.
</p>
<button (click)="increaseFont()">Increase Font</button>
<button (click)="toggleColor()">Toggle Color</button>
`
})
export class NgStyleDemoComponent {
color = 'red';
fontSize = 14;
increaseFont() {
this.fontSize += 2;
}
toggleColor() {
this.color = this.color === 'red' ? 'blue' : 'red';
}
}
- Users can interactively change style properties.
[ngStyle]
allows fine-grained control over specific style properties.
Combining [ngClass] and [ngStyle]
You can use both directives together for more complex styling scenarios:
<div
[ngClass]="{ 'highlighted': isHighlighted }"
[ngStyle]="{ 'font-size.px': fontSize, 'color': textColor }">
Combined Styling Example
</div>
isHighlighted = true;
fontSize = 16;
textColor = 'green';
[ngClass]
handles structural class changes[ngStyle]
handles inline property changes
Creating Custom Attribute Directives
Angular also allows you to create your own attribute directives to encapsulate styling or behavior logic.
Step 1: Generate a Directive
ng generate directive highlight
This creates:
src/app/highlight.directive.ts
Step 2: Implement the Directive
import { Directive, ElementRef, HostListener, Input } from '@angular/core';
@Directive({
selector: '[appHighlight]'
})
export class HighlightDirective {
@Input('appHighlight') highlightColor: string = 'yellow';
constructor(private el: ElementRef) {}
@HostListener('mouseenter') onMouseEnter() {
this.highlight(this.highlightColor);
}
@HostListener('mouseleave') onMouseLeave() {
this.highlight('');
}
private highlight(color: string) {
this.el.nativeElement.style.backgroundColor = color;
}
}
@Input()
allows passing a custom colorHostListener
listens for events likemouseenter
andmouseleave
ElementRef
provides access to the DOM element
Step 3: Use the Directive
<p appHighlight="lightgreen">Hover over me to see highlight</p>
<p appHighlight="lightblue">Hover over me too!</p>
- Each element responds independently with dynamic styling.
- This approach encapsulates styling logic in a reusable directive.
Examples for Toggling Classes
1. Toggle Multiple Classes Dynamically
<div [ngClass]="{
'bold': isBold,
'italic': isItalic,
'underline': isUnderlined
}">
Styled Text
</div>
<button (click)="isBold = !isBold">Toggle Bold</button>
<button (click)="isItalic = !isItalic">Toggle Italic</button>
<button (click)="isUnderlined = !isUnderlined">Toggle Underline</button>
- Each class toggles individually
ngClass
supports multiple conditional classes
2. Dynamic Button Styles
<button [ngStyle]="{ 'background-color': isPrimary ? 'blue' : 'gray', 'color': 'white' }"
(click)="isPrimary = !isPrimary">
Click Me
</button>
- Button color toggles dynamically when clicked
[ngStyle]
is ideal for property-level control
3. Conditional Styling Based on Component State
import { Component } from '@angular/core';
@Component({
selector: 'app-status',
template: `
<p [ngClass]="statusClass">{{ statusMessage }}</p>
<button (click)="toggleStatus()">Toggle Status</button>
`
})
export class StatusComponent {
isActive = true;
get statusClass() {
return this.isActive ? 'active-status' : 'inactive-status';
}
get statusMessage() {
return this.isActive ? 'Active' : 'Inactive';
}
toggleStatus() {
this.isActive = !this.isActive;
}
}
CSS:
.active-status {
color: green;
font-weight: bold;
}
.inactive-status {
color: red;
font-style: italic;
}
- Combines ngClass and component logic
- Dynamic class selection based on a method or getter
Best Practices for Attribute Directives and Dynamic Styling
- Prefer CSS Classes Over Inline Styles
- Use
[ngClass]
rather than[ngStyle]
whenever possible for maintainability.
- Use
- Encapsulate Complex Logic in Directives
- Create reusable custom directives for styling or behavior instead of repeating code.
- Keep Component Templates Clean
- Avoid cluttered templates with many
[ngStyle]
bindings.
- Avoid cluttered templates with many
- Use HostBinding in Custom Directives
- Simplifies binding styles or classes in directives:
@HostBinding('style.backgroundColor') bgColor: string = 'yellow';
- Combine ngClass and ngStyle for Maximum Flexibility
[ngClass]
for conditional classes[ngStyle]
for property-specific adjustments
Leave a Reply