Difference Between Variable Fonts and Regular Fonts

Dealing with multiple font files easier

You could safely remove some older file types (unless you need the best legacy support):

Example: "Inter" - generated by google web font helper

@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 400;
src: url('fonts/inter-v11-latin-regular.eot');
src: local(''),
url('fonts/inter-v11-latin-regular.eot?#iefix') format('embedded-opentype'),
url('fonts/inter-v11-latin-regular.woff2') format('woff2'),
url('fonts/inter-v11-latin-regular.woff') format('woff'),
url('fonts/inter-v11-latin-regular.ttf') format('truetype'),
url('fonts/inter-v11-latin-regular.svg#Inter') format('svg');
}

Could be reduced to:

@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 400;
src: url('fonts/inter-v11-latin-regular.woff2') format('woff2'),
url('fonts/inter-v11-latin-regular.woff') format('woff');
}

woff should suffice as a fallback for older browsers by now. (Even supported by ie 9 - see caniuse record).

eot was exclusively used by Microsoft's Internet Explorer. If you're not developing for special cases like windows embedded system applications (depending on custom ie builds) you don't need them.

svg only supported by some legacy safari versions - ditch them.

truetype Overall probably the best browser support (widely used for desktop applications) but not as optimized for web usage (larger in file size). Might be needed for tasks like dynamic pdf generation (e.g domPdf or mPdf: most of the time you'll need to manually define embedded fonts at some point)

local better remove this rule! Especially firefox had issues displaying local fonts due to security settings.

CSS preprocessor mixin

As @Parapluie already pointed out you could use a mixin to simplify your css coding.

SCSS mixin

based on @jonathantneal gist

@mixin font-face($name, $path, $weight: null, $style: null, $exts: woff2 woff ttf otf) {
$src: null;
$formats: (
otf: "opentype",
ttf: "truetype"
);

@each $ext in $exts {
$format: if(map-has-key($formats, $ext), map-get($formats, $ext), $ext);
$src: append($src, url(quote($path + "." + $ext)) format(quote($format)), comma
);
}

@font-face {
font-family: quote($name);
font-style: $style;
font-weight: $weight;
src: $src;
}
}

@include font-face('Inter', 'fonts/Inter', 400, normal, woff2 woff ttf);
@include font-face('Inter', 'fonts/Inter', 400, italic, woff2 woff ttf);

Codepen example:

You can switch between compiled/uncompiled css view to see the output.

Variable fonts

font-face property values accept ranges like e.g for a weight range from 100–900 (light/thin to black).

@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 100 900;
src: url('https://fonts.gstatic.com/s/inter/v11/UcC73FwrK3iLTeHuS_fvQtMwCp50KnMa1ZL7W0Q5nw.woff2') format('woff2')
}

SCSS code

@include font-face('Inter VF', 'https://fonts.gstatic.com/s/inter/v11/UcC73FwrK3iLTeHuS_fvQtMwCp50KnMa1ZL7W0Q5nw', 100 900, normal, woff2);

A presumably more accurate rule would add specific variable font format values like format('woff2-variations') and format('woff2 supports variations'):

@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 100 900;
src: url('https://fonts.gstatic.com/s/inter/v11/UcC73FwrK3iLTeHuS_fvQtMwCp50KnMa1ZL7W0Q5nw.woff2') format('woff2 supports variations'),
url('https://fonts.gstatic.com/s/inter/v11/UcC73FwrK3iLTeHuS_fvQtMwCp50KnMa1ZL7W0Q5nw.woff2') format('woff2-variations');
}

Unfortunately, these declarations are not yet supported by some browsers and many documentations are outdated due to recent API changes.

So you should still test your rules in different browsers.

How to fetch google variable fonts

When using the google fonts UI you might not get the actual variable font .woff2 file.

"fonts.googleapis.com/css2?family=Inter:wght@100..900"

should work in most modern browsers:

The returned css will contain variable font file URLs

"fonts.googleapis.com/css2?family=Inter:wght@100;200;300;400;500;600;700;800;900"

(generated using the UI) will return seperate font files for each weight.

See also MDN Docs: Variable fonts guide

Variable weight version of a TTF font not working in browser

This question was asked two years ago and got the same sub-optimal answer that needed a second answer to get the W3C recommended solution.

The problem isn't that you need to use font-variation-settings, but rather that your @font-face rule didn't have a font-weight declaration.

