How to use commas in a CSS variable fallback?

2019-01-28 01:01发布

问题:

How can one use commas in the fallback value of a CSS variable?

E.g. this is fine: var(--color, #f00), but this is weird var(--font-body, Verdana, sans-serif).

The idea is to be able to set a font-family using a variable with a fallback value of say Verdana, sans-serif.


Edit: This actually works pretty well for browsers that support CSS properties, but the issue seems to come from Google Polymer's polyfills.

For future reference, I ended up using variables for both the font and the font family fallback like so (seems to be the cleanest way of doing it for now):

font-family: var(--font-body, Verdana), var(--font-body-family, sans-serif)

回答1:

The below is an extract from the W3C spec: (emphasis is mine)

Note: The syntax of the fallback, like that of custom properties, allows commas. For example, var(--foo, red, blue) defines a fallback of red, blue; that is, anything between the first comma and the end of the function is considered a fallback value.

As you can see from the above statement, if your intention is to set Verdana, sans-serif as fallback value when --font-body is not defined then the syntax given in question is expected to work. It does not require any quotes as per spec.

I don't have a browser that supports CSS variables and hence I couldn't test the following code but it should work based on the spec:

.component .item1 {
  --font-body: Arial;
  font-family: var(--font-body, Verdana, sans-serif); 
  /* should result in font-family: Arial */
}
.component .item2 {
  font-family: var(--font-body, Verdana, sans-serif);
  /* should result in font-family: Verdana, sans-serif */
}
<div class=component>
  <p class=item1>Arial
  <p class=item2>Verdana, sans-serif
</div>



回答2:

As Harry mentions, what you have should already work in browsers that implement custom properties.

But if you're using custom properties with font-family, there is a major caveat: var() does not allow you to modify or add to an existing font-stack, due to the fact that custom properties cascade in exactly the same way as all other properties. That is to say, the expression

var(--font-body, Verdana, sans-serif)

results in one of two possible values:

  1. If a --font-body custom property declaration exists, var(--font-body)
  2. Otherwise, Verdana, sans-serif

The "Verdana, sans-serif" is not part of the font-stack that's defined in --font-body, and should the family defined in --font-body be missing or otherwise unavailable to the browser, it will not fall back to Verdana or sans-serif; it will instead fall back to an arbitrary default font of the browser's choosing.

Worst of all, if the value of --font-body causes the entire font-family declaration to be invalid, that font-family declaration will have no effect.

If you're looking to build font-stacks dynamically in a stylesheet, you cannot use custom properties. You will need a CSS preprocessor.



回答3:

This can be achieved by simply separating the separate values by commas:

p{
  /* By commenting this out, we are making the variable non-existent */
  /* --font-family: "Times New Roman, serif"; */
}

p.sans-serif{
  font-family: var(--font-family, "Arial", "Helvetica");
}
<p class="sans-serif">
  This will be in a sans-serif font because the fallback value is "Arial" and "Helvetica"
</p>

As you can see, the p.sans-serif would normally show in a serif font. If you uncomment the p style, it will show in a serif font.

However, if the variable doesn't exist (which, it doesn't since we commented it out), the fallback works.