All about fonts on websites!
I recently did a big cleanup of how fonts are used on a project. Here's a quick rundown of some things I learned along the way. Each building block is pretty straightforward and easy to find documentation for, but overall best practices, and explanations for how it all comes together, are lacking, so hopefully this guide will fix that situation a bit.
First I'll show an example using Google Fonts and explain the concepts in its provided code. Then further down I'll talk about fonts from other sources.
The basics
As advertised, Google fonts is a very easy way to get fonts into your website correctly.
@import url('https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,400;0,500;0,700;1,400;1,500;1,700&display=swap');
What does this do? It brings some CSS into your CSS which points to some font files. It does this for several character sets. You can simply visit the link in the code above to view the CSS.
Here are just the latin definitions, with some attributes removed for clarity:
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 400;
src: url(https://fonts.gstatic.com/s/roboto/v27/KFOkCnqEu92Fr1Mu51xIIzIXKMny.woff2) format('woff2');
}
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 500;
src: url(https://fonts.gstatic.com/s/roboto/v27/KFOjCnqEu92Fr1Mu51S7ACc6CsTYl4BO.woff2) format('woff2');
}
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 700;
src: url(https://fonts.gstatic.com/s/roboto/v27/KFOjCnqEu92Fr1Mu51TzBic6CsTYl4BO.woff2) format('woff2');
}
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 400;
src: url(https://fonts.gstatic.com/s/roboto/v27/KFOmCnqEu92Fr1Mu4mxKKTU1Kg.woff2) format('woff2');
}
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 500;
src: url(https://fonts.gstatic.com/s/roboto/v27/KFOlCnqEu92Fr1MmEU9fBBc4AMP6lQ.woff2) format('woff2');
}
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 700;
src: url(https://fonts.gstatic.com/s/roboto/v27/KFOlCnqEu92Fr1MmWUlfBBc4AMP6lQ.woff2) format('woff2');
}
Why are there 6 font-face definitions?
Because the browser wants to have a file for each "variant". A variant is:
family+weight+style
What is a font family?
You can probably guess that this is simply the name of the font. Note that the family name is identical for all 6 font-face declarations above, "Roboto". More discussion about the significance of font family is further down in this guide.
What is a font weight?
The two weights you are probably familiar with from word processors, WYSIWYGs, etc. are "normal" and "bold". But there are more than those two weights in the wide world of typography. A weight is a number between 100 and 900, in increments of 100. "normal" is 400 and "bold" is 700. The next most interesting weight is "medium" which is 500. In the example above, google fonts only provides 400, 500, and 700 for Roboto. You can see all the weight name mappings here.
What is a font style?
The two styles you are probably familiar with are "normal" and "italic". There are also a couple more, I'm not sure how well supported in browsers or how commonly used. Google fonts provides "normal" and "italic" variants for Roboto.
What is a format?
A format, such as woff2 in the example above, is the format of the font file that your browser is instructed to download. Several font formats have come and gone over the years. For a period of time (2009-2016 or so?) web developers would dilligently provide 3 or more different font formats to cover as many browsers as possible. These days, it's pretty much accepted to only provide woff2. This covers quite a lot of browsers.
Notably, it does not cover IE11, which has a <1% global usage, but might be a several percent larger portion of your customer base depending on your market. You might be happy letting these users fall back to another font, which will simplify your deployment and code and life. But, if you want to support these users, it's easy enough to do so by also providing woff, which is supported by IE 9 and above. You can read about providing multiple formats here.
Interestingly, google fonts will only send the needed font format to your browser, depending on what the browser supports.
How do I put non-google fonts on my website?
Just like how google makes it quick and easy to include fonts with a single link to a CDN, other commercial venders do the same. Just kidding, that's not the case at all, at least not with fonts.com which I was recently working with.
With fonts.com you will need to host your font files somewhere and link to them in the same way as the example code above. If you know other vendors who make this easier, let me know!
What's the deal with font-family?
Your browser cannot (or at least, does not) magically know a font file's name or variant by reading its metadata. It simply trusts what you tell it. So if you include the above code in your CSS but instead of "Roboto" you use the font-family "Hamster", your browser will think there is a typeface named Hamster made available by those files.
I recently encounted a situation where instead of properly defined variants like in the above example, each variant had a font-family like "Roboto-Bold". The source of this was from copy-pasting generated style from a project in another third-party system (I think Abstract). I'm not sure why that system did that. For a while I assumed this was some sort of naming format that browsers expected, and that "Roboto-bold" would map to the Roboto variant with weight 700. This is not the case.
What do browsers do if a variant isn't available?
The browser will sometimes try to fake a variant. If it only has one variant, weight 400 style normal, it can use this to "fake" weight 700 and italic. It will only do this for these two variants.
The browser will also, by some undocumented heuristic, reuse one bold variant for another bold variant. For example, if only weight 700 is available and CSS calls for weight 900, it will use the 700 variant. It will not attempt to fake 900. It will simply display 700.
If you think anything else should go into this guide, let me know!