Angular Styling
Styling in Angular uses class/style bindings in templates and component-scoped CSS for maintainable, theme-friendly UIs.
Styling Essentials
- Bindings: Use
[class.foo]
/[ngClass]
for classes and[style.prop]
/[ngStyle]
for styles. - Themes: Toggle CSS variables to switch light/dark or accents.
- Encapsulation: Component styles are scoped by default; use
:host
and:host-context()
for host/theme styling.
<div [class.active]="isActive" [ngClass]="{ big: big }" [style.color]="color" [ngStyle]="{ padding: pad + 'px' }">...</div>
Related: See Data Binding for property/class/style bindings, Templates for applying directives, and Components for component-scoped styles.
Tip: Use class bindings over inline styles for maintainability.
Import CommonModule
for ngClass
/ngStyle
in standalone components.
Use CSS variables to implement theme toggles efficiently.
Encapsulation: Component styles are scoped by default.
Use :host
to style the component root and :host-context(.theme-dark)
to react to a parent theme.
Basic Styling
<div class="box"
[class.highlight]="highlight"
[ngClass]="{ big: big }"
[style.color]="color"
[style.borderColor]="color">...</div>
Use [class.foo]
for single boolean toggles and [ngClass]
when applying multiple classes.
Use classes for reusable look-and-feel.
Use [style.prop]
for one-off numeric or dynamic values (like color, width, padding).
Keep complex styling in CSS classes.
Example
import { bootstrapApplication } from '@angular/platform-browser';
import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
@Component({
selector: 'app-root',
standalone: true,
imports: [CommonModule],
styles: [`
.box { padding: 12px; border: 2px solid #ccc; margin-top: 8px; border-radius: 6px; }
.highlight { background: #fffa8b; }
.big { font-size: 24px; }
.toolbar button { margin-right: 6px; }
`],
template: `
<h3>Styling</h3>
<div class="toolbar">
<button (click)="toggleHighlight()">Toggle Highlight</button>
<button (click)="toggleBig()">Toggle Big</button>
<button (click)="setColor('crimson')">Crimson</button>
<button (click)="setColor('seagreen')">Green</button>
<button (click)="setColor('royalblue')">Blue</button>
</div>
<div class="box"
[class.highlight]="highlight"
[ngClass]="{ big: big }"
[style.color]="color"
[style.borderColor]="color">
Styled box
</div>
`
})
export class App {
highlight = false;
big = false;
color = 'royalblue';
toggleHighlight() { this.highlight = !this.highlight; }
toggleBig() { this.big = !this.big; }
setColor(c: string) { this.color = c; }
}
bootstrapApplication(App);
<app-root></app-root>
Example explained
[class.highlight]
: Toggles thehighlight
class with a boolean.[ngClass]
: Applies multiple classes from an object (e.g.,{ big: big }
).[style.color]
/[style.borderColor]
: Bind style properties to the currentcolor
.- Toolbar: Buttons update component state to demonstrate the bindings.
Bindings over literal class=: Using class="..."
together with [ngClass]
can overwrite classes.
Use [class.foo]
/[ngClass]
for predictable toggles.
Boolean values: Avoid string booleans like [class.active]="'false'"
.
Bind real booleans: [class.active]="isActive"
.
Import CommonModule: ngClass
/ngStyle
live in CommonModule
for standalone components.
Dynamic Styling
<div [ngClass]="{ fancy: fancy, rounded: rounded }"
[ngStyle]="{ color: color, padding: pad + 'px' }">...</div>
Two-way binding with controls lets you change styles live.
[ngClass]
toggles classes based on booleans, and [ngStyle]
sets several style properties at once.
Tip: For performance and clarity, keep style objects small and focused.
Favor classes for larger visual changes.
Example
import { bootstrapApplication } from '@angular/platform-browser';
import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
@Component({
selector: 'app-root',
standalone: true,
imports: [CommonModule, FormsModule],
styles: [`
.box { border: 2px solid #ccc; margin-top: 12px; border-radius: 6px; transition: all .15s ease-in-out; }
.fancy { box-shadow: 0 2px 8px rgba(0,0,0,.15); background: #f9fbff; }
.rounded { border-radius: 14px; }
.toolbar { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.toolbar label { display: inline-flex; align-items: center; gap: 6px; }
`],
template: `
<h3>Dynamic Styling</h3>
<div class="toolbar">
<label><input type="checkbox" [(ngModel)]="fancy"> Fancy</label>
<label><input type="checkbox" [(ngModel)]="rounded"> Rounded</label>
<label>Color <input type="color" [(ngModel)]="color"></label>
<label>Padding <input type="range" min="0" max="40" [(ngModel)]="padding"> {{ padding }}px</label>
<label>Font Size <input type="range" min="12" max="36" [(ngModel)]="fontSize"> {{ fontSize }}px</label>
</div>
<div class="box"
[ngClass]="{ fancy: fancy, rounded: rounded }"
[ngStyle]="{
color: color,
borderColor: color,
padding: padding + 'px',
fontSize: fontSize + 'px'
}">
Styled box
</div>
`
})
export class App {
fancy = true;
rounded = false;
color = '#4169e1';
padding = 12;
fontSize = 18;
}
bootstrapApplication(App);
<app-root></app-root>
Example explained
[(ngModel)]
: Two-way binds form controls to component fields.[ngClass]
: Togglesfancy
/rounded
based on booleans.[ngStyle]
: Sets several style properties at once from component state.
Keep ngStyle small: Large inline style objects become hard to maintain.
Move most styling into CSS classes and bind only dynamic bits.
Encapsulation
:host { display: block; }
:host(.dense) { padding: 8px; }
:host-context(.theme-dark) { color: #eee; }
Component styles are scoped by default to their host element.
Use :host
and :host-context()
for host and theme-aware styling.
Modes: Default is Emulated
.
Use None
sparingly for global styles (e.g., third‑party overrides).
ShadowDom
isolates styles fully.
Host styling: Use :host
over selecting wrapper tags.
Combine with classes on the host for variants (e.g., :host(.dense)
).
Theme context: Use :host-context(.theme-dark)
to adapt to parent themes without leaking global CSS.
Avoid deep selectors: Don't rely on .parent .child
chains inside components.
Expose tokens via CSS variables instead.
Theme with CSS Variables
<div [class.theme-dark]="dark" class="toolbar">
<button (click)="dark = !dark">Toggle {{ dark ? 'Light' : 'Dark' }}</button>
<button (click)="setAccent('#e91e63')">Pink</button>
<button (click)="setAccent('#00b894')">Green</button>
<button (click)="setAccent('#ff9800')">Orange</button>
<span class="swatch" [style.background]="accent"></span>
</div>
<div class="box" [style.--accent]="accent">
This box follows the current theme and accent color.
</div>
CSS variables are named paint buckets you can swap at runtime.
Toggle a class to switch buckets (light/dark) and bind the accent variable for instant theme changes.
Use variables for colors, spacing, and shadows so components can respond to theme changes without code changes.
Example
import { bootstrapApplication } from '@angular/platform-browser';
import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
@Component({
selector: 'app-root',
standalone: true,
imports: [CommonModule],
styles: [`
:host { --bg: #ffffff; --fg: #222; --accent: #4169e1; }
.theme-dark { --bg: #121212; --fg: #eaeaea; --accent: #4f8cff; }
.toolbar { display: flex; gap: 8px; align-items: center; }
.swatch { width: 18px; height: 18px; border-radius: 50%; border: 1px solid #ccc; display: inline-block; vertical-align: middle; }
.box { margin-top: 10px; padding: 14px; border-radius: 8px; border: 2px solid var(--accent); background: var(--bg); color: var(--fg); transition: all .15s ease-in-out; }
button { padding: 6px 10px; }
`],
template: `
<h3>Theme with CSS Variables</h3>
<div [class.theme-dark]="dark" class="toolbar">
<button (click)="dark = !dark">Toggle {{ dark ? 'Light' : 'Dark' }}</button>
<button (click)="setAccent('#e91e63')">Pink</button>
<button (click)="setAccent('#00b894')">Green</button>
<button (click)="setAccent('#ff9800')">Orange</button>
<span class="swatch" [style.background]="accent"></span>
</div>
<div class="box" [style.--accent]="accent">
This box follows the current theme and accent color.
</div>
`
})
export class App {
dark = false;
accent = '#4169e1';
setAccent(c: string) { this.accent = c; }
}
bootstrapApplication(App);
<app-root></app-root>
Example explained
- Theme tokens: CSS variables (e.g.,
--bg
,--fg
,--accent
) define the theme. - Toggle: Adding
theme-dark
on the toolbar swaps variable values. [style.--accent]
: Binds a custom CSS property; the box reads it viavar(--accent)
.
Don't hard-code colors: Binding literal colors (e.g., [style.color]="'red'"
) fights theming.
Use CSS variables and classes.
Scope variables carefully: Keep theme variables at the component host or a top-level theme wrapper to avoid conflicts.
Respect user preference: Use @media (prefers-color-scheme: dark)
to set a sensible default, then allow toggling.
Design tokens: Define semantic tokens (e.g., --surface
, --text
, --accent
) and reference them in components for consistent theming.