Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix 32619: clarify font-weight descriptor #32853

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a reminder you can use any of these instead of landing the assets in the content repo:

https://github.com/mdn/shared-assets/tree/main/fonts

i.e., https://mdn.github.io/shared-assets/fonts/FiraSans-Light.woff2

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, now we're using Fira Sans and League Mono!

Binary file not shown.
Binary file not shown.
Binary file not shown.
134 changes: 117 additions & 17 deletions files/en-us/web/css/@font-face/font-weight/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ browser-compat: css.at-rules.font-face.font-weight

{{CSSRef}}

The **`font-weight`** CSS descriptor allows authors to specify font weights for the fonts specified in the {{cssxref("@font-face")}} at-rule. The {{cssxref("font-weight")}} property can separately be used to set how thick or thin characters in text should be displayed.
The **`font-weight`** CSS descriptor enables authors to specify a single font weight, or a range of font weights, for the font specified in a {{cssxref("@font-face")}} at-rule. This is then used by the browser to select the appropriate font when a CSS rule sets the desired weight of a font.

For a particular font family, authors can download various font faces which correspond to the different styles of the same font family, and then use the `font-weight` descriptor to explicitly specify the font face's weights. The values for the CSS descriptor is same as that of its corresponding font property.
Unless it contains a [variable font](/en-US/docs/Web/CSS/CSS_fonts/Variable_fonts_guide), a single font file contains characters from a font family in a specific weight and style: for example, "Helvetica bold italic". Typically, a developer will want to use fonts from a single font family in a range of different weights. To accomplish this, you can define multiple {{cssxref("@font-face")}} at-rules for the same family, one for each weight, and set the `font-weight` descriptor to match the font's weight. Then CSS rules can select a font in the appropriate weight by setting the {{cssxref("font-weight")}} property or the {{cssxref("font")}} shorthand property.
estelle marked this conversation as resolved.
Show resolved Hide resolved

There are generally limited weights available for a particular font family. When a specified weight doesn't exist, a nearby weight is used. Fonts lacking bold typeface are often synthesized by the user agent. To prevent this, use the {{cssxref('font-synthesis')}} shorthand property.
If a font file contains a variable font, it may contain more than one weight. To reflect this, the `font-weight` descriptor can specify a range of weights, given as a space separated pair of weight values.
wbamberg marked this conversation as resolved.
Show resolved Hide resolved

## Syntax

Expand All @@ -21,26 +21,28 @@ font-weight: normal;
font-weight: bold;
font-weight: 400;

/* Multiple Values */
/* Defining a range */
font-weight: normal bold;
font-weight: 300 500;
```

The `font-weight` property is described using any one of the values listed below.

### Values

The syntax of the `font-weight` descriptor takes one of the following forms:

- The keyword `auto`.
- A single `<font-weight-absolute>` value.
- A pair of `<font-weight-absolute>` values, separated by a space.

Each `<font-weight-absolute>` may be any one of the following:

- `normal`
- : Normal font weight. Same as `400`.
- `bold`
- : Bold font weight. Same as `700`.
- `<number>`
- : A {{cssxref("&lt;number&gt;")}} value between 1 and 1000, inclusive. Higher numbers represent weights that are bolder than (or as bold as) lower numbers. Certain commonly used values correspond to common weight names, as described in the [Common weight name mapping](#common_weight_name_mapping) section below.

In earlier versions of the `font-weight` specification, the property accepts only keyword values and the numeric values 100, 200, 300, 400, 500, 600, 700, 800, and 900; non-variable fonts can only really make use of these set values, although fine-grained values (e.g. 451) will be translated to one of these values for non-variable fonts.

CSS Fonts Level 4 extends the syntax to accept any number between 1 and 1000, inclusive, and introduces [Variable fonts](#variable_fonts), which can make use of this much finer-grained range of font weights.

### Common weight name mapping

The numerical values `100` to `900` roughly correspond to the following common weight names:
Expand Down Expand Up @@ -80,20 +82,118 @@ People experiencing low vision conditions may have difficulty reading text set w

## Examples

### Setting normal font weight in a @font-face rule
### Selecting normal and bold fonts

In this example we include two fonts, one normal weight, one bold weight, from the ["Karantina"](https://fonts.google.com/specimen/Karantina) font family using two `@font-face` at rules. We set `font-weight` descriptors to match the weight of the fonts.

The following finds a local Open Sans font or imports it, and allows using the font for normal font weights.
After this, CSS rules can select the normal or the bold font for the "Karantina" family just by setting the {{cssxref("font-weight")}} property. Note that the {{htmlelement("strong")}} HTML element also selects the bold font, because by default `<strong>` elements use a bold font.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
After this, CSS rules can select the normal or the bold font for the "Karantina" family just by setting the {{cssxref("font-weight")}} property. Note that the {{htmlelement("strong")}} HTML element also selects the bold font, because by default `<strong>` elements use a bold font.
After this, CSS rules automatically select the normal or the bold font for the "Karantina" family based on an element's computed {{cssxref("font-weight")}} property value. Note that the {{htmlelement("strong")}} HTML element also selects the bold font, because user agents set `font-weight: bolder` on `<strong>` elements as the default.


#### HTML

```html
<p class="one">Karantina, normal weight paragraph</p>
<p class="two">Karantina, bold weight paragraph</p>
<strong>Karantina, default weight &lt;strong&gt; element</strong>
```

#### CSS

```css
@font-face {
font-family: "Open Sans";
src:
local("Open Sans") format("woff2"),
url("/fonts/OpenSans-Regular-webfont.woff") format("woff");
font-weight: 400;
font-family: "Karantina";
font-weight: normal;
src: url("Karantina-Regular.woff2");
}

