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:

    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)