I have a simple Next.js app that I am developing on macOS (chrome) and have only noticed something is wrong when testing on Windows (chrome, and others too).
I use the font Inter from Google Fonts, nextjs + tailwind takes care of injecting needed css in <head>
:
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="" />
<link href="https://fonts.googleapis.com/css2?family=Inter&display=swap" rel="stylesheet" />
which after build translates to:
<style data-href="https://fonts.googleapis.com/css2?family=Inter&display=swap">
@font-face{font-family:'Inter';font-style:normal;font-weight:400;font-display:swap;src:url(https://fonts.gstatic.com/s/inter/v7/UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuLyfMZs.woff) format('woff')}@font-face{font-family:'Inter';font-style:normal;font-weight:400;font-display:swap;src:url(https://fonts.gstatic.com/s/inter/v7/UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuLyfAZJhjp-Ek-_EeAmM.woff) format('woff');unicode-range:U+0460-052F,U+1C80-1C88,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:'Inter';font-style:normal;font-weight:400;font-display:swap;src:url(https://fonts.gstatic.com/s/inter/v7/UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuLyfAZthjp-Ek-_EeAmM.woff) format('woff');unicode-range:U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:'Inter';font-style:normal;font-weight:400;font-display:swap;src:url(https://fonts.gstatic.com/s/inter/v7/UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuLyfAZNhjp-Ek-_EeAmM.woff) format('woff');unicode-range:U+1F00-1FFF}@font-face{font-family:'Inter';font-style:normal;font-weight:400;font-display:swap;src:url(https://fonts.gstatic.com/s/inter/v7/UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuLyfAZxhjp-Ek-_EeAmM.woff) format('woff');unicode-range:U+0370-03FF}@font-face{font-family:'Inter';font-style:normal;font-weight:400;font-display:swap;src:url(https://fonts.gstatic.com/s/inter/v7/UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuLyfAZBhjp-Ek-_EeAmM.woff) format('woff');unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+1EA0-1EF9,U+20AB}@font-face{font-family:'Inter';font-style:normal;font-weight:400;font-display:swap;src:url(https://fonts.gstatic.com/s/inter/v7/UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuLyfAZFhjp-Ek-_EeAmM.woff) format('woff');unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:'Inter';font-style:normal;font-weight:400;font-display:swap;src:url(https://fonts.gstatic.com/s/inter/v7/UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuLyfAZ9hjp-Ek-_EeA.woff) format('woff');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
</style>
and tailwind config:
theme: {
extend: {
fontFamily: {
sans: ['Inter var', ...defaultTheme.fontFamily.sans],
},
},
},
which then after build, in browsers sets following declaration to <html>
tag:
font-family:
Inter var,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji
The "Inter var" works perfectly on macOS browsers, doesn't work on Windows - it falls back to next option. When I change it to "Inter" only, it works on Windows too, but obviously, the variable font stuff is gone and everything is too thin. Rather than changing all CSS to reflect to this, why does the variable font not work on Windows? I already spend about a whole day on this and other SO posts didn't seem to work for me. Am I doing something wrong?
Due to user-agent detection, you might get static rules in some browsers – even though they support variable fonts flawlessly (e.g. chromium/blink based Opera browser). Firefox or Chrome should work perfectly.
Use the '..' range delimiter and open the css URL in firefox
https://fonts.googleapis.com/css2?family=Inter:wght@100..900
The desired variable @font-face
rules should look like this:
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 100 900;
src: url(https://fonts.gstatic.com/s/inter/v12/UcC73FwrK3iLTeHuS_fvQtMwCp50KnMa1ZL7.woff2) format('woff2');
}
Note the font-weight: 100 900
property using two values to specify a weight range – Bingo! we got the correct variable font css.
@font-face
via API css URLlet fontWeight = document.querySelector('#fontWeight');
let fontVariation = document.querySelector('#fontVariation');
let fontSamples = document.querySelectorAll('.fontSample');
fontWeight.addEventListener('change', function(e){
let value = e.target.value;
fontSamples.forEach(function(item, i){
fontSamples[i].setAttribute('style', 'font-weight:'+value);
} )
} );
fontVariation.addEventListener('change', function(e){
let value = e.target.value;
fontSamples.forEach(function(item, i){
fontSamples[i].setAttribute('style', 'font-variation-settings: \'wght\' '+value);
} )
} )
body{
font-family: georgia
}
@font-face {
src: url('https://mdn.github.io/css-examples/variable-fonts/fonts/AmstelvarAlpha-VF.woff2') format('woff2-variations');
font-family:'Amstelvar';
font-style: normal;
}
.amstelvar{
font-family: 'Amstelvar', serif;
}
.inter{
font-family: 'Inter', 'Open Sans', sans-serif;
}
h1{
font-weight: 500;
transition: 0.3s;
}
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@100..900&display=swap" rel="stylesheet">
<h1 class="fontSample inter">Hamburglefonstiv (Inter)</h1>
<h1 class="fontSample amstelvar">Hamburglefonstiv (Amstelvar)</h1>
<p>
<label>Font weight</label>
<input id="fontWeight" type="range" min="100" max="900" step="1">
</p>
<p>
<label>font-variation-settings</label>
<input id="fontVariation" type="range" min="100" max="900" step="1">
</p>
As mentioned before, this won't work in Opera (and maybe other browsers). So the above css URL
https://fonts.googleapis.com/css2?family=Inter:wght@100..900
will return the same result as:
https://fonts.googleapis.com/css2?family=Inter:wght@100;200;300;400;500;600;700;800;900
containing rules for each font-weight.
@font-face
We can copy the correct variable font-face
rule to our css.
let fontWeight = document.querySelector('#fontWeight');
let fontVariation = document.querySelector('#fontVariation');
let fontSamples = document.querySelectorAll('.fontSample');
fontWeight.addEventListener('change', function(e) {
let value = e.target.value;
fontSamples.forEach(function(item, i) {
fontSamples[i].setAttribute('style', 'font-weight:' + value);
})
});
fontVariation.addEventListener('change', function(e) {
let value = e.target.value;
fontSamples.forEach(function(item, i) {
fontSamples[i].setAttribute('style', 'font-variation-settings: \'wght\' ' + value);
})
})
body {
font-family: georgia
}
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 100 900;
src: url(https://fonts.gstatic.com/s/inter/v12/UcC73FwrK3iLTeHuS_fvQtMwCp50KnMa1ZL7.woff2) format('woff2');
}
@font-face {
src: url('https://mdn.github.io/css-examples/variable-fonts/fonts/AmstelvarAlpha-VF.woff2') format('woff2-variations');
font-family: 'Amstelvar';
font-style: normal;
}
.amstelvar {
font-family: 'Amstelvar', serif;
}
.inter {
font-family: 'Inter', 'Open Sans', sans-serif;
}
h1 {
font-weight: 500;
transition: 0.3s;
}
<h1 class="fontSample inter">Hamburglefonstiv (Inter)</h1>
<h1 class="fontSample amstelvar">Hamburglefonstiv (Amstelvar)</h1>
<p>
<label>Font weight</label>
<input id="fontWeight" type="range" min="100" max="900" step="1">
</p>
<p>
<label>font-variation-settings</label>
<input id="fontVariation" type="range" min="100" max="900" step="1">
</p>
Since the font-family name is defined just as "Inter" (without "var") in the retrieved @font-face
declaration you should also refer to it using this name:
theme: {
extend: {
fontFamily: {
sans: ['Inter', ...defaultTheme.fontFamily.sans],
},
},
},
Update as of 2024 the UI allows you to generate a variable font query. However, undestanding the creation of tuples may still be interesting if you intend to create something like a custom font selector.
Theres is currently no intuitive way to retrieve the correct parameters since the the UI is more focused on static file output.
Concatenate the URL query parameters manually:
https://fonts.googleapis.com/css2?family=
+
Inter
+
:
+ slnt
+ ,
+ wght
(design axis names)+
@
+ -10..0
+ ,
+ 100..900
(design axis range values)
let fontWeight = document.querySelector('#fontWeight');
let fontVariation = document.querySelector('#fontVariation');
let fontSamples = document.querySelectorAll('.fontSample');
fontWeight.addEventListener('change', function(e) {
let value = e.target.value;
fontSamples.forEach(function(item, i) {
fontSamples[i].setAttribute('style', 'font-weight:' + value);
})
});
fontVariation.addEventListener('change', function(e) {
let value = e.target.value;
fontSamples.forEach(function(item, i) {
fontSamples[i].setAttribute('style', 'font-variation-settings: \'slnt\' ' + value);
})
})
/* latin */
@font-face {
font-family: "Inter";
font-style: oblique 0deg 10deg;
font-weight: 100 900;
src: url(https://fonts.gstatic.com/s/inter/v12/UcCo3FwrK3iLTcviYwY.woff2) format("woff2");
}
body {
font-family: Inter;
}
.inter {
font-family: "Inter", "Open Sans", sans-serif;
}
h1 {
font-weight: 500;
transition: 0.3s;
}
<h1 class="fontSample inter">Hamburglefonstiv (Inter)</h1>
<p>
<label>Font weight</label>
<input id="fontWeight" type="range" min="100" max="900" step="1">
</p>
<p>
<label>font-slant</label>
<input id="fontVariation" type="range" min="-10" max="0" step="1" value="0">
</p>
Worth noting:
You can also style your text via font-variation-settings
property.
To change the boldness we would use:
.black{
font-variation-settings: wght 900
}
See also css-tricks.com: Getting the Most Out of Variable Fonts on Google Fonts