@font-face {
font-family: "Karantina";
font-weight: bold;
src: url("Karantina-Bold.woff2");
}

body {
font-family: "Karantina", serif;
font-size: 3rem;
}

p.one {
font-weight: normal;
}

p.two {
font-weight: bold;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This works, but it's the default action expected of "font-weight: bold;". Should we invert the font calls, so Karantina-Bold is displayed for normal and Karantina for bold? Or something similar to show this really makes a difference?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand this comment.

it's the default action expected of "font-weight: bold;"

I'm not sure what "the default action" means here. Like, if you don't set the font-weight descriptor, like this:

@font-face {
  font-family: "Karantina";
  src: url("Karantina-Regular.woff2");
}

@font-face {
  font-family: "Karantina";
  src: url("Karantina-Bold.woff2");
}

body {
  font-family: "Karantina", serif;
  font-size: 3rem;
}

p.one {
  font-weight: normal;
}

p.two {
  font-weight: bold;
}

...then both paras and the <strong> will select "Karantina-Bold" because that's matched last (I think). The browser will also apply synthetic boldification to para 2 and the <strong>:

Screen Shot 2024-04-03 at 8 03 40 PM

It's only because we've set the font-weight descriptor that:

  • para 1 selects "Karantina-Regular",
  • para 2 and the <strong> select "Karantina-Bold" don't apply synthetic boldification
    ... and we get proper typography:
Screen Shot 2024-04-03 at 8 05 16 PM

That's what this example is showing: by setting the font-weight descriptor, you enable a rule to select the appropriate font file by setting the font-weight property.

At least such is my understanding.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Everything you wrote is correct. The issue is that the user will not be able to see a difference between a synthetic bold and the use of the actual bold font.

I found this old example I wrote that barely works, but explains what I mean. At https://estelle.github.io/CSS/fonts/index.html#slide60 (slide 60 if the presentation doesn't actually move forward), if you change the font-weight in the p.fwd block to 700, you'll note the font family changes. The deck is old, and i had all the other fonts on my local machine when i did the presentation, so only the boldest font will work on your device. In that CSS, all the @font declarations are using the same font-family descriptor, but include different font-weight values and import complete different fonts. That was the user can see that a different font file is being used when the font-weight leads to different font-files used to render content. This is obviously not something one would do in production, but it enables the learner to really see what is going on.

In the current example on this page, the example will still be bold (or light) if the fonts don't even load. Yes, the second paragraph and the <strong> select "Karantina-Bold" and don't apply a synthetic a bold because we say so, but is it really just applying a synthetic bold? If we use drastically different fonts for normal v. bold in our @font src descriptor, the user will definitely see the effect. My suggestion was to invert bold and normal to show the difference, but drastically different fonts would be better (as it would be less confusing that "messing up" and explaining it)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this example should show the actual proper common usage of the font-weight descriptor to support multiple fonts in the same family, which is what it currently does. It implies "this is a good-practice way to use font-weight, if you're not using variable fonts". That's why I don't think we should change it to show something unrealistic, even if it is more illustrative.

I do agree that the counterfactual is not that clear, and that font synthesis makes the story more complicated. It might help to:

(a) find a font family that has a clearer differentiation between bold and normal weight
(b) maybe talk about the counterfactual (and even show it in the example) to explain what is happening (and that it is in fact broken)

That would make the example quite complex. I think one underlying problem here is that a lot of this explanation would go into a guide page, and because we don't have one, it is having to go here instead.

But I do think it is important for the first example here to show an actual good practice usage. Otherwise people have to infer it from unrealistic examples, and that's also putting a burden on them.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All valid points. We really do need a font guide!

We can leave as is, but I did think of other options. Sharing in case you want to include one of them:

  1. Duplicating the first example as a second example, and just inverting the bold / normal descriptors, with something like "This example "accidentally" inverts the font-weight descriptors, leading to a bold font being rendered when the font-weight property is normal and a normal font is rendered when the property is bold.

  2. including 3 katerina fonts, serving 'light' up to 500, regular from 501 to 700, and bold 701 and above (though this would be for the numeric example after this one)

  3. in the numeric example, leaving gaps, so fallback font-family is used below 200 and above 800 or something similar.

}
```

#### Result

{{embedlivesample("Selecting normal and bold fonts", "", 300)}}

### Setting a range for a variable font

In this example we include a variable font, ["Montserrat"](https://fonts.google.com/specimen/Montserrat), using a single `@font-face` at-rule. We've used a `font-weight: 300 700` value to effectively limit the range of weights that are available. If a CSS rule uses our "Montserrat" font, then if it specifies a weight outside this range the weight it gets is clamped to the range.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
In this example we include a variable font, ["Montserrat"](https://fonts.google.com/specimen/Montserrat), using a single `@font-face` at-rule. We've used a `font-weight: 300 700` value to effectively limit the range of weights that are available. If a CSS rule uses our "Montserrat" font, then if it specifies a weight outside this range the weight it gets is clamped to the range.
In this example we include a variable font, ["Montserrat"](https://fonts.google.com/specimen/Montserrat), using a single `@font-face` at-rule. We've used a `font-weight: 300 700` value to effectively limit the range of weights for which this font will be used. If a CSS rule includes "Montserrat" as its first declared `font-family`, but the `font-weight` property value is outside of the weight range specified by the `font-weight` descriptor, the next font in the `font-family` list will be used, as the `Monserrat` font is clamped to the limited range specified by the descriptor.

this is what we want to say, though this might not be exactly how you want to say it.


To show the effect of this we've included another font using "Montserrat" that does not set the `font-weight` descriptor, and we've called this "Montserrat-complete".
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do you want to change the value to auto?


#### HTML

```html
<p class="one">Montserrat, font-weight 100</p>
<p class="two">Montserrat, font-weight 900</p>
<p class="three">Montserrat-complete, font-weight 100</p>
<p class="four">Montserrat-complete, font-weight 900</p>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
<p class="one">Montserrat, font-weight 100</p>
<p class="two">Montserrat, font-weight 900</p>
<p class="three">Montserrat-complete, font-weight 100</p>
<p class="four">Montserrat-complete, font-weight 900</p>
<p class="one">font-weight 200</p>
<p class="two">font-weight 400</p>
<p class="three">font-weight 600</p>
<p class="four">font-weight 800</p>