You can use font-variation-settings, but note that that does not work well in regard to cascading. (For details and workaround, see https://pixelambacht.nl/2022/boiled-down-fixing-variable-font-inheritance/.)

For this reason, CSS specs advise against using font-variation-settings in any case where a specific property could be used.

When possible, authors should generally use the other properties related to font variations (such as font-optical-sizing), and only use this property for special cases where its use is the only way of accessing a particular infrequently used font variation.

For example, it is preferable to use font-weight: 700 rather than font-variation-settings: "wght" 700.

https://www.w3.org/TR/css-fonts-4/#font-variation-settings-def

The better solution is to add a font-weight declaration in the @font-face rule. With a variable font, you can specify two values to declare a range of weights.

HTML

<div class="w400">weight 400</div>
<div class="w500">weight 500</div>
<div class="w600">weight 600</div>
<div class="w700">weight 700</div>
<div class="w800">weight 800</div>

CSS

@font-face {
font-family: Montserrat;
/* declare weights giving two values to specify a range */
font-weight: 400 800;
src: url(Montserrat-VariableFont_wght.ttf);
}

* {
font-family: Montserrat;
}

.w400 {
font-weight: 400;
}

.w500 {
font-weight: 500;
}

.w600 {
font-weight: 600;
}

.w700 {
font-weight: 700;
}

.w800 {
font-weight: 800;
}

Addendum: It turns out the misunderstanding about needing to use font-variation-settings to access different weights in a variable font is widespread. The Web Almanac site just published its biennial analysis of font usage on the Web, and it turns out that 87% of usage of font-variation-settings is for the 'wght' axis. They observe,

This somewhat surprised us, because there is no need to use the low-level font-variation-settings property to set a custom weight axis value. You can simply use the font-weight property with a custom value, for example, font-weight: 550 for a weight between 500 and 600...

... Similar results can be seen for the optical size, width, italic, and slant axes, which can be set using the high-level font-optical-sizing, font-stretch, and font-style properties. Using the higher level properties will make your CSS more readable and avoid accidentally disabling an axis—a common source of errors with the low-level property.

How do I get a variable font axes with javascript?

Obviously, all credits to @Mike 'Pomax' Kamermans

As mentioned in his comment you can retrieve the design axes data parsing a font file with the LibFont library (the successor of font.js).

Example 1: Get all design axes info

// retrieve font data after all required assets are loaded (e.g for decompression)
window.addEventListener('DOMContentLoaded', (e) => {

// Example font: roboto flex
/* api url:
https://fonts.googleapis.com/css2?family=Roboto+Flex:opsz,slnt,wdth,wght,GRAD,XTRA,YOPQ,YTAS,YTDE,YTFI,YTLC,YTUC@8..144,-10..0,25..151,100..1000,-200..150,323..603,25..135,649..854,-305..-98,560..788,416..570,528..760*/
let fontUrl = "https://fonts.gstatic.com/s/robotoflex/v9/NaPccZLOBv5T3oB7Cb4i0zu6RME.woff2";
let fontFamily = "variable Font";
getAxisInfo(fontFamily, fontUrl);
});

function getAxisInfo(fontFamily, fontUrl) {
let font = new Font(fontFamily, {
skipStyleSheet: true
});
font.src = fontUrl;
font.onload = (evt) => {
let font = evt.detail.font;
let otTables = font.opentype.tables;
let fontname = otTables.name.get(1);

// get variable font axes
let axes = otTables.fvar.axes;
let axesInfo = [];
axes.forEach((axis, a) => {
let axisName = axis.tag;
let min = axis.minValue;
let max = axis.maxValue;
let defaultValue = axis.defaultValue;
axesInfo.push(`name:"${axisName}"; min:${min}; max:${max}; default:${defaultValue};`);

})
let fontAxisString = fontname + '\n' + axesInfo.join('\n');
fontAxisData.textContent = fontAxisString;
}
}
<!-- add brotli decompression needed for woff2 -->
<script src="https://cdn.jsdelivr.net/npm/lib-font@2.4.0/lib/unbrotli.js"></script>
<script src="https://cdn.jsdelivr.net/npm/lib-font@2.4.0/lib-font.browser.js" type="module"></script>

<pre id="fontAxisData">


Related Topics



Leave a reply



Submit