htmlcssfonts

Do Font Files (e.g. .ttc .ttf .otf) Contain Different Weights?


I often see projects where fonts (not from a CDN like Google Fonts) will have one font file per weight. Is this always the case?

I ask because I was sent a font file from a client (Yuanti SC, a .ttc but I converted it to otf and ttf) and I can't seem to get any other weight to show other than bold.

@font-face {
    font-family: Yuanti;
    src:  url(/fonts/yuanti.otf) format('otf'),
          url(/fonts/yuanti.ttf) format('truetype');
    font-weight: 100;
}

I wanted to make sure it's not possible (or at least unlikely) that there are multiple font weights in one font file.


Solution

  • one font file per weight. Is this always the case?

    Traditional OpenType fonts (unlike the newer variable font) only cover single weights, but: don't confuse font weights with CSS weights. Fonts can technically have any weight between 0 and 65336, and these numbers technically don't mean anything, they're just a way for a foundry to indicate what they feel appropriate for a full family (consisting of many differently weighted/modeled individual fonts).

    In regular CSS (i.e. not for variable fonts), there's an artificial restriction that there are only 9 font weights, namely 100 through 900 in increments of 100. Weight "150" doesn't mean anything in CSS, for instance, even though a font file can have a weight value 150 or 25000 in its OS/2 metadata table (which, incidentally, is called OS/2 for historical reasons only).

    If you want multiple fonts in one file, and if browsers supported font collections, then you could load those, but they don't: the way you load multiple weights is to literally load multiple fonts:

    @font-face {
      font-family: "myfont";
      font-weight: 100;
      src: url(fonts/super-bold.woff) format("woff");
    }
    
    @font-face {
      font-family: "myfont";
      font-weight: 400;
      src: url(fonts/italic.woff) format("woff");
    }
    
    @font-face {
      font-family: "myfont";
      font-weight: 900;
      src: url(fonts/ultra-thing.woff) format("woff");
    }
    

    Note what happened there: it doesn't matter what the font file itself says its font weight is: you as the stylesheet designer get to define which weight maps to which actual font resource, so if we say "in my CSS, weight 100 maps to super-bold" then the browser will do that. The CSS @font-face definition is what defines the mapping between the resource file and the CSS style/weight, not the font file.

    Normally you'd bind 100 to ultra-light, 400 to normal, and 900 to ultra-black, but this is you calling the shots, not the fonts. CSS does not respect the OpenType metadata, the @font-face binding gets the final say.

    As for why browsers don't support font collections, this has to do with which data is actually used when loading fonts. "Real" OpenType fonts (the ones you use for general purpose typesetting on your computer) come with a ton of data that is quite literally ignored when loaded as a webfont (names and contextual metadata, for instance), whereas loading a font collection would require actually parsing a lot of that data and doing resource mapping based on what is found, which doesn't just complicate the matter of figuring out which packed resource maps to what, but also requires additional code to properly handle the not-even-remotely-edge cases where overrides are necessary. "What happens if someone loads a collection but they want to keep control over which sub-resource maps to which style/weight values?".

    As such, adding collection support would complicate matters incredibly, without any real benefit: extracting a OpenType collection to individual ttf/otf fonts (both of which are OpenType fonts, they only differ in their glyph definitions; all the other data is identically encoded) and simply packing them for the web by using WOFF or WOFF2 is trivial, and leaves the designer/user with far more control over how to load those fonts, so it is unlikely we'll see collection support anytime soon.

    What about variable fonts?

    As of mid-2018 all browsers support variable fonts, which are single typefaces where the outlines are not "fixed" but use (unsurprisingly) variables to determine things like the position of outline vertices and control values. This allows a single file to encode "a single, but variable" type face. The typical example you'll see is a single typeface with a "weight" variable, effectively giving you (up to) 1000 distinct levels of boldness/lightness, but variables are arbitrary, and CSS has been updated to allow you to control any named variable in a variable font by using the font-variation-settings property.