If we change to this, the two middle ones will be Monserrat and the first and list will be M-Complete. If we do this, however, we may want to use two very different fonts so the reader can quickly see that the middle two are different from the first and last. It is also how developers should be using @font; though most don't because font descriptors are rarely fully explained. In other words, I am super glad we are writing this!!!!!

```

#### CSS

```css
@font-face {
font-family: "Montserrat";
src: url("Montserrat[wght].woff2");
font-weight: 300 700;
}

@font-face {
estelle marked this conversation as resolved.
Show resolved Hide resolved
font-family: "Montserrat-complete";
src: url("Montserrat[wght].woff2");
}

p {
font-size: 2rem;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
font-size: 2rem;
font-size: 2rem;
font-family: "Montserrat", "Montserrat-complete", serif;

}

p.one {
font-family: "Montserrat", serif;
font-weight: 100;
}

p.two {
font-family: "Montserrat", serif;
font-weight: 900;
}

p.three {
font-family: "Montserrat-complete", serif;
font-weight: 100;
}

p.four {
font-family: "Montserrat-complete", serif;
font-weight: 900;
}
Copy link
Member

@estelle estelle Apr 3, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
p.one {
font-family: "Montserrat", serif;
font-weight: 100;
}
p.two {
font-family: "Montserrat", serif;
font-weight: 900;
}
p.three {
font-family: "Montserrat-complete", serif;
font-weight: 100;
}
p.four {
font-family: "Montserrat-complete", serif;
font-weight: 900;
}
p.one {
font-weight: 200;
}
p.two {
font-weight: 400;
}
p.three {
font-weight: 600;
}
p.four {
font-weight: 800;
}

```

#### Result

The result of this is:

- Setting the `font-weight` property to `100` for "Montserrat" gets a weight of 300.
- Setting the `font-weight` property to `900` for "Montserrat" gets a weight of 700.
- Setting the `font-weight` property to `100` for "Montserrat-complete" gets a weight of 100.
- Setting the `font-weight` property to `900` for "Montserrat-complete" gets a weight of 900.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- Setting the `font-weight` property to `100` for "Montserrat" gets a weight of 300.
- Setting the `font-weight` property to `900` for "Montserrat" gets a weight of 700.
- Setting the `font-weight` property to `100` for "Montserrat-complete" gets a weight of 100.
- Setting the `font-weight` property to `900` for "Montserrat-complete" gets a weight of 900.
- Setting the `font-weight` property to `200` for "Montserrat-complete" gets a weight of 200.
- Setting the `font-weight` property to `400` for "Montserrat" gets a weight of 400.
- Setting the `font-weight` property to `600` for "Montserrat" gets a weight of 600.
- Setting the `font-weight` property to `800` for "Montserrat-complete" gets a weight of 800.


{{embedlivesample("Setting a range for a variable font", "", "400")}}

## Specifications

{{Specifications}}
Expand Down
Loading