CSS Cascade has no affect on font shorthand if properties have variables as values

74 Views Asked by At

Let’s assume we have the following CSS Custom Properties:

// Global CSS
:root {
  --font-weight-500: 500;
  --font-size-350: 14px;
  --font-line-height-500: 20px;
  --font-family-sans: 'Roboto Flex', Roboto, Helvetica, Arial, sans-serif;
  --font-family-primary: var(--font-family-sans);

  --font-body-medium-1: var(--font-weight-500) var(--font-size-350)/var(--font-line-height-500) var(--font-family-primary);
}

And the following web component with an open shadow root.

// Web Component
:host {
  --font-family-primary: “Comic Sans MS”;
  font: var(--font-body-medium-1);
}

Any idea why the font shorthand does not accept any individual property overrides? Every test fails. If the font properties individual properties like font-family have custom properties as their values, the cascade doesn't happen.

1

There are 1 best solutions below

2
Nkemdi Anyiam On

EDIT: Updated for correct answer

The reason it isn't working is because in CSS, the property values are computed, and then the computed value is inherited. --font-body-medium-1 was already computed in :root, so it's locked into using the custom vars that were also in :root. It can't see the overridden --font-family-primary because it can't reach down into a descendant to read that new value.

As proof, if you copy --font-body-medium-1: var(--font-weight-500) var(--font-size-350)/var(--font-line-height-500) var(--font-family-primary); directly into your :host, you'll see that the override does work. That's because now, font-body-medium-1 is inhereting the other custom vars from :root but can see the new --font-family-primary value.

There is a solution. It would obviously be tedious to copy --font-body-medium-1 everywhere you want to use it, so you can instead define the custom property on every element using the universal selector. You can also remove it from :root since it doesn't accomplish anything there.

// Global CSS
:root {
  --font-weight-500: 500;
  --font-size-350: 14px;
  --font-line-height-500: 20px;
  --font-family-sans: 'Roboto Flex', Roboto, Helvetica, Arial, sans-serif;
  --font-family-primary: var(--font-family-sans);

  /*  --font-body-medium-1: var(--font-weight-500) var(--font-size-350)/var(--font-line-height-500) var(--font-family-primary);  */
}

* {
  --font-body-medium-1: var(--font-weight-500) var(--font-size-350)/var(--font-line-height-500) var(--font-family-primary);
}
// Web Component
:host {
  --font-family-primary: “Comic Sans MS”;
  font: var(--font-body-medium-1);
}

Old answer

The font shorthand must provide values for at least font-size and font-family (and in that order). Your code isn't working because you're only providing a value for the font family—put a font size before it and it should work fine. E.g. font: 16px var(--font-family-primary);.

You can read more about the specifics in the documentation here: https://developer.mozilla.org/en-US/docs/Web/CSS/font (just look at the Syntax section).