Tag: Fonts

Bunny Fonts

Bunny Fonts bills itself as the “privacy-first web font platform designed to put privacy back into the internet.”According to its FAQ:

With a zero-tracking and no-logging policy, Bunny Fonts helps you stay fully GDPR compliant and puts your user’s personal data into their own hands.

Hard for my mind not to go straight to Google Fonts. Bunny Fonts even says they are a drop-in replacement for Google Fonts. It offers the same open source fonts and holds the same API structure used by Google Fonts.

Now, I’m no GDPR expert but the possibility of Google collecting data through its Fonts API is hardly unsurprising or even unexpected. I was curious to check out Google’s privacy statement for Fonts:

The Google Fonts API logs the details of the HTTP request, which includes the timestamp, requested URL, and all HTTP headers (including referrer and user agent string) provided in connection with the use of our CSS API.

IP addresses are not logged.

Comparing that to what Bunny Fonts says in its FAQ:

When using Bunny Fonts, no personal data or logs are stored. All the requests are processed completely anonymously.

Or perhaps more thoroughly explained on the bunny.net GDPR statement:

In most cases, the data held and collected by bunny.net does not contain any user identifiable data. In some cases, which depend on how you are using bunny.net and how your website is structured, personal data may be collected from your users. Such information includes hosting user uploaded content as well as personal data that might be transmitted in the URL, User-Agent or Referer headers of the HTTP protocol.

Sounds pretty similar, right? Well, it may not have been that similar earlier this year when a German court ruled that embedded Google Fonts violated GDPR compliance. It appears that one line in the Google Fonts privacy statement about IP addresses came after the ruling, once the API scrubbed them from collected data.

So, do you need to ditch Google Fonts to be GDPR compliant? I would imagine not if IP addresses were the sole concern, but I’ll leave that for folks who know the rules to comment on that.

But if you are concerned about Google Font’s GDPR compliance, I guess Bunny Fonts is worth a look! And seeing that it’s powered by bunny.net’s CDN services, you should get pretty comparable performance marks.

To Shared LinkPermalink on CSS-Tricks

Bunny Fonts originally published on CSS-Tricks. You should get the newsletter.



Customizing Color Fonts on the Web

Myles C. Maxfield on the WebKit Blog published a nifty how-to for color fonts. It comes on the heels of what Ollie wrote up here on CSS-Tricks the other day, and while they cover a lot of common ground, there’s some nice nuggets in the WebKit post that make them both worth reading.

Case in point: there’s a little progressive enhancement in there using @supports for older browsers lacking support the font-palette property. Then the post gets into a strategy that shows the property’s light and dark values at play to make the font more legible in certain contexts. There’s also a clever idea about how creating multiple @font-palette-values blocks with the same name can be used for fallbacks.

To Shared LinkPermalink on CSS-Tricks

Customizing Color Fonts on the Web originally published on CSS-Tricks. You should get the newsletter.


, ,

Firefox’s `bolder` Default is a Problem for Variable Fonts

Variable fonts make it easy to create a large set of font styles from a single font file. Unfortunately, the default rendering of the <b> and <strong> elements in browsers today is not very compatible with the wide range of font-weight values enabled by variable fonts.

Browsers disagree on the default font-weight of <b>

The purpose of the <b> and <strong> elements is to draw attention to a specific word or span of text on the page. Browsers make these elements stand out by increasing their font-weight. This works well under normal conditions. For example, MDN Web Docs uses <b> in a few places in the “Found a problem?” card at the bottom of each page.

Screenshot of an MDN article with red arrows pointing at instances of bolded words on the page.

Things become more complicated when the text on the page has a custom font-weight. The default weight of text is 400, but the font-weight property accepts any number between 1 and 1000 (inclusive). Let’s take a look at how Chrome and Firefox render text wrapped in <b> by default depending on the font-weight of the surrounding text.

View on CodePen

Chrome and Firefox disagree on the default rendering of <b> elements. Chrome uses a constant font-weight of 700 (Safari behaves the same), while Firefox chooses between three values (400, 700, and 900) depending on the font-weight of the surrounding text.

Where is this difference coming from?

As you might have guessed, Chrome and Firefox use different font-weight values for the <b> and <strong> elements in their user agent stylesheets.

/* Chrome and Safari’s user agent stylesheet */ strong, b {   font-weight: bold; }  /* Firefox’s user agent stylesheet */ strong, b {   font-weight: bolder; }

The bold and bolder values are specified in the CSS Fonts module; bold is equivalent to 700, while bolder is a relative weight that is calculated as follows:

If the outer text has a font-weight of… the bolder keyword computes to…
1 to 349 400
350 to 549 700
550 to 899 900
900 to 1000 No change (same value as outer text)

Chrome and Firefox disagree on the default rendering of <b>, but which browser follows the standards more closely? The font-weight property itself is defined in the CSS Fonts module, but the suggested font-weight values for different HTML elements are located in the Rendering section of the HTML Standard.

/* The HTML Standard suggests the following user agent style */ strong, b {   font-weight: bolder; }

The HTML Standard started suggesting bolder instead of bold all the way back in 2012. As of today, only Firefox follows this recommendation. Chrome and Safari have not made the switch to bolder. Because of this inconsistency, the popular Normalize base stylesheet has a CSS rule that enforces bolder across browsers.

Which of the two defaults is better?

There are two different defaults in browsers, and Firefox’s default matches the standard. So, should Chrome align with Firefox, or is Chrome’s default the better one? Let’s take another look at the default rendering of the <b> element.

View on CodePen

Each of the two defaults has a weak spot: Chrome’s bold default breaks down at higher font-weight values (around 700), while Firefox’s bolder default has a problem with lower font-weight values (around 300).

In the worst-case scenario for Firefox, text wrapped in <b> becomes virtually indiscernible. The following screenshot shows text at a font-weight of 349 in Firefox. Can you spot the single word that is wrapped in <b>? Firefox renders this element at a default font-weight of 400, which is an increase of only 51 points.

Three paragraphs of text about English scientist Tim Berners-Lee. All of the text appears to be the same font weight.
(View on CodePen)

The takeaway

If you use thin fonts or variable fonts at font-weight values below 350, be aware that the <b> and <strong> elements may not always be discernible in Firefox by default. In this case, it is probably a good idea to manually define a custom font-weight for <b> and <strong> instead of relying on the browser’s sub-optimal default, which insufficiently increases the font-weight of these elements.

/* Defining the regular and bold font-weight at the same time */  body {   font-weight: 340; }  b, strong {   font-weight: 620; }

