Angular Material Setup — Theming, Typography and Global Styles

Angular Material provides a comprehensive component library based on Google’s Material Design 3 specification. Setting it up correctly — theme, typography, and dark mode — establishes a consistent visual foundation for the entire BlogApp. Material Design 3’s theming system uses “color roles” (primary, secondary, tertiary, surface, error) that adapt automatically for light and dark modes, eliminating manual dark mode CSS. The correct setup takes 15 minutes and saves hours of custom styling.

Angular Material Theme Configuration

// 1. Install: ng add @angular/material
// ── app.config.ts ─────────────────────────────────────────────────────────
export const appConfig: ApplicationConfig = {
  providers: [
    provideAnimationsAsync(),   // required for Material animations
    provideRouter(routes),
    provideHttpClient(),
  ],
};
/* ── styles.scss — Material Design 3 theme ──────────────────────────────── */
@use '@angular/material' as mat;

/* ── Include core styles once ─────────────────────────────────────────────*/
@include mat.core();

/* ── Define the application theme ─────────────────────────────────────────*/
$blogapp-theme: mat.define-theme((
  color: (
    theme-type: light,
    primary:    mat.$azure-palette,    /* blue-based primary */
    tertiary:   mat.$violet-palette,
  ),
  typography: (
    brand-family: 'Inter, sans-serif',
    plain-family: 'Roboto, sans-serif',
  ),
  density: (
    scale: 0,    /* 0=default, -1=compact, -2=more compact */
  ),
));

/* ── Apply to html element ─────────────────────────────────────────────── */
html {
  @include mat.all-component-themes($blogapp-theme);
  height: 100%;
}

body {
  margin: 0;
  height: 100%;
  font-family: var(--mat-sys-body-large-font);
  background-color: var(--mat-sys-background);
  color: var(--mat-sys-on-background);
}

/* ── Dark mode — automatic via prefers-color-scheme ─────────────────────*/
$blogapp-dark-theme: mat.define-theme((
  color: (
    theme-type: dark,
    primary:    mat.$azure-palette,
    tertiary:   mat.$violet-palette,
  ),
));

@media (prefers-color-scheme: dark) {
  html {
    @include mat.all-component-colors($blogapp-dark-theme);
  }
}

/* ── Typography scale — use Material type tokens ──────────────────────── */
h1 { font: var(--mat-sys-headline-large);  }
h2 { font: var(--mat-sys-headline-medium); }
h3 { font: var(--mat-sys-headline-small);  }
p  { font: var(--mat-sys-body-large);      }

/* ── Utility classes ───────────────────────────────────────────────────── */
.full-width      { width: 100%; }
.text-center     { text-align: center; }
.mt-1 { margin-top:    0.5rem; }
.mt-2 { margin-top:    1rem;   }
.gap-1 { gap: 0.5rem; }
.gap-2 { gap: 1rem;   }
Note: Material Design 3 uses color tokens (CSS custom properties like --mat-sys-primary, --mat-sys-surface) throughout all components. These tokens automatically switch between light and dark values based on the theme type. Using these tokens in your custom component styles instead of hardcoded hex colors gives you automatic dark mode support: color: var(--mat-sys-on-surface) renders dark text in light mode and light text in dark mode without any additional CSS.
Tip: Use the density: { scale: -1 } option to create a compact layout for data-dense admin screens and scale: 0 (default) for comfortable consumer-facing screens. You can also apply density to individual components: @include mat.button-density(-1) in a specific component’s SCSS file creates compact buttons only in that component without affecting the rest of the application.
Warning: Always import @use '@angular/material' as mat at the top of styles.scss before any other Angular Material usage. The mat.core() mixin must be included exactly once — it registers global styles for Material overlays, ripples, and focus indicators. Including it multiple times creates duplicate CSS. If you use per-component styles (styleUrls), only import the specific component theme mixin there, never mat.all-component-themes() which includes all components and balloons the CSS bundle.

Common Mistakes

Mistake 1 — Importing all-component-themes in multiple places (bloated CSS bundle)

❌ Wrong — including mat.all-component-themes() in both styles.scss and component SCSS files; duplicates all Material CSS.

✅ Correct — include mat.all-component-themes() once in styles.scss; use component-specific mixins in component SCSS files if customisation is needed.

Mistake 2 — Hardcoding colors instead of Material tokens (no dark mode support)

❌ Wrong — color: #1976d2 in component CSS; ignores the theme; wrong color in dark mode.

✅ Correct — color: var(--mat-sys-primary); adapts to light/dark theme automatically.

🧠 Test Yourself

A user’s OS is set to dark mode. The app uses mat.define-theme with theme-type: light and a dark theme applied via @media (prefers-color-scheme: dark). What does the user see?