csswebfontstypographygoogle-webfonts

How to get true small-caps from a webfont from Google-fonts


I'm using the Alegreya font family from Google Fonts in a website. It seems like Google strips out the small-caps font feature, so although Alegreya has small-caps (see below), they don't seem to work with Google Fonts. How can I get true small-caps in this scenario (font from Google Fonts)?

Alegreya has true small-caps (as OpenType feature) in it, and also has a sister small-caps-only family, Alegreya SC. I've downloaded the Regular font from both families (directly from Google Fonts) and compared Alegreya-with-small-caps with Alegreya SC. They are identical, e.g., Alegreya has the same small-caps as its sister. But when I try CSS below:

.variant-smcp {
  font-family: Alegreya, serif; /* Alegreya from Google Fonts */
  font-variant: small-caps; /* should use OpenType smcp feature */
}

I only get fake small-caps (e.g., capitals shrinked by the browser).

A workaround would be to import both Alegreya and Alegreya SC, using the latter without setting any font-variant when needed. But this comes with a big problem for me: it doubles the number of requested fonts. And overall it seems a bit clumsy to import another font just for small-caps, if my font already has these baked in.

Edit: I've also tested using font-feature-settings: "smcp" on;, with exactly same result: fake small-caps, from an smcp-capable font (Alegreya). And I've tested all these things in Firefox 66 (for Windows and for Android), with exactly same result. (Thanks @Parapluie)


Solution

  • In fact you can apply true small-caps – provided they are supported.

    The main problem: the open google-fonts-API always tries to deliver the most compact font files – most importantly by delivering font subsets according to supported unicode-ranges/languages.

    To use open-type font substitution features, such as small caps, you will need an "unsubset" version of the font:

    /* standard substituted version */
    
    @font-face {
      font-family: Alegreya;
      font-weight: 400;
      src: url(https://fonts.gstatic.com/s/alegreya/v35/4UacrEBBsBhlBjvfkQjt71kZfyBzPgNG9hU4-6qj.woff2) format('woff2');
    }
    
    
    /* custom unsubstituted version */
    
    @font-face {
      font-family: Alegreya_unsubstituted;
      font-weight: 400;
      src: url('https://fonts.gstatic.com/s/alegreya/v35/4UacrEBBsBhlBjvfkQjt71kZfyBzPgNG9hUI-aCisSGVrw.woff2') format('woff2')
    }
    
    *{
    margin:0.5rem
    }
    
    body {
      font-family: sans-serif;
      font-size: 12vw;
    }
    
    h3 {
      font-size: 14px;
    }
    
    .fake_sc {
      font-family: Alegreya;
      font-variant: small-caps;
    }
    
    .sc {
      font-family: Alegreya_unsubstituted;
      font-variant: small-caps;
    }
    <h3>Fake small caps</h3>
    <p class="fake_sc">Hamburgefons</p>
    
    <h3>Proper small caps</h3>
    <p class="sc">Hamburgefons</p>

    You can retrieve complete/unsubsetted fonts from:

    Optimizations?

    Keep in mind: the small cap feature alone will inevitably increase the overall font file size (A-Z plus accented/diacritic variations). So google's decision to omit these features by default actually makes sense – albeit, we should ideally have an additional query parameter to include these substitution feature related glyphs. Maybe we'll see this feature in future versions of the API – but that's speculative.

    For more fine-grained tweaks, you need to bite the bullet and dive deeper into the realm of font software such as fontforge (free), fontlab or glyphs (commercial), or libraries such as the python-based font tools.

    Google font's text query Subsetting?

    You may think: maybe we could take advantage of the &text query parameter?

    Unfortunately, we can't as glyphs designed for open-type substitution features usually don't have individual unicode-points/values. (However this can work for symbol like glyphs which are assigned to specific unicode points (usually in the PUA-Private User Area) e.g arrows)