The bolder value is outdated and doesn’t work well with variable fonts. Ideally, text wrapped in <b> should be easy to spot regardless of the font-weight of the surrounding text. Browsers could achieve that by always increasing the font-weight by the same or a similar amount.

On that note, there is a discussion in the CSS Working Group about allowing percentages in font-weight in the same manner as in font-size. Lea Verou writes:

A far more common use case is when we want a bolder or lighter stroke than the surrounding text, in a way that’s agnostic to the weight of the surrounding text.

/* Increasing font-size by 100% */ h1 {   font-size: 200%; }  /* PROPOSAL - Increasing font-weight by 50% */ strong, b {   font-weight: 150%; }

Taking variable fonts into account, a value like 150% would probably be a better default than the existing bold/bolder defaults in browsers today.

The post Firefox’s `bolder` Default is a Problem for Variable Fonts appeared first on CSS-Tricks. You can support CSS-Tricks by being an MVP Supporter.


, , , , ,

A Microsite Showcasing Coding Fonts

We made one! It’s open source if you want to make it better or fix things.

There are quite a few purpose-built fonts for writing code. The point of this site is to show you some of the nicest options so you can be aware of them and perhaps pick one out to try that suites your taste.

We used screenshots of the code to display just so we could show off some of the paid fonts without managing a license just for this site, and for fonts without a clear way to link them up (like San. Also because setting up the screenshotting process was kinda fun.

High Fives

Special high five to Jonathan Land who helped a ton getting the site together including literally all the design work. Also to Sendil Kumar who had the original idea for a blog post like this, before the idea grew up into a full blown microsite. And finally to all the contributors so far.


There are still more fonts to add. If you want to add one, feel free to make a PR. Or if you’re unsure if it will be accepted or not, open an issue first. I’d like to keep any of the fonts we add fairly high quality. There is also a current bug with some of the ligatures not showing properly in the screenshots of some of the fonts. I’m sure we’ll sort it out eventually, but I’d love an assist there if you are particularly knowledgeable in that area.

Open issues here.

The post A Microsite Showcasing Coding Fonts appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.


, , ,

How to Load Fonts in a Way That Fights FOUT and Makes Lighthouse Happy

A web font workflow is simple, right? Choose a few nice-looking web-ready fonts, get the HTML or CSS code snippet, plop it in the project, and check if they display properly. People do this with Google Fonts a zillion times a day, dropping its <link> tag into the <head>.

Let’s see what Lighthouse has to say about this workflow.

Stylesheets in the <head> have been flagged by Lighthouse as render-blocking resources and they add a one-second delay to render? Not great.

We’ve done everything by the book, documentation, and HTML standards, so why is Lighthouse telling us everything is wrong?

Let’s talk about eliminating font stylesheets as a render-blocking resource, and walk through an optimal setup that not only makes Lighthouse happy, but also overcomes the dreaded flash of unstyled text (FOUT) that usually comes with loading fonts. We’ll do all that with vanilla HTML, CSS, and JavaScript, so it can be applied to any tech stack. As a bonus, we’ll also look at a Gatsby implementation as well as a plugin that I’ve developed as a simple drop-in solution for it.

What we mean by “render-blocking” fonts

When the browser loads a website, it creates a render tree from the DOM, i.e. an object model for HTML, and CSSOM, i.e. a map of all CSS selectors. A render tree is a part of a critical render path that represents the steps that the browser goes through to render a page. For browser to render a page, it needs to load and parse the HTML document and every CSS file that is linked in that HTML.

Here’s a fairly typical font stylesheet pulled directly from Google Fonts:

@font-face {   font-family: 'Merriweather';   src: local('Merriweather'), url(https://fonts.gstatic.com/...) format('woff2'); }

You might be thinking that font stylesheets are tiny in terms of file size because they usually contain, at most, a few @font-face definitions. They shouldn’t have any noticeable effect on rendering, right?

Let’s say we’re loading a CSS font file from an external CDN. When our website loads, the browser needs to wait for that file to load from the CDN and be included in the render tree. Not only that, but it also needs to wait for the font file that is referenced as a URL value in the CSS @font-face definition to be requested and loaded.

Bottom line: The font file becomes a part of the critical render path and it increases the page render delay.

Critical render path delay when loading font stylesheet and font file 
(Credit: web.dev under Creative Commons Attribution 4.0 License)

What is the most vital part of any website to the average user? It’s the content, of course. That is why content needs to be displayed to the user as soon as possible in a website loading process. To achieve that, the critical render path needs to be reduced to critical resources (e.g. HTML and critical CSS), with everything else loaded after the page has been rendered, fonts included.

If a user is browsing an unoptimized website on a slow, unreliable connection, they will get annoyed sitting on a blank screen that’s waiting for font files and other critical resources to finish loading. The result? Unless that user is super patient, chances are they’ll just give up and close the window, thinking that the page is not loading at all.

However, if non-critical resources are deferred and the content is displayed as soon as possible, the user will be able to browse the website and ignore any missing presentational styles (like fonts) — that is, if they don’t get in the way of the content.

Optimized websites render content with critical CSS as soon as possible with non-critical resources deferred. A font switch occurs between 0.5s and 1.0s on the second timeline, indicating the time when presentational styles start rendering.

The optimal way to load fonts

There’s no point in reinventing the wheel here. Harry Roberts has already done a great job describing an optimal way to load web fonts. He goes into great detail with thorough research and data from Google Fonts, boiling it all down into a four-step process:

  • Preconnect to the font file origin.
  • Preload the font stylesheet asynchronously with low priority.
  • Asynchronously load the font stylesheet and font file after the content has been rendered with JavaScript.
  • Provide a fallback font for users with JavaScript turned off.

Let’s implement our font using Harry’s approach:

<!-- https://fonts.gstatic.com is the font file origin --> <!-- It may not have the same origin as the CSS file (https://fonts.googleapis.com) --> <link rel="preconnect"       href="https://fonts.gstatic.com"       crossorigin /> 
 <!-- We use the full link to the CSS file in the rest of the tags --> <link rel="preload"       as="style"       href="https://fonts.googleapis.com/css2?family=Merriweather&display=swap" /> 
 <link rel="stylesheet"       href="https://fonts.googleapis.com/css2?family=Merriweather&display=swap"       media="print" onload="this.media='all'" /> 
 <noscript>   <link rel="stylesheet"         href="https://fonts.googleapis.com/css2?family=Merriweather&display=swap" /> </noscript>

Notice the media="print" on the font stylesheet link. Browsers automatically give print stylesheets a low priority and exclude them as a part of the critical render path. After the print stylesheet has been loaded, an onload event is fired, the media is switched to a default all value, and the font is applied to all media types (screen, print, and speech).

Lighthouse is happy with this approach!

It’s important to note that self-hosting the fonts might also help fix render-blocking issues, but that is not always an option. Using a CDN, for example, might be unavoidable. In some cases, it’s beneficial to let a CDN do the heavy lifting when it comes to serving static resources.

Even though we’re now loading the font stylesheet and font files in the optimal non-render-blocking way, we’ve introduced a minor UX issue…

Flash of unstyled text (FOUT)

This is what we call FOUT:

Why does that happen? To eliminate a render-blocking resource, we have to load it after the page content has rendered (i.e. displayed on the screen). In the case of a low-priority font stylesheet that is loaded asynchronously after critical resources, the user can see the moment the font changes from the fallback font to the downloaded font. Not only that, the page layout might shift, resulting in some elements looking broken until the web font loads.

The best way to deal with FOUT is to make the transition between the fallback font and web font smooth. To achieve that we need to:

  • Choose a suitable fallback system font that matches the asynchronously loaded font as closely as possible.
  • Adjust the font styles (font-size, line-height, letter-spacing, etc.) of the fallback font to match the characteristics of the asynchronously loaded font, again, as closely as possible.
  • Clear the styles for the fallback font once the asynchronously loaded font file has has rendered, and apply the styles intended for the newly loaded font.

We can use Font Style Matcher to find optimal fallback system fonts and configure them for any given web font we plan to use. Once we have styles for both the fallback font and web font ready, we can move on to the next step.

Merriweather is the font and Georgia is the fallback system font in this example. Once the Merriweather styles are applied, there should be minimal layout shifting and the switch between fonts should be less noticeable.

We can use the CSS font loading API to detect when our web font has loaded. Why that? Typekit’s web font loader was once one of the more popular ways to do it and, while it’s tempting to continue using it or similar libraries, we need to consider the following:

  • It hasn’t been updated for over four years, meaning that if anything breaks on the plugin side or new features are required, it’s likely no one will implement and maintain them.
  • We are already handling async loading efficiently using Harry Roberts’ snippet and we don’t need to rely on JavaScript to load the font.

If you ask me, using a Typekit-like library is just too much JavaScript for a simple task like this. I want to avoid using any third-party libraries and dependencies, so let’s implement the solution ourselves and try to make it is as simple and straightforward as possible, without over-engineering it.

Although the CSS Font Loading API is considered experimental technology, it has roughly 95% browser support. But regardless, we should provide a fallback if the API changes or is deprecated in the future. The risk of losing a font isn’t worth the trouble.

The CSS Font Loading API can be used to load fonts dynamically and asynchronously. We’ve already decided not to rely on JavaScript for something simple as font loading and we’ve solved it in an optimal way using plain HTML with preload and preconnect. We will use a single function from the API that will help us check if the font is loaded and available.

document.fonts.check("12px 'Merriweather'");

The check() function returns true or false depending on whether the font specified in the function argument is available or not. The font size parameter value is not important for our use case and it can be set to any value. Still, we need to make sure that:

  • We have at least one HTML element on a page that contains at least one character with web font declaration applied to it. In the examples, we will use the &nbsp; but any character can do the job as long it’s hidden (without using display: none;) from both sighted and non-sighted users. The API tracks DOM elements that have font styles applied to them. If there are no matching elements on a page, then the API isn’t be able to determine if the font has loaded or not.
  • The specified font in the check() function argument is exactly what the font is called in the CSS.

I’ve implemented the font loading listener using CSS font loading API in the following demo. For example purposes, loading fonts and the listener for it are initiated by clicking the button to simulate a page load so you can see the change occur. On regular projects, this should happen soon after the website has loaded and rendered.

Isn’t that awesome? It took us less than 30 lines of JavaScript to implement a simple font loading listener, thanks to a well-supported function from the CSS Font Loading API. We’ve also handled two possible edge cases in the process:

  • Something goes wrong with the API, or some error occurs preventing the web font from loading.
  • The user is browsing the website with JavaScript turned off.

Now that we have a way to detect when the font file has finished loading, we need to add styles to our fallback font to match the web font and see how to handle FOUT more effectively.

The transition between the fallback font and web font looks smooth and we’ve managed to achieve a much less noticeable FOUT! On a complex site, this change would result in a fewer layout shifts, and elements that depend on the content size wouldn’t look broken or out of place.

What’s happening under the hood

Let’s take a closer look at the code from the previous example, starting with the HTML. We have the snippet in the <head> element, allowing us to load the font asynchronously with preload, preconnect, and fallback.

<body class="no-js">   <!-- ... Website content ... -->   <div aria-visibility="hidden" class="hidden" style="font-family: '[web-font-name]'">       /* There is a non-breaking space here here */   </div>   <script>      document.getElementsByTagName("body")[0].classList.remove("no-js");   </script> </body>

Notice that we have a hardcoded .no-js class on the <body> element, which is removed the moment the HTML document has finished loading. This applies webfont styles for users with JavaScript disabled.

Secondly, remember how the CSS Font Loading API requires at least one HTML element with a single character to track the font and apply its styles? We added a <div> with a &nbsp; character that we are hiding from both sighted and non-sighted users in an accessible way, since we cannot use display: none;. This element has an inlined font-family: 'Merriweather' style. This allows us to smoothly switch between the fallback styles and loaded font styles, and make sure that all font files are properly tracked, regardless of whether they are used on the page or not.

Note that the &nbsp; character is not showing up in the code snippet but it is there!

The CSS is the most straightforward part. We can utilize the CSS classes that are hardcoded in the HTML or applied conditionally with JavaScript to handle various font loading states.

body:not(.wf-merriweather--loaded):not(.no-js) {   font-family: [fallback-system-font];   /* Fallback font styles */ } 
 .wf-merriweather--loaded, .no-js {   font-family: "[web-font-name]";   /* Webfont styles */ } 
 /* Accessible hiding */ .hidden {   position: absolute;    overflow: hidden;    clip: rect(0 0 0 0);    height: 1px;   width: 1px;    margin: -1px;   padding: 0;   border: 0;  }

JavaScript is where the magic happens. As described previously, we are checking if the font has been loaded by using the CSS Font Loading API’s check() function. Again, the font size parameter can be any value (in pixels); it’s the font family value that needs to match the name of the font that we’re loading.

var interval = null; 
 function fontLoadListener() {   var hasLoaded = false; 
   try {     hasLoaded = document.fonts.check('12px "[web-font-name]"')   } catch(error) {     console.info("CSS font loading API error", error);     fontLoadedSuccess();     return;   }      if(hasLoaded) {     fontLoadedSuccess();   } } 
 function fontLoadedSuccess() {   if(interval) {     clearInterval(interval);   }   /* Apply class names */ } 
 interval = setInterval(fontLoadListener, 500);

What’s happening here is we’re setting up our listener with fontLoadListener() that runs at regular intervals. This function should be as simple as possible so it runs efficiently within the interval. We are using the try-catch block to handle any errors and catch any issues so that web font styles still apply in the case of a JavaScript error so that the user doesn’t experience any UI issues.

Next, we’re accounting for when the font successfully loads with fontLoadedSuccess(). We need to make sure to first clear the interval so the check doesn’t unnecessarily run after it.  Here we can add class names that we need in order to apply the web font styles.

And, finally, we are initiating the interval. In this example, we’ve set it up to 500ms, so the function runs twice per second.

Here’s a Gatsby implementation

Gatsby does a few things that are different compared to vanilla web development (and even the regular create-react-app tech stack) which makes implementing what we’ve covered here a bit tricky.

To make this easy, we’ll develop a local Gatsby plugin, so all code that is relevant to our font loader is located at plugins/gatsby-font-loader in the example below.

Our font loader code and config will be split across the three main Gatsby files:

  • Plugin configuration (gatsby-config.js): We’ll include the local plugin in our project, list all local and external fonts and their properties (including the font name, and the CSS file URL), and include all preconnect URLs.
  • Server-side code (gatsby-ssr.js): We’ll use the config to generate and include preload and preconnect tags in the HTML <head> using setHeadComponents function from Gatsby’s API. Then, we’ll generate the HTML snippets that hide the font and include them in HTML using setPostBodyComponents.
  • Client-side code (gatsby-browser.js): Since this code runs after the page has loaded and after React starts up, it is already asynchronous. That means we can inject the font stylesheet links using react-helmet. We’ll also start a font loading listener to deal with FOUT.

You can check out the Gatsby implementation in the following CodeSandbox example.

I know, some of this stuff is complex. If you just want a simple drop-in solution for performant, asynchronous font loading and FOUT busting, I’ve developed a gatsby-omni-font-loader plugin just for that. It uses the code from this article and I am actively maintaining it. If you have any suggestions, bug reports, or code contributions, feel free to submit them on on GitHub.


Content is perhaps the most component to a user’s experience on a website. We need to make sure content gets top priority and loads as quickly as possible. That means using bare minimum presentation styles (i.e. inlined critical CSS) in the loading process. That is also why web fonts are considered non-critical in most cases — the user can still consume the content without them — so it’s perfectly fine for them to load after the page has rendered.

But that might lead to FOUT and layout shifts, so the font loading listener is needed to make a smooth switch between the fallback system font and the web font.

I’d like to hear your thoughts! Let me know in the comments how are you tackling the issue of web font loading, render-blocking resources and FOUT on your projects.


The post How to Load Fonts in a Way That Fights FOUT and Makes Lighthouse Happy appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.


, , , , , ,

Getting the Most Out of Variable Fonts on Google Fonts

I have spent the past several years working (alongside a bunch of super talented people) on a font family called Recursive Sans & Mono, and it just launched officially on Google Fonts!

Wanna try it out super fast? Here’s the embed code to use the full Recursive variable font family from Google Fonts (but you will get a lot more flexibility & performance if you read further!)

<link href="https://fonts.googleapis.com/css2?family=Recursive:slnt,wght,CASL,CRSV,MONO@-15..0,300..1000,0..1,0..1,0..1&display=swap" rel="stylesheet">

Recursive is made for code, websites, apps, and more.
Recursive Mono has both Linear and Casual styles for different “voices” in code, along with cursive italics if you want them — plus a wider weight range for monospaced display typography.

Recursive Sans is proportional, but unlike most proportional fonts, letters maintain the same width across styles for more flexibility in UI interactions and layout.

I started Recursive as a thesis project for a type design masters program at KABK TypeMedia, and when I launched my type foundry, Arrow Type, I was subsequently commissioned by Google Fonts to finish and release Recursive as an open-source, OFL font.

You can see Recursive and learn more about it what it can do at recursive.design

Recursive is made to be a flexible type family for both websites and code, where its main purpose is to give developers and designers some fun & useful type to play with, combining fresh aesthetics with the latest in font tech.

First, a necessary definition: variable fonts are font files that fit a range of styles inside one file, usually in a way that allows the font user to select a style from a fluid range of styles. These stylistic ranges are called variable axes, and can be parameters, like font weight, font width, optical size, font slant, or more creative things. In the case of Recursive, you can control the “Monospacedness” (from Mono to Sans) and “Casualness” (between a normal, linear style and a brushy, casual style). Each type family may have one or more of its own axes and, like many features of type, variable axes are another design consideration for font designers.

You may have seen that Google Fonts has started adding variable fonts to its vast collection. You may have read about some of the awesome things variable fonts can do. But, you may not realize that many of the variable fonts coming to Google Fonts (including Recursive) have a lot more stylistic range than you can get from the default Google Fonts front end.

Because Google Fonts has a huge range of users — many of them new to web development — it is understandable that they’re keeping things simple by only showing the “weight” axis for variable fonts. But, for fonts like Recursive, this simplification actually leaves out a bunch of options. On the Recursive page, Google Fonts shows visitors eight styles, plus one axis. However, Recursive actually has 64 preset styles (also called named instances), and a total of five variable axes you can adjust (which account for a slew of more potential custom styles).

Recursive can be divided into what I think of as one of four “subfamilies.” The part shown by Google Fonts is the simplest, proportional (sans-serif) version. The four Recursive subfamilies each have a range of weights, plus Italics, and can be categorized as:

  • Sans Linear: A proportional, “normal”-looking sans-serif font. This is what gets shown on the Google Fonts website.
  • Sans Casual: A proportional “brush casual” font
  • Mono Linear: A monospace “normal” font
  • Mono Casual: A monospace “brush casual” font

This is probably better to visualize than to describe in words. Here are two tables (one for Sans, the other for Mono) showing the 64 named instances:

But again, the main Google Fonts interface only provides access to eight of those styles, plus the Weight axis:

Recursive has 64 preset styles — and many more using when using custom axis settings — but Google Fonts only shows eight of the preset styles, and just the Weight axis of the five available variable axes.

Not many variable fonts today have more than a Weight axis, so this is an understandable UX choice in some sense. Still, I hope they add a little more flexibility in the future. As a font designer & type fan, seeing the current weight-only approach feels more like an artificial flattening than true simplification — sort of like if Google Maps were to “simplify” maps by excluding every road that wasn’t a highway.

Luckily, you can still access the full potential of variable fonts hosted by Google Fonts: meet the Google Fonts CSS API, version 2. Let’s take a look at how you can use this to get more out of Recursive.

But first, it is helpful to know a few things about how variable fonts work.

How variable fonts work, and why it matters

If you’ve ever worked with photos on the web then you know that you should never serve a 9,000-pixel JPEG file when a smaller version will do. Usually, you can shrink a photo down using compression to save bandwidth when users download it.

There are similar considerations for font files. You can often reduce the size of a font dramatically by subsetting the characters included in it (a bit like cropping pixels to just leave the area you need). You can further compress the file by converting it into a WOFF2 file (which is a bit like running a raster image file though an optimizer tool like imageOptim). Vendors that host fonts, like Google Fonts, will often do these things for you automatically.

Now, think of a video file. If you only need to show the first 10 seconds of a 60-second video, you could trim the last 50 seconds to have a much small video file. 

Variable fonts are a bit like video files: they have one or more ranges of information (variable axes), and those can often either be trimmed down or “pinned” to a certain location, which helps to reduce file size. 

Of course, variable fonts are nothing like video files. Fonts record each letter shape in vectors, (similar to SVGs store shape information). Variable fonts have multiple “source locations” which are like keyframes in an animation. To go between styles, the control points that make up letters are mathematically interpolated between their different source locations (also called deltas). A font may have many sets of deltas (at least one per variable axis, but sometimes more). To trim a variable font, then, you must trim out unneeded deltas.

As a specific example, the Casual axis in Recursive takes letterforms from “Linear” to “Casual” by interpolating vector control points between two extremes: basically, a normal drawing and a brushy drawing. The ampersand glyph animation below shows the mechanics in action: control points draw rounded corners at one extreme and shift to squared corners on the other end.

Generally, each added axis doubles the number of drawings that must exist to make a variable font work. Sometimes the number is more or less – Recursive’s Weight axis requires 3 locations (tripling the number of drawings), while its Cursive axis doesn’t require extra locations at all, but actually just activates different alternate glyphs that already exist at each location. But, the general math is: if you only use opt into fewer axes of a variable font, you will usually get a smaller file.

When using the Google Fonts API, you are actually opting into each axis. This way, instead of starting with a big file and whittling it down, you get to pick and choose the parts you want.

Variable axis tags

If you’re going to use the Google Fonts API, you first need to know about font axes abbreviations so you can use them yourself.

Variable font axes have abbreviations in the form of four-letter “tags.” These are lowercase for industry-standard axes and uppercase for axes invented by individual type designers (also called “custom” or “private” axes). 

There are currently five standard axes a font can include: 

  • wght – Weight, to control lightness and boldness
  • wdth – Width, to control overall letter width
  • opsz – Optical Size, to control adjustments to design for better readability at various sizes
  • ital – Italic, generally to switch between separate upright/italic designs
  • slnt – Slant, generally to control upright-to-slanted designs with intermediate values available

Custom axes can be almost anything. Recursive includes three of them — Monospace (MONO), Casual (CASL), and Cursive (CRSV)  — plus two standard axes, wght and slnt.

Google Fonts API basics

When you configure a font embed from the Google Fonts interface, it gives you a bit of HTML or CSS which includes a URL, and this ultimately calls in a CSS document that includes one or more @font-face rules. This includes things like font names as well as links to font files on Google servers.

This URL is actually a way of calling the Google Fonts API, and has a lot more power than you might realize. It has a few basic parts: 

  1. The main URL, specifying the API (https://fonts.googleapis.com/css2)
  2. Details about the fonts you are requesting in one or more family parameters
  3. A font-display property setting in a display parameter

As an example, let’s say we want the regular weight of Recursive (in the Sans Linear subfamily). Here’s the URL we would use with our CSS @import:

@import url('https://fonts.googleapis.com/css2?family=Recursive&display=swap');

Or we can link it up in the <head> of our HTML:

<link href="https://fonts.googleapis.com/css2?family=Recursive&display=swap" rel="stylesheet">

Once that’s in place, we can start applying the font in CSS:

body {   font-family: 'Recursive', sans-serif; }

There is a default value for each axis:

  • MONO 0 (Sans/proportional)
  • CASL 0 (Linear/normal)
  • wght 400 (Regular)
  • slnt 0 (upright)
  • CRSV 0 (Roman/non-cursive lowercase)

Choose your adventure: styles or axes

The Google Fonts API gives you two ways to request portions of variable fonts:

  1. Listing axes and the specific non-default values you want from them
  2. listing axes and the ranges you want from them

Getting specific font styles

Font styles are requested by adding parameters to the Google Fonts URL. To keep the defaults on all axes but use get a Casual style, you could make the query Recursive:CASL@1 (this will serve Recursive Sans Casual Regular). To make that Recursive Mono Casual Regular, specify two axes before the @ and then their respective values (but remember, custom axes have uppercase tags):


To request both Regular and Bold, you would simply update the family call to Recursive:wght@400;700, adding the wght axis and specific values on it:


A very helpful thing about Google Fonts is that you can request a bunch of individual styles from the API, and wherever possible, it will actually serve variable fonts that cover all of those requested styles, rather than separate font files for each style. This is true even when you are requesting specific locations, rather than variable axis ranges — if they can serve a smaller font file for your API request, they probably will.

As variable fonts can be trimmed more flexibility and efficiently in the future, the files served for given API requests will likely get smarter over time. So, for production sites, it may be best to request exactly the styles you need.

Where it gets interesting, however, is that you can also request variable axes. That allows you to retain a lot of design flexibility without changing your font requests every time you want to use a new style.

Getting a full variable font with the Google Fonts API

The Google Fonts API seeks to make fonts smaller by having users opt into only the styles and axes they want. But, to get the full benefits of variable fonts (more design flexibility in fewer files), you should use one or more axes. So, instead of requesting single styles with Recursive:wght@400;700, you can instead request that full range with Recursive:wght@400..700 (changing from the ; to .. to indicate a range), or even extending to the full Recursive weight range with Recursive:wght@300..1000 (which adds very little file size, but a whole lot of extra design oomph).

You can add additional axes by listing them alphabetically (with lowercase standard axes first, then uppercase custom axes) before the @, then specifying their values or ranges after that in the same order. For instance, to add the MONO axis and the wght axis, you could use Recursive:wght,MONO@300..1000,0..1 as the font query.

Or, to get the full variable font, you could use the following URL:


Of course, you still need to put that into an HTML link, like this:

<link href="https://fonts.googleapis.com/css2?family=Recursive:slnt,wght,CASL,CRSV,MONO@-15..0,300..1000,0..1,0..1,0..1&display=swap" rel="stylesheet">

Customizing it further to balance flexibility and filesize 

While it can be tempting to use every single axis of a variable font, it’s worth remembering that each additional axis adds to the overall files ize. So, if you really don’t expect to use an axis, it makes sense to leave it off. You can always add it later.

Let’s say you want Recursive’s Mono Casual styles in a range of weights,. You could use Recursive:wght,CASL,MONO@300..1000,1,1 like this:

<link href="https://fonts.googleapis.com/css2?family=Recursive:CASL,MONO,wght@1,1,300..1000&display=swap" rel="stylesheet">

You can, of course, add multiple font families to an API call with additional family parameters. Just be sure that the fonts are alphabetized by family name.

<link href="https://fonts.googleapis.com/css2?family=Inter:slnt,wght@-10..0,100..900?family=Recursive:CASL,MONO,wght@1,1,300..1000&display=swap" rel="stylesheet">

Using variable fonts

The standard axes can all be controlled with existing CSS properties. For instance, if you have a variable font with a weight range, you can specify a specific weight with font-weight: 425;. A specific Slant can be requested with font-style: oblique 9deg;. All axes can be controlled with font-variation-settings. So, if you want a Mono Casual very-heavy style of Recursive (assuming you have called the full family as shown above), you could use the following CSS:

body {  font-weight: 950;  font-variation-settings: 'MONO' 1, 'CASL' 1; }

Something good to know: font-variation-settings is much nicer to use along with CSS custom properties

Another useful thing to know is that, while you should be able to activate slant with font-style: italic; or font-style: oblique Xdeg;, browser support for this is inconsistent (at least at the time of this writing), so it is useful to utilize font-variation-settings for the Slant axis, as well.

You can read more specifics about designing with variable fonts at VariableFonts.io and in the excellent collection of CSS-Tricks articles on variable fonts.

Nerdy notes on the performance of variable fonts

If you were to using all 64 preset styles of Recursive as separate WOFF2 files (with their full, non-subset character set), it would be total of about 6.4 MB. By contrast, you could have that much stylistic range (and everything in between) at just 537 KB. Of course, that is a slightly absurd comparison — you would almost never actually use 64 styles on a single web page, especially not with their full character sets (and if you do, you should use subsets and unicode-range).

A better comparison is Recursive with one axis range versus styles within that axis range. In my testing, a Recursive WOFF2 file that’s subset to the “Google Fonts Latin Basic” character set (including only characters to cover English and western European languages), including the full 300–1000 Weight range (and all other axes “pinned” to their default values) is 60 KB. Meanwhile, a single style with the same subset is 25 KB. So, if you use just three weights of Recursive, you can save about 15 KB by using the variable font instead of individual files.

The full variable font as a subset WOFF2 clocks in at 281 KB which is kind of a lot for a font, but not so much if you compare it to the weight of a big JPEG image. So, if you assume that individual styles are about 25 KB, if you plan to use more than 11 styles, you would be better off using the variable font.

This kind of math is mostly an academic exercise for two big reasons:

  1. Variable fonts aren’t just about file size.The much bigger advantage is that they allow you to just design, picking the exact font weights (or other styles) that you want. Is a font looking a little too light? Bump up the font-weight a bit, say from 400 to 425!
  2. More importantly (as explained earlier), if you request variable font styles or axes from Google Fonts, they take care of the heavy lifting for you, sending whatever fonts they deem the most performant and useful based on your API request and the browsers visitors access your site from.

So, you don’t really need to go downloading fonts that the Google Fonts API returns to compare their file sizes. Still, it’s worth understanding the general tradeoffs so you can best decide when to opt into the variable axes and when to limit yourself to a couple of styles.

What’s next?

Fire up CodePen and give the API a try! For CodePen, you will probably want to use the CSS @import syntax, like this in the CSS panel:

@import url('https://fonts.googleapis.com/css2?family=Recursive:CASL,CRSV,MONO,slnt,wght@0..1,0..1,0..1,-15..0,300..1000&display=swap');

It is apparently better to use the HTML link syntax to avoid blocking parallel downloads of other resources. In CodePen, you’d crack open the Pen settings, select HTML, then drop the <link> in the HTML head settings.

Or, hey, you can just fork my CodePen and experiment there:

Take an API configuration shortcut

If you are want to skip the complexity of figuring out exact API calls and looking to opt into variable axes of Recursive and make semi-advanced API calls, I have put together a simple configuration tool on the Recursive minisite (click the “Get Recursive” button). This allows you to quickly select pinned styles or variable ranges that you want to use, and even gives estimates for the resulting file size. But, this only exposes some of the API’s functionality, and you can get more specific if you want. It’s my attempt to get people using the most stylistic range in the smallest files, taking into account the current limitations of variable font instancing.

Use Recursive for code

Also, Recursive is actually designed first as a font to use for code. You can use it on CodePen via your account settings. Better yet, you can download and use the latest Recursive release from GitHub and set it up in any code editor.

Explore more fonts!

The Google Fonts API doc helpfully includes a (partial) list of variable fonts along with details on their available axis ranges. Some of my favorites with axes beyond just Weight are Crimson Pro (ital, wght), Work Sans (ital, wght), Encode Sans (wdth, wght), and Inter (slnt, wght). You can also filter Google Fonts to show only variable fonts, though most of these results have only a Weight axis (still cool and useful, but don’t need custom URL configuration).

Some more amazing variable fonts are coming to Google Fonts. Some that I am especially looking forward to are:

  • Fraunces: “A display, “Old Style” soft-serif typeface inspired by the mannerisms of early 20th century typefaces such as Windsor, Souvenir, and the Cooper Series”
  • Roboto Flex: Like Roboto, but withan extensive ranges of Weight, Width, and Optical Size
  • Crispy: A creative, angular, super-flexible variable display font
  • Science Gothic: A squarish sans “based closely on Bank Gothic, a typeface from the early 1930s—but a lowercase, design axes, and language coverage have been added”

And yes, you can absolutely download and self-host these fonts if you want to use them on projects today. But stay tuned to Google Fonts for more awesomely-flexible typefaces to come!

Of course, the world of type is much bigger than open-source fonts. There are a bunch of incredible type foundries working on exciting, boundary-pushing fonts, and many of them are also exploring new & exciting territory in variable fonts. Many tend to take other approaches to licensing, but for the right project, a good typeface can be an extremely good value (I’m obviously biased, but for a simple argument, just look at how much typography strengthens brands like Apple, Stripe, Google, IBM, Figma, Slack, and so many more). If you want to feast your eyes on more possibilities and you don’t already know these names, definitely check out DJR, OHno, Grilli, XYZ, Dinamo, Typotheque, Underware, Bold Monday, and the many very-fun WIP projects on Future Fonts. (I’ve left out a bunch of other amazing foundries, but each of these has done stuff I particularly love, and this isn’t a directory of type foundries.)

Finally, some shameless plugs for myself: if you’d like to support me and my work beyond Recursive, please consider checking out my WIP versatile sans-serif Name Sans, signing up for my (very) infrequent newsletter, and giving me a follow on Instagram.

The post Getting the Most Out of Variable Fonts on Google Fonts appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.


, , , ,

The Fastest Google Fonts

When you use font-display: swap;, which Google Fonts does when you use the default &display=swap part of the URL , you’re already saying, “I’m cool with FOUT,” which is another way of saying web text is displayed right away, and when the web font is ready, “swap” to it.

There is already an async nature to what you are doing, so you might as well extend that async-ness to the rest of the font loading. Harry Roberts:

If you’re going to use font-display for your Google Fonts then it makes sense to asynchronously load the whole request chain.

Harry’s recommended snippet:

<link rel="preconnect"       href="https://fonts.gstatic.com"       crossorigin />  <link rel="preload"       as="style"       href="$  CSS&display=swap" />  <link rel="stylesheet"       href="$  CSS&display=swap"       media="print" onload="this.media='all'" />

$ CSS is the main part of the URL that Google Fonts gives you.

Looks like a ~20% render time savings with no change in how it looks/feels when loading/. Other than that, it’s faster.

Direct Link to ArticlePermalink

The post The Fastest Google Fonts appeared first on CSS-Tricks.


, ,

Chrome + System Fonts Snafu

There was just a bug late last year where system fonts (at least on Mac, I don’t know what the story was on other platforms) in Chrome appeared too thin and tracked-in at small sizes and too thick and tracked-out at larger sizes. That one was fixed, thankfully. But while it was a problem, it was the reason I gave up on system fonts for now and switched something else. A performance loss but aesthetic gain.

Now there is a new much worse bug, where the system font can’t be bolded. It’s not great, as a ton of sites roll with the system font stack as it has two major benefits: 1) it can help your site look like the operating system 2) it has great performance as the site doesn’t need to download/display and custom fonts.

Jon Henshaw wrote it up:

… the bug caught the attention of Adam Argyle, maker of VisBug and Chrome CSS Developer Advocate at Google. Argyle created a Chromium bug report, but the Chromium development team ultimately decided it wasn’t a blocker for releasing version 81. That resulted in sites like Coywolf not being able to use bold text for fonts that are larger than 16px (e.g., every heading).

The bug won’t be fixed in version 82 because the Chromium team announced that they’re skipping it, and will be releasing version 83 in mid-May instead. Argyle assured everyone on the original GitHub bug report that it would be fixed in version 83.

Above is Jon’s site. Andy Bell’s site got hit by it too.

So we’re looking at 4 weeks or so. Adam proposed a temporary fix of going Helvetica for now:

body {   font-family: -apple-system, Helvetica; }

I guess with -apple-system in there, older versions of Chrome/macOS still might be able to benefit from system fonts? Not sure.

That brings up a source of confusion for me. When I first heard of using system font stacks, there was -apple-system and BlinkMacSystemFont and you were supposed to use them in that order in the font stack. Then came along -system-ui, and that seemed to work well all by itself and that was nice as it was obviously less Mac-specific. But there is also system-ui (no starting dash), and that seems to do the same thing and I’m not sure which is correct. Now it looks like the plan is ui-sans-serif and friends (like ui-serif and ui-monospace). I like the idea, but I’d love to hear clarity from browser vendors on what the recommended use is. Are we in a spot like this?

/* Just a guess... */ body {   font-family:      ui-sans-serif,      system-ui,      -system-ui,      -apple-system,     BlinkMacSystemFont,     Roboto, Helvetica, Arial,      sans-serif,      "Apple Color Emoji"; }

Another observation from me… as I was trying to replicate this on Chrome 81, at first I was like “weird, works for me”, because I was trying out the bolding on default 16px text. I noticed that it was when the font was 20px or bigger the problem kicked in:

Bramus has an alternative fix idea: use Inter.

The post Chrome + System Fonts Snafu appeared first on CSS-Tricks.


, , ,

Dark mode and variable fonts

Not so long ago, we wrote about dark mode in CSS and I’ve been thinking about how white text on a black background is pretty much always harder to read than black text on a white background. After thinking about this for a while, I realized that we can fix that problem by making the text thinner in dark mode using variable fonts!

Here’s an example of the problem where I’m using the typeface Yanone Kaffeesatz from Google Fonts. Notice that the section with white text on a black background looks heavier than the section with black text on a white background.

Oddly enough, these two bits of text are actually using the same font-weight value of 400. But to my eye, the white text looks extra bold on a black background.

Stare at this example for a while. This is just how white text looks on a darker background; it’s how our eyes perceive shapes and color. And this might not be a big issue in some cases but reading light text on a dark background is always way more difficult for readers. And if we don’t take care designing text in a dark mode context, then it can feel as if the text is vibrating as we read it.

How do we fix this?

Well, this is where variable fonts come in! We can use a lighter font weight to make the text easier to read whenever dark mode is active:

body {   font-weight: 400; }  @media (prefers-color-scheme: dark) {   body {     font-weight: 350;   } }

Here’s how that looks with this new example:

This is better! The two variants now look a lot more balanced to me.

Again, it’s only a small difference, but all great designs consist of micro adjustments like this. And I reckon that, if you’re already using variable fonts and loading all these weights, then you should definitely adjust the text so it’s easier to read.

This effect is definitely easier to spot if we compare the differences between longer paragraphs of text. Here we go, this time in Literata:

Notice that the text on the right feels bolder, but it just isn’t. It’s simply an optical allusion — both examples above have a font-weight of 500.

So to fix this issue we can do the same as the example above:

body {   font-weight: 500; }  @media (prefers-color-scheme: dark) {   body {     font-weight: 400;   } }

Again, it’s a slight change but it’s important because at these sizes every typographic improvement we make helps the reading experience.

Oh and here’s a quick Google fonts tip!

Google Fonts lets you can add a font to your website by adding a <link> in the <head> of the document, like this:

<head>   <link href="https://fonts.googleapis.com/css2?family=Rosario:wght@515&display=swap" rel="stylesheet">  </head>

That’s using the Rosario typeface and adding a font-weight of 515 — that’s the bit in the code above that says wght@515. Even if this happens to be a variable font, 515 only this font weight that’s downloaded. If we try to do something like this:

body {   font-weight: 400; }

…nothing will happen! In fact, the font won’t load at all. Instead, we need to declare which range of font-weight values we want by doing the following:

<link href="https://fonts.googleapis.com/css2?family=Yanone+Kaffeesatz:wght@300..500&display=swap" rel="stylesheet">

This @300..500 bit in the code above is what tells Google Fonts to download a font file with all the weights between 300 and 500. Alternatively, adding a ; between each weight will then only download weights 300 and 500 – so, for example, you can’t pick weight 301:

<link href="https://fonts.googleapis.com/css2?family=Yanone+Kaffeesatz:wght@300;500&display=swap" rel="stylesheet">

It took me a few minutes to figure out what was going wrong and why the font wasn’t loading at all, so hopefully the Google Fonts team can make that a bit clearer with the embed codes in the future. Perhaps there should be an option or a toggle somewhere to select a range or specific weights (or maybe I just didn’t see it).

Either way, I think all this is why variable fonts can be so gosh darn helpful; they allow us to adjust text in ways that we’ve never been able to do before. So, yay for variable fonts!

The post Dark mode and variable fonts appeared first on CSS-Tricks.


, , ,

Considerations When Choosing Fonts for a Multilingual Website

As a front-end developer working for clients all over the world, I’ve always struggled to deal with multilingual websites — especially cases where both right-to-left (RTL) and left-to-right (LTR) are used. That said, I’ve learned a few things along the way and am going to share a few tips in this post.

Let’s work in Arabic and English, not just because Arabic is my native language, but because it’s a classic example of RTL in use.

Adding RTL support to a site

Before this though, we’ll want to add support for an RTL language on our site. There are two ways we can go about this, both of which aren’t exactly ideal.

Not ideal: Use a specific font for each direction

The first way we could go about this is to rely on the direction (dir) attribute on any given element (which is usually the <html> element so it sets the direction globally):

/* For LTR, use Roboto */ [dir=ltr] body {   font-family: "Roboto", sans-serif; }  /* For RTL, use Amiri */ [dir=rtl] body {   font-family: "Amiri", sans-serif; }

PostCSS-RTL makes it even easier to generate styles for each direction, but the issue with this method is that you are only using one font which is not ideal if you have multiple languages in one paragraph.

Here’s why. You’ll find that multi-lingual paragraphs mess up the UI because the Arabic glyphs are given a default font that doesn’t align with the element.

It might be worse in some browsers over others.

Also not ideal: Use one single font that supports both languages

The second option could be using fonts that offer support for both directions. However, in my personal experience, using just one font for both languages limits creativity and freedom to use a different font for each direction. It might not be that bad, depending on the design requirements. But I’ve definitely worked on projects where it makes a difference.

OK, so what then?

We need a simpler solution. According to MDN:

Font selection does not simply stop at the first font in the list that is on the user’s system. Rather, font selection is done one character at a time, so that if an available font does not have a glyph for a needed character, the latter fonts are tried.

Meaning, we can still use the font-family property but using a fallback in cases where the first font doesn’t have a glyph for a character. This actually solves both of the issues above, two birds with one stone style!

body {   font-family: 'Roboto', 'Amiri', 'Galada', sans-serif; }

Why does this work?

Just like the way flexbox and CSS grid, make CSS layouts a lot more flexible, the font matching algorithm makes it even easier to work with content in different languages. Here’s what W3C says about it matching characters to fonts:

When text contains characters such as combining marks, ideally the base character should be rendered using the same font as the mark, this assures proper placement of the mark. For this reason, the font matching algorithm for clusters is more specialized than the general case of matching a single character by itself. For sequences containing variation selectors, which indicate the precise glyph to be used for a given character, user agents always attempt system font fallback to find the appropriate glyph before using the default glyph of the base character.

(Emphasis mine)

And how are fonts matched? The spec outlines the steps the algorithm takes, which I’ll paraphrase here.

  • The browser looks at a cluster of text and tries to match it to the list of fonts that are declared in CSS.
  • If it finds a font that supports all of the characters, great! That’s what gets used.
  • If the browser doesn’t find a font that supports all of the characters, it re-reads the list of fonts to find one that supports the unmatched characters and applies it to those specific characters. 
  • If the browser doesn’t find a font in the list that matches neither all of the characters in the cluster nor individual ones, then it reaches for the default system font and checks that it supports all of the characters.
  • If the default system font matches, again, great! That’s what gets used.
  • If the system font doesn’t work, that’s where the browser renders a broken glyph.

Let’s talk performance

The sequence we just looked at could be taxing on a site’s performance. Imagine the browser having to loop through every defined fallback, match specific characters to glyphs, and download font files based on what it finds. That can add up to a lot of work, not to mention FOUT and other rendering weirdness.

The goal is to let the font matching algorithm decide which font to apply to each text instead of relying on one font for both languages or adding extra CSS to handle different directions. If a font is never applied to anything (say a particular page is in RTL and happens to not have any LTR text on it, or vice versa) the font further down the stack that isn’t used is never downloaded.

Making that happen requires selecting good multilingual fonts. Good multilingual fonts are ones that have glyphs for as many characters you anticipate using on a page. And if you are unable to find one that supports them all, using one that supports most of them and then falling back to another font that does is an efficient way to go. If that happens to be the default system font, that’s just as great because it’s one less downloaded font file.

The good thing about letting the font-family property decide the font for each glyph (instead of making extra CSS selectors for each direction) is that the behavior is already there as we outlined earlier — we simply need to make use of it. 

The post Considerations When Choosing Fonts for a Multilingual Website appeared first on CSS-Tricks.


, , , ,