Attribute directives are the decorators of the Angular world. They don't change the structure of the house, but they definitely change the paint and the furniture.
1The Object Literal Pattern
While Angular allows you to bind to single classes using [class.name], the [ngClass] directive shines when you have multiple conditional styles. By passing an object where keys are class names and values are booleans, you can manage complex UI states in a single line of code. Angular intelligently merges these dynamic classes with any static classes you've already defined on the element.
2Unit-Safe Styling
When working with ngStyle or style binding, one of the most useful features is the unit suffix. Instead of concatenating strings like [style.width]="w + 'px'", you can simply write [style.width.px]="w". This not only makes your code cleaner but also prevents common bugs related to string formatting in CSS.
3Step-by-Step Breakdown
Attribute directives change the appearance or behavior of an element. They look like regular HTML attributes but are powered by Angular's binding engine.
The most common one is ngClass. It allows you to add or remove multiple CSS classes simultaneously using an object literal.
Next is ngStyle. This is used for setting multiple inline styles dynamically. It's perfect for things like calculated widths or dynamic colors.
Checkpoint: Which directive would you use to toggle the CSS class 'highlight' based on a boolean variable?
- →[ngIf]
- →[ngClass]
- →[ngStyle]
You can also use Property Binding directly on the standard attributes for simple cases, like [class.active] or [style.color].
Why use ngClass then? Because it's cleaner when dealing with many classes at once, and it handles the merging of static and dynamic classes automatically.
Checkpoint: When binding a style value that needs a unit (like pixels), which syntax is correct?
- →[style.font-size.px]="20"
- →[style.font-size]="20"
Great job! Your UI is now visually dynamic. Next, we'll learn how to build our own custom directives from scratch!
Ready to go deeper? Let's move to Custom Directives.
Level Up 🚀
Advanced cheat sheets, SEO tricks, and interview prep for this topic.
Browser Support
Fully supported.
Fully supported.
Fully supported.
Fully supported.
Accessibility (A11y)
1A Custom Directive Adding Interactivity Must Also Add the Right ARIA and Keyboard Behavior
If an attribute directive turns a `<div>` into something clickable or toggleable, it inherits none of a native element's built-in accessibility — the directive itself is responsible for adding `role`, `tabindex`, and keydown handling, not just visual behavior.
2Directives That Manipulate `Renderer2` Styles Shouldn't Rely on Color Alone
A directive like `appHighlight` that only changes background color to signal a state (valid/invalid, active/inactive) conveys nothing to colorblind or screen reader users — pair it with a text or icon change communicated through the DOM, not just a style binding.
SEO Implications
- 1
Attribute Directives Don't Change the Underlying Element's Crawlability
A directive modifies behavior or appearance of an existing host element without altering the semantic tag itself — from a crawler's perspective, the element's fundamental meaning (its tag) is unaffected by whatever directive attributes are attached to it.
- 2
Overusing Directives for DOM Manipulation Can Delay Meaningful Content Rendering
A directive that does heavy computation in `ngOnInit` before revealing its host element can add unnecessary delay to Largest Contentful Paint — keep directive logic that gates visible content as lightweight as possible.
Best Practices
Use `Renderer2` Instead of Direct DOM Manipulation Inside a Directive
Directly setting `elementRef.nativeElement.style` bypasses Angular's abstraction layer and breaks in non-browser rendering contexts (like server-side rendering) — `Renderer2` provides the same capability safely across all Angular platforms.
Use `@HostListener` and `@HostBinding` Instead of Manual Event Listeners
These decorators let Angular manage event binding and cleanup declaratively, integrating with change detection correctly, rather than manually attaching and forgetting to remove native event listeners.
Frequent Bugs
A custom directive works in the browser but throws an error during server-side rendering.
The directive manipulated the DOM directly via `elementRef.nativeElement.style` or similar browser-only APIs, which don't exist in a server (Node.js) rendering context. Use `Renderer2`, which is designed to work safely across both browser and server platforms.
A directive's visual effect (like a highlight) doesn't update when an input-bound value changes.
The directive's `@Input()` setter or `ngOnChanges` isn't reacting to the new value — either add an `ngOnChanges` lifecycle hook, or convert the input to a setter that re-runs the styling logic whenever a new value is assigned.
Real-World Examples
Reusable Highlight Directive
A custom attribute directive highlights any host element on hover, using Renderer2 for safe DOM manipulation that works correctly under server-side rendering.
@Directive({ selector: '[appHighlight]' })
export class HighlightDirective {
constructor(private el: ElementRef, private renderer: Renderer2) {}
@HostListener('mouseenter') onEnter() {
this.renderer.setStyle(this.el.nativeElement, 'background', 'yellow');
}
}