Felix
Felix

Reputation: 89566

How to add multiple font files for the same font?

I'm looking at the MDC page for the @font-face CSS rule, but I don't get one thing. I have separate files for bold, italic and bold + italic. How can I embed all three files in one @font-face rule? For example, if I have:

@font-face {
    font-family: "DejaVu Sans";
    src: url("./fonts/DejaVuSans.ttf") format("ttf");
}
strong {
    font-family: "DejaVu Sans";
    font-weight: bold;
}

The browser will not know which font to be used for bold (because that file is DejaVuSansBold.ttf), so it will default to something I probably don't want. How can I tell the browser all the different variants I have for a certain font?

Upvotes: 559

Views: 296127

Answers (10)

herrstrietzel
herrstrietzel

Reputation: 17115

@font-face rules are quite unforgiving!

You need to ensure the syntax and format descriptors are correct. See W3C specs.
In case of the OP:

@font-face {
    font-family: "DejaVu Sans";
    src: url("./fonts/DejaVuSans.ttf") format("ttf"); /* not correct!!! */
}

wouldn't work as the correct format descriptor is "truetype" not "ttf" - whereas omitting the descriptor completely would work (in most modern browsers).

Example 1: correct descriptor

@font-face {
  font-family: 'Dejavu Sans';
  font-style: normal;
  font-weight: 400;
  src: url(https://cdn.jsdelivr.net/gh/herrstrietzel/testfiles@main/fonts/dejavu/DejaVuSans.ttf) format("truetype");
}
@font-face {
  font-family: 'Dejavu Sans';
  font-style: italic;
  font-weight: 400;
  src: url(https://cdn.jsdelivr.net/gh/herrstrietzel/testfiles@main/fonts/dejavu/DejaVuSans-Oblique.ttf) format("truetype");
}
@font-face {
  font-family: 'Dejavu Sans';
  font-style: normal;
  font-weight: 700;
  src: url(https://cdn.jsdelivr.net/gh/herrstrietzel/testfiles@main/fonts/dejavu/DejaVuSans-Bold.ttf) format("truetype");
}
@font-face {
  font-family: 'Dejavu Sans';
  font-style: italic;
  font-weight: 700;
  src: url(https://cdn.jsdelivr.net/gh/herrstrietzel/testfiles@main/fonts/dejavu/DejaVuSans-BoldOblique.ttf)
      format("truetype");
}

body{
  font-size:10vmin;
}

.dejavue{
    font-family: 'Dejavu Sans';
}
<p><strong>Ham</strong>burge<em>fons<strong>tiv</strong></em></p>
<p class="dejavue"><strong>Ham</strong>burge<em>fons<strong>tiv</strong></em></p>

Example 1.2: incorrect descriptor – though paths are correct

@font-face {
  font-family: 'Dejavu Sans2';
  font-style: normal;
  font-weight: 400;
  src: url(https://cdn.jsdelivr.net/gh/herrstrietzel/testfiles@main/fonts/dejavu/DejaVuSans.ttf) format("ttf");
}

@font-face {
  font-family: 'Dejavu Sans3';
  font-style: normal;
  font-weight: 400;
  src: url(https://cdn.jsdelivr.net/gh/herrstrietzel/testfiles@main/fonts/dejavu/DejaVuSans.ttf) format("truetype");
}



body{
  font-size:10vmin;
}

.dejavue2{
    font-family: 'Dejavu Sans2';
}

.dejavue3{
    font-family: 'Dejavu Sans3';
}
<p>Hamburgefonstiv (default serif font)</p>
<p class="dejavue2">Hamburgefonstiv (ttf - won’t work)</p>
<p class="dejavue3">Hamburgefonstiv (truetype - works!)</p>

Another similar syntax error would occur when using format("otf") instead of format("opentype") (coorect) .

descriptor Font Format Extension
"woff2" WOFF 2.0 .woff2
"woff" WOFF 1.0 .woff
"truetype" TrueType (glyf) .ttf
"opentype" OpenType (CFF, CFF2) .otf

Multiple formats, legacy support and obsolete formats

All modern browsers support the most compact woff2 format. However, you may still need truetypes especially for native applications or converters (e.g pdf-conversion) that may not be able to handle/decode web font container formats like woff2 or woff.

Order of font sources: from modern to legacy

In case you need legacy support make sure to stack the font sources from
most modern/compact to legacy like so:

 @font-face {
  font-family: 'Dejavu Sans';
  font-style: normal;
  font-weight: 400;
  src: url(https://cdn.jsdelivr.net/gh/herrstrietzel/testfiles@main/fonts/dejavu/DejaVuSans.woff2) format("woff2"),
    url(https://cdn.jsdelivr.net/gh/herrstrietzel/testfiles@main/fonts/dejavu/DejaVuSans.woff2) format("woff"),
    url(https://cdn.jsdelivr.net/gh/herrstrietzel/testfiles@main/fonts/dejavu/DejaVuSans.ttf) format("truetype");
}

Multiple sources must be separated by a "," comma.
A browser will choose the first valid font file. In other words if you specify the larger "truetype" file as the first src it will load this file although, it can also handle the more comapct "woff2" candidate.

Myth busting

The order of the font-face rule doesn't matter!.
If you encounter any issues it is likely due to other syntax errors in your font-face rules e.g omitting font weight or font style properties.

"Bulletproof @font-face Syntax"

In case you need to support outdated browsers internet explorer or very early webkit browsers - have a look at Paul Irish's post

For modern browsers: get rid of .eot and .svg as it it only makes your rule more prone to syntax errors.

Example 2.1: font loading priority

@font-face {
  font-family: 'Dejavu SansWoff2';
  font-style: normal;
  font-weight: 400;
  src: url(https://cdn.jsdelivr.net/gh/herrstrietzel/testfiles@main/fonts/dejavu/DejaVuSans.woff2) format("woff2"),
    url(https://cdn.jsdelivr.net/gh/herrstrietzel/testfiles@main/fonts/dejavu/DejaVuSans.woff2) format("woff"),
    url(https://cdn.jsdelivr.net/gh/herrstrietzel/testfiles@main/fonts/dejavu/DejaVuSans.ttf) format("truetype");
}

@font-face {
  font-family: 'Dejavu SansTTF';
  font-style: normal;
  font-weight: 400;
  src: 
  url(https://cdn.jsdelivr.net/gh/herrstrietzel/testfiles@main/fonts/dejavu/DejaVuSans.ttf) format("truetype"),
  url(https://cdn.jsdelivr.net/gh/herrstrietzel/testfiles@main/fonts/dejavu/DejaVuSans.woff2) format("woff2"),
    url(https://cdn.jsdelivr.net/gh/herrstrietzel/testfiles@main/fonts/dejavu/DejaVuSans.woff2) format("woff");
}

body{
  font-size:10vmin;
}


.dejavuTTF{
  font-family: 'Dejavu SansTTF';
}

.dejavuWoff2{
  font-family: 'Dejavu SansWoff2';
}
<p>Hamburgefonstiv</p>

<p class="dejavuWoff2">Hamburgefonstiv</p>
<p class="dejavuTTF">Hamburgefonstiv</p>

Local fonts or network resource?

In short: always ditch the local() method as it is highly unreliable if you need to provide a consistent fonts rendering across all browsers. It's mainly unreliable because a font-family can have a plethora of different font names – depending on OS and font version.

Always check your DEV tools for rendered/loaded fonts

The font info should show a "network resource" in the computed styles view. Besides the network tab should show entries for loaded font files.
If not - you're seeing a locally installed font that won't be available on all devices. Dev tools

network tab

Variable Fonts

When you're using a variable font you can reduce the number of @font-face rules. Usually you need at max 2 rules (one for regular and another for italic style)

/* latin */
@font-face {
  font-family: 'Open Sans';
  font-style: italic;
  font-weight: 300 800;
  font-stretch: 75% 100%;
  font-display: swap;
  src: url(https://fonts.gstatic.com/s/opensans/v40/mem6YaGs126MiZpBA-UFUK0Zdc0.woff2) format('woff2');
}

/* latin */
@font-face {
  font-family: 'Open Sans';
  font-style: normal;
  font-weight: 300 800;
  font-stretch: 75% 100%;
  font-display: swap;
  src: url(https://fonts.gstatic.com/s/opensans/v40/mem8YaGs126MiZpBA-UFVZ0b.woff2) format('woff2');
}


body{
  font-family: 'Open Sans';
  font-size:10vmin;
}

.cnd{
  font-stretch:75%;
}
<p><em>Ham</em>Hamburge<strong>fonstiv</strong></p>
<p class="cnd"><em>Ham</em>Hamburge<strong>fonstiv</strong></p>

Note: We need to specify a font-variant range by adding 2 values – separated by a space:

font-weight: 100 1000;
font-stretch: 0% 200%;

Italic vs Oblique vs Slanted

Italic and Oblique refer to typographic classifications. An italic usually has distinctively different letter shapes - e.g a two storage "a" in regular (upright) style as opposed to a one storage design in a lot of fonts.
Oblique refers to a design concept where "italics" rather look like skewed letter designs – in fact they are still manually designed but similar to the upright design. font-style:oblique is rather obsolete – just use italic.

"slanted" is more relevant to variable fonts. Some fonts contain a seamless interpolation of the slanting angle that can be used as a replacement for italics

@font-face {
  font-family: 'Roboto Flex';
  font-style: oblique 0deg 10deg;
  font-weight: 100 1000;
  font-stretch: 25% 151%;
  font-display: swap;
  src: url(https://fonts.gstatic.com/s/robotoflex/v26/NaPLcZLOBv5T3oB7Cb4i0xG2bBVmtU5Wc7yZcSAuwtiL.woff2) format('woff2');
}


body{
  font-size:10vmin;
  font-family: 'Roboto Flex';
}

.slnt1{
  font-style: oblique 3deg
}

.slnt2{
  font-style: oblique 10deg
}
<p>Hamburgefonstiv</p>
<p class="slnt1">Hamburgefonstiv</p>
<p class="slnt2">Hamburgefonstiv</p>

Upvotes: 1

Abdul Malik
Abdul Malik

Reputation: 559

I added a custom font like this to my styles.less. Here I have added more one url in 'src' as a fallback.

More you can read here: https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/src#specifying_fallbacks_for_older_browsers

@font-face {
    font-family: EuclidSquare;
    src: url('/fonts/EuclidSquare-LightItalic.woff2') format('woff2'),
        url('/fonts/EuclidSquare-LightItalic.woff') format('woff'),
        url('/fonts/EuclidSquare-LightItalic.otf') format('opentype');
    font-weight: 300;
    font-style: italic, oblique;
}
@font-face {
    font-family: EuclidSquare;
    src: url('/fonts/EuclidSquare-Light.woff2') format('woff2'),
        url('/fonts/EuclidSquare-Light.woff') format('woff'),
        url('/fonts/EuclidSquare-Light.otf') format('opentype');
    font-weight: 300;
}
@font-face {
    font-family: EuclidSquare;
    src: url('/fonts/EuclidSquare-RegularItalic.woff2') format('woff2'),
        url('/fonts/EuclidSquare-RegularItalic.woff') format('woff'),
        url('/fonts/EuclidSquare-RegularItalic.otf') format('opentype');
    font-style: italic, oblique;
}
@font-face {
    font-family: EuclidSquare;
    src: url('/fonts/EuclidSquare-Regular.woff2') format('woff2'),
        url('/fonts/EuclidSquare-Regular.woff') format('woff'),
        url('/fonts/EuclidSquare-Regular.otf') format('opentype');
}
@font-face {
    font-family: EuclidSquare;
    src: url('/fonts/EuclidSquare-MediumItalic.woff2') format('woff2'),
        url('/fonts/EuclidSquare-MediumItalic.woff') format('woff'),
        url('/fonts/EuclidSquare-MediumItalic.otf') format('opentype');
    font-weight: 500;
    font-style: italic, oblique;
}
@font-face {
    font-family: EuclidSquare;
    src: url('/fonts/EuclidSquare-Medium.woff2') format('woff2'),
        url('/fonts/EuclidSquare-Medium.woff') format('woff'),
        url('/fonts/EuclidSquare-Medium.otf') format('opentype');
    font-weight: 500;
}
@font-face {
    font-family: EuclidSquare;
    src: url('/fonts/EuclidSquare-SemiboldItalic.woff2') format('woff2'),
        url('/fonts/EuclidSquare-SemiboldItalic.woff') format('woff'),
        url('/fonts/EuclidSquare-SemiboldItalic.otf') format('opentype');
    font-weight: 600;
    font-style: italic, oblique;
}
@font-face {
    font-family: EuclidSquare;
    src: url('/fonts/EuclidSquare-Semibold.woff2') format('woff2'),
        url('/fonts/EuclidSquare-Semibold.woff') format('woff'),
        url('/fonts/EuclidSquare-Semibold.otf') format('opentype');
    font-weight: 600;
}
@font-face {
    font-family: EuclidSquare;
    src: url('/fonts/EuclidSquare-BoldItalic.woff2') format('woff2'),
        url('/fonts/EuclidSquare-BoldItalic.woff') format('woff'),
        url('/fonts/EuclidSquare-BoldItalic.otf') format('opentype');
    font-weight: bold;
    font-style: italic, oblique;
}
@font-face {
    font-family: EuclidSquare;
    src: url('/fonts/EuclidSquare-Bold.woff2') format('woff2'),
        url('/fonts/EuclidSquare-Bold.woff') format('woff'),
        url('/fonts/EuclidSquare-Bold.otf') format('opentype');
    font-weight: bold;
}

body {
    font-family: EuclidSquare, Lato, sans-serif;
}

Upvotes: 5

Tux
Tux

Reputation: 61

If you are using a Google Font, I suggest using @import url("@import url('https://fonts.googleapis.com/css2?family=Saira+Condensed:wght@900&display=swap');") and specifying font-family: 'Saira Condensed', sans-serif; as the CSS Rule.

Upvotes: 0

piouson
piouson

Reputation: 4545

For Create React App see my other SO answer here

  1. If you choose to link the css file directly to your public/index.html:
@font-face {
  font-family: "FontName"; <---
  font-style: normal; <---
  font-weight: normal;
  src: url("path-to-assets/fonts/FontName.ttf") format("truetype");
}
@font-face {
  font-family: "FontName"; <---
  font-style: italic; <---
  font-weight: normal;
  src: url("path-to-assets/fonts/FontName-Italic.ttf") format("truetype");
}
  1. If you choose to link the css file via Js for bundling:
@font-face {
  font-family: "FontName"; <---
  font-style: normal; <---
  font-weight: normal; /* normal | 300 | 400 | 600 | bold | etc */
  src: url("path-to-assets/fonts/FontName.ttf") format("truetype");
}
@font-face {
  font-family: "FontNameItalic"; <---
  font-style: normal; <----
  font-weight: normal; /* normal | 300 | 400 | 600 | bold | etc */
  src: url("path-to-assets/fonts/FontName-Italic.ttf") format("truetype");
}

Upvotes: 0

xlaoyu.Lee
xlaoyu.Lee

Reputation: 333

nowadays,2017-12-17. I don't find any description about Font-property-order‘s necessity in spec. And I test in chrome always works whatever the order is.

@font-face {
  font-family: 'Font Awesome 5 Free';
  font-weight: 900;
  src: url('#{$fa-font-path}/fa-solid-900.eot');
  src: url('#{$fa-font-path}/fa-solid-900.eot?#iefix') format('embedded-opentype'),
  url('#{$fa-font-path}/fa-solid-900.woff2') format('woff2'),
  url('#{$fa-font-path}/fa-solid-900.woff') format('woff'),
  url('#{$fa-font-path}/fa-solid-900.ttf') format('truetype'),
  url('#{$fa-font-path}/fa-solid-900.svg#fontawesome') format('svg');
}

@font-face {
  font-family: 'Font Awesome 5 Free';
  font-weight: 400;
  src: url('#{$fa-font-path}/fa-regular-400.eot');
  src: url('#{$fa-font-path}/fa-regular-400.eot?#iefix') format('embedded-opentype'),
  url('#{$fa-font-path}/fa-regular-400.woff2') format('woff2'),
  url('#{$fa-font-path}/fa-regular-400.woff') format('woff'),
  url('#{$fa-font-path}/fa-regular-400.ttf') format('truetype'),
  url('#{$fa-font-path}/fa-regular-400.svg#fontawesome') format('svg');
}

Upvotes: 19

Jerry T
Jerry T

Reputation: 1690

/*
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
# dejavu sans
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
*/
/*default version*/
@font-face {
    font-family: 'DejaVu Sans';
    src: url('dejavu/DejaVuSans.ttf'); /* IE9 Compat Modes */
    src: 
        local('DejaVu Sans'),
        local('DejaVu-Sans'), /* Duplicated name with hyphen */
        url('dejavu/DejaVuSans.ttf') 
        format('truetype');
}
/*bold version*/
@font-face {
    font-family: 'DejaVu Sans';
    src: url('dejavu/DejaVuSans-Bold.ttf'); 
    src: 
        local('DejaVu Sans'),
        local('DejaVu-Sans'),
        url('dejavu/DejaVuSans-Bold.ttf') 
        format('truetype');
    font-weight: bold;
}
/*italic version*/
@font-face {
    font-family: 'DejaVu Sans';
    src: url('dejavu/DejaVuSans-Oblique.ttf'); 
    src: 
        local('DejaVu Sans'),
        local('DejaVu-Sans'),
        url('dejavu/DejaVuSans-Oblique.ttf') 
        format('truetype');
    font-style: italic;
}
/*bold italic version*/
@font-face {
    font-family: 'DejaVu Sans';
    src: url('dejavu/DejaVuSans-BoldOblique.ttf'); 
    src: 
        local('DejaVu Sans'),
        local('DejaVu-Sans'),
        url('dejavu/DejaVuSans-BoldOblique.ttf') 
        format('truetype');
    font-weight: bold;
    font-style: italic;
}

Upvotes: 7

Cedric Simon
Cedric Simon

Reputation: 4659

To have font variation working correctly, I had to reverse the order of @font-face in CSS.

@font-face {
    font-family: "DejaVuMono";
    src: url("styles/DejaVuSansMono-BoldOblique.ttf");
    font-weight: bold;
    font-style: italic, oblique;
}   
@font-face {
    font-family: "DejaVuMono";
    src: url("styles/DejaVuSansMono-Oblique.ttf");
    font-style: italic, oblique;
}
@font-face {
    font-family: "DejaVuMono";
    src: url("styles/DejaVuSansMono-Bold.ttf");
    font-weight: bold;
}
 @font-face {
    font-family: "DejaVuMono";
    src: url("styles/DejaVuSansMono.ttf");
}

Upvotes: 32

Dieter Gribnitz
Dieter Gribnitz

Reputation: 5208

If you are using Google fonts I would suggest the following.

If you want the fonts to run from your localhost or server you need to download the files.

Instead of downloading the ttf packages in the download links, use the live link they provide, for example:

http://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,600,300italic,400italic,600italic

Paste the URL in your browser and you should get a font-face declaration similar to the first answer.

Open the URLs provided, download and rename the files.

Stick the updated font-face declarations with relative paths to the woff files in your CSS, and you are done.

Upvotes: 14

Felix
Felix

Reputation: 89566

The solution seems to be to add multiple @font-face rules, for example:

@font-face {
    font-family: "DejaVu Sans";
    src: url("fonts/DejaVuSans.ttf");
}
@font-face {
    font-family: "DejaVu Sans";
    src: url("fonts/DejaVuSans-Bold.ttf");
    font-weight: bold;
}
@font-face {
    font-family: "DejaVu Sans";
    src: url("fonts/DejaVuSans-Oblique.ttf");
    font-style: italic, oblique;
}
@font-face {
    font-family: "DejaVu Sans";
    src: url("fonts/DejaVuSans-BoldOblique.ttf");
    font-weight: bold;
    font-style: italic, oblique;
}

By the way, it would seem Google Chrome doesn't know about the format("ttf") argument, so you might want to skip that.

(This answer was correct for the CSS 2 specification. CSS3 only allows for one font-style rather than a comma-separated list.)

Upvotes: 906

Josiah
Josiah

Reputation: 3158

As of CSS3, the spec has changed, allowing for only a single font-style. A comma-separated list (per CSS2) will be treated as if it were normal and override any earlier (default) entry. This will make fonts defined in this way appear italic permanently.

@font-face {
    font-family: "DejaVu Sans";
    src: url("fonts/DejaVuSans.ttf");
}
@font-face {
    font-family: "DejaVu Sans";
    src: url("fonts/DejaVuSans-Bold.ttf");
    font-weight: bold;
}
@font-face {
    font-family: "DejaVu Sans";
    src: url("fonts/DejaVuSans-Oblique.ttf");
    font-style: italic;
}
@font-face {
    font-family: "DejaVu Sans";
    src: url("fonts/DejaVuSans-BoldOblique.ttf");
    font-weight: bold;
    font-style: italic;
}
@font-face {
    font-family: "DejaVu Sans";
    src: url("fonts/DejaVuSans-Oblique.ttf");
    font-style: oblique;
}
@font-face {
    font-family: "DejaVu Sans";
    src: url("fonts/DejaVuSans-BoldOblique.ttf");
    font-weight: bold;
    font-style: oblique;
}

In most cases, italic will probably be sufficient and oblique rules won't be necessary if you take care to define whichever you will use and stick to it.

Upvotes: 93

Related Questions