Use 2 Fonts in Your Angular Material Custom Typography Config

posted in: Designer 0

So, you like Angular, and you like Angular.Material for styling, theming, and ready-made components that fit a coherent design language. But you still want to make customizations; in this case, to the mat-typography-config. More specifically: create a custom config with a different font family for title headings and body text, and get both configs to work in an override.

In the last sentence, I linked to a stack overflow question where a user answers how to do this. I’ll show you what I was trying to do, I’ll try to get it to work the way the stack exchange user shows (it’s less DRY than what I was trying to do, but whatever works). Then I’ll tell you which one I think is worth a try to get 2 Angular.Material custom typography configs (each with their own, different font-family) to both be added to a typography override and both work.

Here I was setting up 2x custom mat-typography-configs (red squared), one for Title headings, with the Roboto Condensed font, the other for Body text, with the regular Roboto font (blue squared).

// Override typography CSS classes (e.g., mat-h1, mat-display-1, mat-typography, etc.).
@include mat-base-typography($custom-name-typography);

// Override typography for all Angular Material, including mat-base-typography and all components.
@include angular-material-typography($custom-name-typography); 

// Override the typography in the core CSS.
@include mat-core($custom-name-typography);

The problem is: there seems to be room for only one custom typography config per Material Typography override (light-green squared). By “overrides” I mean the 3 different ones Angular.Material lists in their typography section, as shown above.

You can see how I tried to shoehorn 2 different configs into an override, separated by comma (circled red), and the compiler rejects it. But it will compile this scheme if separated by the word “and”, which is an SCSS boolean operator.

Yet, while I’m trying to tell the code I want to include both configs in one override, I either don’t understand the proper syntax to write, or this is not supposed to be done, as it exhibits some unwanted and erratic behavior. Sometimes it works, sometimes it makes a text element too large or too small.

… some testing time passes …

— Testy McGee

Maybe This Works?

// Override typography for all Angular Material, including mat-base-typography and all components

@include angular-material-typography($custom-heading-typography and $custom-body-typography);

I’m starting to be torn on this, because it looks like the most elegant or intuitive solution, to me, for getting 2 configs in a single override. And the last few times I compiled this, searching for an example of how this scheme blows up paragraphs or span elements, I suddenly can’t find any issues… so maybe it is a correct solution?

The Correct Order…

One way to get unwanted behavior to reappear is to change the order of the configs. Notice this sidenav drawer’s toolbar text; it’s too large now. Actually, all the text is a little wrong. And it happened when I changed the order of the configs in the override (yellow and blue squared).

Now when I switch the order back, the fonts seem to behave much more as expected. (Back to the order the configs are defined above… Is that what matters??)

Does it work then?

I dunno. I’m going to try it another way and see if it seems more predictable. Meanwhile, here’s an example of the 2 configs and at the bottom, adding them both to an override simply by adding the “and” operator between the 2 configs.

// First custom Material typography config
$custom-heading-typography: mat-typography-config(
  /* First font family ('Roboto Condensed') */
  $font-family: $title-font,
  // ...
  $display-1: mat-typography-level($d1, $title-line-ht, $regular),
  $headline: mat-typography-level($h1, $title-line-ht, $regular),
  // ...
// Second custom Material typography config
$custom-body-typography: mat-typography-config(
  /* Second font family ('Roboto') */
  $font-family: $primary-font,
  // ...
  $body-2: mat-typography-level($primary-fs, $primary-line-ht, $medium),
  $caption: mat-typography-level($primary-fs, $caption-line-ht, $light),
  // ...

// Override typography for all Angular Material, including mat-base-typography and all components.
/* This works if you put the typography configs in the correct order!? */
@include angular-material-typography($custom-heading-typography and $custom-body-typography); 

Let’s try 2 font families, 1 Config?

I couldn’t get this to work. It blew up more elements than anything else:

Notice I combined the 2 configs into one, named simply “custom-typography”, and added the other font-family inline, as the 4th attribute of a “mat-typography-level()” method. Then there’s only one config to add to the override (I was thinking my problem before was trying to add multiple configs to one override–but now it may just be the ordering problem.)

I also tried describing the Roboto family in various ways–as a variable with quotes, without quotes, as just the font-family name with quotes (Angular wants font names passed as strings)… Almost everything compiled, yet nothing seemed to suddenly fix every text element, so the app could appear as designed. I also stopped the compiler, restarted ‘ng serve,’ and refreshed the browser a few times to try getting the scheme to work–it didn’t matter.


So I’m going to say this 2nd way won’t work, and perhaps the other way I tried will work–or is worth a try… Just make sure you order the various configs as they ‘want to be’ ordered (possibly the same order as they’re described in your style sheet.)

I figure this stuff out as I go, so if you know it already, and can explain exactly how to get 2 different custom Angular mat-typography-configs with 2 different font-families to work seamlessly, please let us know in the comments or send me an email and I’ll update this post.

Leave a Reply about how this blog changed your life.