A variable font replaces a family of static files with one file exposing continuous axes. The registered axes are lowercase and map to ordinary properties: wght to font-weight, wdth to font-stretch, ital and slnt to font-style, opsz to font-optical-sizing. Custom axes such as GRAD (grade) are uppercase and reachable only through font-variation-settings. Its @font-face rule declares ranges such as font-weight: 100 1000.
<style>
@import "https://fonts.googleapis.com/css2?family=Roboto+Flex:\
wdth,wght,GRAD@25..151,100..1000,-200..150";
p { font: 30px "Roboto Flex", sans-serif; margin: 0 8px; }
.a { font-weight: 150; font-stretch: 151%; } .b { font-weight: 900; font-stretch: 25%; }
.c { font-variation-settings: "GRAD" 150; }
</style>
<p><span class="a">Thin and wide</span> · <span class="b">Black and condensed</span></p>
<p>Grade 0 · <span class="c">Grade 150 bolder, same width</span></p>
font-variation-settings values are not merged: a rule that sets only "GRAD" resets every other axis, so feed axes from custom properties and prefer high-level properties. To keep fonts fast:
Subset and serve WOFF2. fontTools 5,265 (github.com/fonttools/fonttools (https://github.com/fonttools/fonttools 5,265 ), pip 21,050 install fonttools brotli) strips unused glyphs: pyftsubset font.ttf --unicodes="U+0000-00FF" --flavor=woff2. Google Fonts 1 serves per-script files with unicode-range, so Latin pages skip Cyrillic.
Preload the one or two faces used above the fold: <link rel="preload" as="font" type="font/woff2" href="..." crossorigin>. crossorigin is required even for same-origin fonts, or the preload goes unused.
Pick a font-display strategy (@font-face) and match the fallback with font-size-adjust or the size-adjust and ascent-override descriptors (not yet in Safari 10 ) to reduce layout shift at the swap.