angularsassangular-materialangular-material2

$font-family is an 'Undefined variable' in Angular 17 and Material 17


I've followed the Angular and Material documentation on migration from previous versions to the new, and I've run into an issue that doesn't make sense to me. Take a look at the official documentation: https://v17.material.angular.io/guide/theming-your-components#step-4-include-the-theme-mixin-in-your-application

It specifically has this as an example:

 typography: mat.define-typography-config(
    $font-family: serif,
  );

Why $font-family and not font-family? I don't know. By using the same piece of code, but modified to my needs, I get an error:

Undefined variable.
   ╷
50 │     $font-family: "'Avenir Next LT Pro Bold', sans-serif",
   │     ^^^^^^^^^^^^
   ╵
  src\_theme.scss 50:5  root stylesheet

Here's my _theme.scss file:

@use '@angular/material' as mat;
@import './variables';

@include mat.core();

$b-blue: (
  50: #e4e8ef,
  100: #bcc5d6,
  200: #8f9fbb,
  300: #6278a0,
  400: #415b8b,
  500: #1f3e77,
  600: #1b386f,
  700: #173064,
  800: #12285a,
  900: #0a1b47,
  A100: #7e9cff,
  A200: #4b74ff,
  A400: #184dff,
  A700: #003afd,
  contrast: (
    50: #000000,
    100: #000000,
    200: #000000,
    300: #ffffff,
    400: #ffffff,
    500: #ffffff,
    600: #ffffff,
    700: #ffffff,
    800: #ffffff,
    900: #ffffff,
    A100: #000000,
    A200: #ffffff,
    A400: #ffffff,
    A700: #ffffff
  )
);

$b-print-theme: mat.define-light-theme((
  color: (
    primary: $b-print-theme-primary,
    accent: $b-print-theme-accent,
    warn: $b-print-theme-warn,
  ),
  typography: mat.define-typography-config((
    $font-family: "'Avenir Next LT Pro Bold', sans-serif",
    $display-1: mat.define-typography-level(21px, 28.69px, 700),
    $headline: mat.define-typography-level(24px, 24px, 700),
    $title: mat.define-typography-level(18px, 24.59px, 400, 'Avenir Next LT Pro Regular'),
    $subheading-2: mat.define-typography-level(18px, 24.59px, 700),
    $subheading-1: mat.define-typography-level(16px, 21.86px, 400, 'Avenir Next LT Pro Regular'),
    $body-1: mat.define-typography-level(12px, 16.39px, 400, 'Avenir Next LT Pro Regular'),
    $body-2: mat.define-typography-level(12px, 16.39px, 400),
  ))
));

@include mat.all-component-themes($b-print-theme);
@include mat.typography-hierarchy($b-typography);

According to other sources, this should work, but I just get the Undefined variable.

Relevant package.json sections:

  "dependencies": {
    "@angular/animations": "^17.3.12",
    "@angular/cdk": "^17.3.10",
    "@angular/common": "^17.3.12",
    "@angular/compiler": "^17.3.12",
    "@angular/core": "^17.3.12",
    "@angular/forms": "^17.3.12",
    "@angular/material": "^17.3.10",
    "@angular/platform-browser": "^17.3.12",
    "@angular/platform-browser-dynamic": "^17.3.12",
    "@angular/router": "^17.3.12",
    "@fortawesome/fontawesome-free": "^5.15.4",
    "@ng-select/ng-select": "^12.0.7",
    "@ngx-translate/core": "^14.0.0",
    "@ngx-translate/http-loader": "^6.0.0",
    "@types/events": "^3.0.3",
    "angular2-uuid": "^1.1.1",
    "lodash": "^4.17.21",
    "moment": "^2.29.1",
    "msal": "^1.4.4",
    "rxjs": "^6.0.0",
    "tslib": "^2.7.0",
    "zone.js": "~0.14.10"
  }

Solution

  • You are wrapping the variables into parentheses, which creates an additional Sass map. However, Angular expects the variable directly and without a map. Just remove those parentheses.

    $b-print-theme: mat.define-light-theme((
      color: (
        primary: $b-print-theme-primary,
        accent: $b-print-theme-accent,
        warn: $b-print-theme-warn,
      ),
      typography: mat.define-typography-config(
        $font-family: "'Avenir Next LT Pro Bold', sans-serif",
        $display-1: mat.define-typography-level(21px, 28.69px, 700),
        $headline: mat.define-typography-level(24px, 24px, 700),
        $title: mat.define-typography-level(18px, 24.59px, 400, 'Avenir Next LT Pro Regular'),
        $subheading-2: mat.define-typography-level(18px, 24.59px, 700),
        $subheading-1: mat.define-typography-level(16px, 21.86px, 400, 'Avenir Next LT Pro Regular'),
        $body-1: mat.define-typography-level(12px, 16.39px, 400, 'Avenir Next LT Pro Regular'),
        $body-2: mat.define-typography-level(12px, 16.39px, 400),
      )
    ));