Color

Another aspect to consider is the color for your typefaces. This is a very design-dependent step. Were you given a color palette as part of your design brief? Then use those. But if you’re planning your own project then you can use the tools below.

Adobe Color CSS (Formerly known as Adobe Kuler) let’s you create color sets for your projects. If you use SASS/SCSS you can then turn the colors into variables to use in your CSS.

Dudley Storye creataed a color Thesaurus that makes it easier to see what the colors will look like in the page. We can combine the colors from the chart with text to test

For this section I’ve created an Adobe Color CC Palette.

It may not have al the colors I need and I’m in no way required to use all the colors in the palette but I will set them up anyways so we can see what it looks like in all the colors available to the palette.

[codepen_embed height=”577″ theme_id=”2039″ slug_hash=”LVjVzY” default_tab=”result” user=”caraya”]See the Pen Example Colored Headings by Carlos Araya (@caraya) on CodePen.[/codepen_embed]

The first palette is fairly cool, let’s see what other colors look like on our heading text; to do so, I’ve chosen a second palete from Color CC.

[codepen_embed height=”573″ theme_id=”2039″ slug_hash=”ZGJGXq” default_tab=”result” user=”caraya”]See the Pen Colored headings, take 2 by Carlos Araya (@caraya) on CodePen.[/codepen_embed]

We can also test color with our paragraph formatting. I will pick the second color palette for this experiment. Notice how the lighter colors make things harder to read and the darker colors help… When we discuss accessibility concerns we’ll touch on color blindness and contrast as necessary elements of your typographical design.

Technical note: In the example below there are two values for color in each selector. I coded it that way to provide a fallback solution for older browsers that do not support RGB color syntax. If the browser doesn’t support RGB colors the rule will be ignored and the browser will move to the hexadecimal color and, hopefully, will render it without an issue.

[codepen_embed height=”969″ theme_id=”2039″ slug_hash=”gpxpXg” default_tab=”result” user=”caraya”]See the Pen Colored Paragraph Example by Carlos Araya (@caraya) on CodePen.[/codepen_embed]

Even different shades of gray/grey may have an impact. In the last color example I’ve picked different shades of grey for each paragraph color. As with many things related to type, the best color for your text will depend on the typeface you choose.

[codepen_embed height=”969″ theme_id=”2039″ slug_hash=”pJrJdK” default_tab=”result” user=”caraya”]See the Pen Paragraph in Shades of Gray/Grey by Carlos Araya (@caraya) on CodePen.[/codepen_embed]

Media Queries: Not all displays are equal

Media queries are a part of the progressive enhancement process. Using Media Queries (Specification and first public draft of Level 4 extensions) you can use a single CSS style sheet to work with multiple devices.

At its most basic, a media query tells the browser to change selectors and attributes based on a certain value or to load (or not load) a specified resource. For example, you can use media queries when loading a stylesheet with a link element:


<link rel="stylesheet" media="(max-width: 800px)" href="example.css" />

In this query, The user agen test is the the user agent is 800 pixels wider or narrower and, if it is, it will load the specified style sheet; otherwise it’ll skip it.

You can also use media queries inside a stylesheet (internal or external) using the media at-rule.


@media (max-width: 600px) {
  .facet_sidebar {
    display: none;
  }
}

In the stylesheet example, the test if for width of 600 pixels or less. If the rule is matches then we will change the display propery of the facet_siderbar class to hide it. You can have multiple rules inside each media query.

You can also do multiple queries, limit them to specific device types (like screen or print) and even chain queries together. The following example taken from CSS Tricks.com provides media queries for some iPhones (the article has additional queries for standard devices.)



/* ----------- iPhone 6 ----------- */

/* Portrait and Landscape */
@media only screen
  and (min-device-width: 375px)
  and (max-device-width: 667px)
  and (-webkit-min-device-pixel-ratio: 2) {

}

/* Portrait */
@media only screen
  and (min-device-width: 375px)
  and (max-device-width: 667px)
  and (-webkit-min-device-pixel-ratio: 2)
  and (orientation: portrait) {

}

/* Landscape */
@media only screen
  and (min-device-width: 375px)
  and (max-device-width: 667px)
  and (-webkit-min-device-pixel-ratio: 2)
  and (orientation: landscape) {

}

/* ----------- iPhone 6+ ----------- */

/* Portrait and Landscape */
@media only screen
  and (min-device-width: 414px)
  and (max-device-width: 736px)
  and (-webkit-min-device-pixel-ratio: 3) {

}

/* Portrait */
@media only screen
  and (min-device-width: 414px)
  and (max-device-width: 736px)
  and (-webkit-min-device-pixel-ratio: 3)
  and (orientation: portrait) {

}

/* Landscape */
@media only screen
  and (min-device-width: 414px)
  and (max-device-width: 736px)
  and (-webkit-min-device-pixel-ratio: 3)
  and (orientation: landscape) {

}

This begs a question: Do we design for devices or resolutions?

Justin Avery suggests that we don’t need device specific media queries and that we should base the media queries we use in the devices and resolutions that we need to support rather than specific devices. He mentions that:

Over the 4 years we have slowly moved away from device specific breakpoints in favour of content specific breakpoints, i.e. adding a breakpoint when the content is no longer easy to consume.

With this fundamental shift in thinking we no longer have to fear a new device — a new iPhone width — because we’ve already fixed our sites to work everywhere.

— Justin Avery

Making changes for print

One of the best uses I’ve seen for media queries is to handle priting web content. As I wrote in Creating print CSS stylesheets this is not an alternative to CSS Paged Media but a stop gap to get the online content printed.

What this media query will do is set up the margins (top, left and right to 1 inch and bottom to 1.5), set the line height to 1.5 (18pt in this case), remove any background image and make the text color black.

It will then adjust the size of the h1, h2 and h3 elements and hide video, audio, and object elements. These are normally multimedia elements that may or may not be needed in a printed document. If you don’t hide them then the printer will spend large amounts of toner or ink to get your content printed (waste of time in my opinion.)

/* example changes for printing a web page */
@media print {
  body {
    margin: 1in 1in 1.5in;
    font-size: 12pt;
    line-height: 1.5;
    background-image: none;
    color: #000;
  }

  h1 {
    font-size: 2em;
  }

  h2 {
    font-size: 1.75em;
  }

  h3 {
    font-size: 1.5em;
  }

  video, audio, object {
    display: none
  }
}        

Moving forward

While the current Media Query specification defines a large set of media features to use in our queries, what really excite me are some of the queries (additional dimensions, display quality and interaction in particular) available in the editor draft for level 4

When these queries are supported in browsers we will be able to query for both screen size and DPI density and serve the appropriate content using CSS. It may look something like this:

/* possible test for screen size and 2x HDPI */
@media screen and (min-width: 800px) and (max-width: 1024px) and (resolution >= 2dppx) {
  .facet_sidebar {
    /* Do something for browsers that go between the two values */
  }
}

Just in case you’re curious (as I was): dppx represents the number of dots per px unit. Due to the 1:96 fixed ratio of CSS in to CSS px, 1dppx is equivalent to 96dpi, that corresponds to the default resolution of images displayed in CSS as defined by image-resolution (from MDN.)

Even when widely supported you must test this in your target devices!

Links and resources

Headings

Headings serve as the visual representation of our content and, as such, they deserve special consideration. We’ll discuss whether to use the same font as our body or whether it’s better to use a different one, and some things we can do with heading text. I wish I could tell you exactly what fonts to use but, as with many things type related, it’ll depend on many factors.

Let’s look at what the possibilities are.

Same or different fontface?

One of the questions that always baffles me is whether to use the same font for headings as I use for the body text.The first example uses the same font (Lato) for both headings and body text. It looks ok but I’m still not sold out on the idea.

[codepen_embed height=”338″ theme_id=”2039″ slug_hash=”gpxOwe” default_tab=”result” user=”caraya”]See the Pen Headings using body type by Carlos Araya (@caraya) on CodePen.[/codepen_embed]

The second example uses a Serif font, Roboto Slab, in the headings with Stone Humanist as the body font.I like the contrast I have to keep reminding myself that the contrast must be present but not be jarring to the reader.

[codepen_embed height=”336″ theme_id=”2039″ slug_hash=”dozyOW” default_tab=”result” user=”caraya”]See the Pen Headings in Serif Font by Carlos Araya (@caraya) on CodePen.[/codepen_embed]

The last option is to use a typeface from the web safe palette. One of my favorite typefaces is Verdana (don’t judge) so we’ll try that for headings and see how that looks on our headings with the font selected for the body. And here it is:

[codepen_embed height=”334″ theme_id=”2039″ slug_hash=”MwvwJB” default_tab=”result” user=”caraya”]See the Pen Headings in Verdana (or other system font) by Carlos Araya (@caraya) on CodePen.[/codepen_embed]

So with these three options which one should I pick? Three typefaces may not be enough but out of the three I’d pick Roboto Slab. We should certainly test additional fonts either with a system like the one I just did or with Typecast but I was narrowing the choice to these three so doing it by hand was less of a hassle than setting up Typecast. In a larger project I would set up Typecast earlier and do all the testing there.  

Playing with heading type

Now that we’ve selected the font we can look at some effects that will make the headings stand out further. We can play with changing the capitalization of the heading, make them all upper or lower case and maybe even change letter and word spacing. The example below uses different values for the text-transform property to change the way the headings look.

[codepen_embed height=”475″ theme_id=”2039″ slug_hash=”WvENoL” default_tab=”result” user=”caraya”]See the Pen Different text effects applied to headings by Carlos Araya (@caraya) on CodePen.[/codepen_embed]

Paragraph Styling

Most the time we spend engaged with text is with paragraphs and that’s where I put a lot of my research time when working on a new project. You may be asking why put so much work on how the paragraphs look… As you will see in the example below there are many elements that are involved in controlling paragraph appearance.

See the Pen Playing with paragraph type by Carlos Araya (@caraya) on CodePen.

With the content above we can now start playing with type. Do the following activities to get a feel for how much type can change:

  1. Change the font-size on div#example4 p:first-child to 1.5em
    • Does the size of the first paragraph change your reaction to it? Does size matter?
  2. Remove the reference to “fira_sanslight” to see what would the text look like in Arial
  3. Remove the reference to Arial to see what the text would look like in the system’s Sans Serif font
    • What are the differences between the three fonts?
  4. Change the font-size attribute to 1.5em and the line-height to 1 Is it harder to read?
  5. Change the line-height to 1.5. Does it get easier?
  6. Chang the reference to “Stone Humanist” to Verdana. Can you describe the changes?
    • Does the line height change how easy or hard it is to read the text?
  7. Change the width attribute of div#example4 to 50%
    • Does the text become harder to read as it gets narrower?
  8. Change the word spacing from normal to .25em
  9. Change the word spacing from .25em to -.25em
    • Does the text become harder to read as it gets sspread further apart? As it gets condensed together?
  10. Change the letter spacing from 0 to .25em.
  11. Change the letter spacing from .25em to -.25em
    • Does the text become harder to read as it gets sspread further apart? As it gets condensed together?

The typeface you select does make a difference. While we may not conciously notice how the text changes the changes affect the way text looks and the way we interact with it. I know I hit you with a lot of activities and questions for this little paragraph exercise so feel free to play with some, all or none of the activities above.

But whether you use them or not, you get the idea of how much work goes into making paragraphs read well.

Drop caps

Most (if not all) of us have seen the big initial capital letter on the first paragraph of a chapter. We can do th is with CSS. One version of the effect looks like the code below using first–of-type and first-letter to identify the first letter of the first paragraph and the styles to apply to t his pseudo element

p:first-of-type:first-letter {
  font-size: 3em;
  line-height: 0.9em;
  float: left;
  padding-right: 0.15em;
}
          

Unfortunately older browsers don’t support the :first-of-type selector (looking at IE7 and possibly IE8) so we have to work around and tie the drop cap to the first letter of the first element. Most of the time this will be an h1 or other heading element but it can be any element you want. Note that you will have to hardcode what the first element is and change your SASS/CSS every time you change the first element

If you don’t care about supporting older browsers then this is a non-issue but coding defensively is always a good practice 🙂

h1 + p:first-letter {
  font-size: 3em;
  line-height: 0.9em;
  float: left;
  padding-right: 0.15em;
}
          

See the Pen Example of drop cap using sibbling selectors by Carlos Araya (@caraya) on CodePen.

Loading Fonts

Now that we have a better idea of what fonts we want to use and the font stack we’ll see how to load them into the page. We’ll explore 3 ways: local loading using the @font-face syntax, loading fonts using the Google font API, using Google’s Web Font Loader and a new tool called Font Face Observer

@font-face

We have been able to use fonts on our web content since the days of IE 3 (3.5 for Macintosh if I remember correctly) but we’ve always had to contend with font creators and foundries fear of piracy. It’s only recently that they have relented and allowed their fonts to be used. The basic syntax, covering all modern browsers, looks like this:

@font-face {
    font-family: 'stone-sans-webfont';
    src: url('../path-to-font-file.eot');
    src: url('../path-to-font-file.eot?#iefix') format('embedded-opentype'),
         url('../path-to-font-file.woff2') format('woff2'),
         url('../path-to-font-file.woff') format('woff'),
         url('../path-to-font-file.ttf') format('truetype'),
         url('../path-to-font-file.svg#stone-sans-webfont') format('svg');
    font-weight: normal;
    font-style: normal;
}

And then we associate the font with CSS like we normally would matching the font-family attribute in the @font-face declaration with the font-family attribute of the element where we want to use it:

html {
        font-family: 'stone-sans-webfont', arial, sans-serif;
}
        

Since we want to avoid faux bold and faux italics in our content, we add the bold and italics versions of our font to the page and then match them to the correct attributes with selectors similar to this:

strong {
  font-family: 'Stone-Humanist-Semi';
}

em {
  font-family: 'Stone-Humanist-Ita';
}

/*
  When using both we don't care what order they are used in
*/
strong em,
em strong {
  font-family: 'Stone-Humanist-SemiItalic';
}

Where Stone-Humanist-Semi is our (semi)bold font, Stone-Humanist-Ita is italics and Stone-Humanist-SemiItalic is the semibold italics combination. Since <b> and <i> have different semantic meaning in HTML5 I’ve chosen not to style them.

Some things to keep in mind

Adding the font to your site/book/app adds to the overall file size. Depending on the font this may increase the size of your project considerably. Taking Gentium as an example, the font supports Latin, Greek and Cyrillic character sets but it weighs a hefty 500k for the regular font (in one format out of the 5 formats needed to support multiple browsers/devices). Add Bold, Italic and you get 1.5 Megabytes just for the font! And it may not be the only font you use in the project.

The flipside to this issue of size is that embedding the fonts means they are always available to desktop and mobile browsers readers that support embedding (and it should be all of them.) Choosing what browsers and what versions to support is a different story.

Google Fonts API

Google has two ways of using web fonts, the first one is directly through their API. Using Google’s font API is a two step process. First add the font to your html head element with the following syntax (using Tangerine as an example):

<link rel="stylesheet" type="text/css" href="http://fonts.googleapis.com/css?family=Tangerine">

The link produces a CSS @font-face declaration that we can use in our CSS as normal. The version produced in Chrome and Firefox uses the woff2 format

@font-face {
  font-family: 'Tangerine';
  font-style: normal;
  font-weight: 400;
  src: local('Tangerine'), url(http://fonts.gstatic.com/s/tangerine/v6/HGfsyCL5WASpHOFnouG-RJBw1xU1rKptJj_0jans920.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;
}

While Safari uses True Type to render the font.

@font-face {
  font-family: 'Tangerine';
  font-style: normal;
  font-weight: 400;
  src: local('Tangerine'), url(http://fonts.gstatic.com/s/tangerine/v6/HGfsyCL5WASpHOFnouG-RCZ2oysoEQEeKwjgmXLRnTc.ttf) format('truetype');
}

As you can see the advantage of using the APi is that we don’t need to use multiple formats in our @font-face declaration. Google takes care of that for us.

The obvoius disadvantage is that this only works online. That’s why a fallback option or options is even more important when working with the API. If we’re offline or connectivity is limited we want a good fallback font.

Google web font loader

One of the things neither the font API or directly downloading the content doesn’t address is the “flash of unstyled text.” According to the Typekit Help Center:

Fonts are loaded as assets into a web page—just like images or video. Depending on your browser or your connection speed, they can load quickly or lag behind the rest of the page. Different browsers handle font loading differently; for example, Safari and Chrome will refrain from displaying text set in a web font until the font has loaded, while Internet Explorer won’t show anything on the page until the font loads. Meanwhile, Firefox will display the site with the fallback fonts in the font stack, and then switch to the linked fonts after they’ve finished loading. This results in a flash of unstyled text, or FOUT.

Typekit, in collaboration with Google, has created loader library to make working with type easier. It works by adding scripts to the page that load the library and tell it what fonts to download and use. For example to load the Droid Sans font from Google you’d use code like this:

<script src="https://ajax.googleapis.com/ajax/libs/webfont/1.5.10/webfont.js"></script>
<script>
  WebFont.load({
    typekit: {
      id: 'xxxxxx'
    },
    custom: {
      families: ['Droid Sans', 'Source Code Pro'],
    },
    google: {
      families: ['Droid Sans', 'Droid Serif'],
      text: 'abcdedfghijklmopqrstuvwxyz!'
    },
    fontdeck: {
      id: 'xxxxx'
    },
    monotype: {
      projectId: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx',
      version: 12345 // (optional, flushes the CDN cache)
    }
  });
</script>

Or using asynchronous loading:

<script src="https://ajax.googleapis.com/ajax/libs/webfont/1.5.10/webfont.js"></script>
<script>
  WebFontConfig = {
    google: { families: [ 'Lora:400,700,400italic,700italic:latin' ] }
  };
  (function() {
    var wf = document.createElement('script');
    wf.src = ('https:' == document.location.protocol ? 'https' : 'http') +
      '://ajax.googleapis.com/ajax/libs/webfont/1/webfont.js';
    wf.type = 'text/javascript';
    wf.async = 'true';
    var s = document.getElementsByTagName('script')[0];
    s.parentNode.insertBefore(wf, s);
  })();

<noscript>
  <link href='http://fonts.googleapis.com/css?family=Lora:400,700,400italic,700italic' rel='stylesheet' type='text/css'>
</noscript>

For an explanation of the values for each foundry check the Font Loader’s readme file in Github.

The font loader creates a set of events, both CSS and Javascript, for developers to interact with. This is similar to the way Modernizr handles feature detection. The Javascript classes are:

  • loading – This event is triggered when all fonts have been requested.
  • active – This event is triggered when the fonts have rendered.
  • inactive – This event is triggered when the browser does not support linked fonts or if none of the fonts could be loaded.
  • fontloading – This event is triggered once for each font that’s loaded.
  • fontactive – This event is triggered once for each font that renders.
  • fontinactive – This event is triggered if the font can’t be loaded.

CSS events are implemented as classes on the html element. The following classes are set on the html element and correspond to the descriptions above:

  • .wf-loading
  • .wf-active
  • .wf-inactive
  • .wf-<familyname>-<fvd>-loading
  • .wf-<familyname>-<fvd>-active
  • .wf-<familyname>-<fvd>-inactive

The <familyname> placeholder will be replaced by a sanitized version of the name of each font family in lowercase with only alphanumeric characters. For example, Droid Sans becomes droidsans. The <fvd> placeholder is a Font Variation Description, a shorthand for describing the style and weight of a particular font.

So why would we use the Font Loader?

In short: to make the user’s experience less jarring. Since fonts are downloaded as any other resource in your web page. If we use the following font stack: 'stone-sans-webfont', arial, sans-serif, we can then use the Font Loader Defined classes to make the transition to our fonts smoother and better looking. Let’s look at one possibility:

.wf-inactive body{
  font-family: arial, sans-serif;
  line-height: 1.4em;
}

.wf-active body {
  font-family: 'stone-sans-webfont', arial, sans-serif;
  line-height: 1.3
}
     

.wf-inactive indicates that loading the font or fonts (in this case we are using one) has not started. To make sure that the user doesn’t see a system fault we provide a fallback option while the web font(s) are loading. This may be an instant or maybe several seconds in a slow or congested network connection (try Starbucks on a Sunday afternoon.)

Once the font(s) load, the class will switch to .wf-active where we put out web font stack and attributes related to font. In this case I only added a different line-height attribute to the selector but you can be as detailed as you want.

One last detail: What happens if Javascript is disabled?

If you’re fonts are loaded from google you can revert back to using the Google API to load your fonts. You can do something like:

<noscript>
  <link href='http://fonts.googleapis.com/css?family=Roboto:700italic,300,700,300italic' rel='stylesheet' type='text/css'>
</noscript>

Font Face Observer

As good as the Webfont Loader is good it causes some Flash of Invisible text when the fonts load and the browser switches from the system fonts to the webfonts it just loaded. The script for the Webfont Loader must be placed in the head of the document with all the performance pitfalls inherent to it.

Font Face Observer, a fairly new delivery mechanism developed by Adobe Typekit engineer Bram Stein, uses JavaScript’s scroll events to load and monitor web fonts. Unlike the Web Font Loader, the Font Face Observer can be referenced at the end of document to avoid the extra overhead. Scott Jehl’s approach, as documented in the Filament’s Group blog and is the system we’ll discuss below. The full page is shown below and will be explained as we go along.

<!DOCTYPE html>
<!--#if expr="$HTTP_COOKIE=/fonts\-loaded\=true/" -->
<html lang="en" class="fonts-loaded">
<!--#else -->
<html lang="en">
<!--#endif -->
<head>
  <meta charset="utf-8">
  <title></title>
  <meta name="viewport" content="width=device-width">
  <style>
  @font-face {
    font-family: 'Lora';
      src: url('lora-regular.woff2') format('woff2'),
           url('lora-regular.woff') format('woff'),
           url('lora-regular.ttf') format('truetype');
    font-weight: 400;
    font-style: normal;
  }
  @font-face {
    font-family: 'Lora';
      src: url('lora-italic.woff2') format('woff2'),
           url('lora-italic.woff') format('woff'),
           url('lora-italic.ttf') format('truetype');
    font-weight: 400;
    font-style: italic;
    }
    body {
        font-family: serif;
  }
    .fonts-loaded body {
        font-family: Lora, serif;
  }
</style>
</head>
<body>
    <p><!-- paragraph text --></p>
    <script src="fontfaceobserver.js"></script>
    <script>
    (function( w ){
    if( w.document.documentElement.className.indexOf( "fonts-loaded" ) > -1 ){
        return;
    }
    var font1 = new w.FontFaceObserver( "Lora", {
        weight: 400
    });
    var font2 = new w.FontFaceObserver( "Lora", {
        weight: 400,
        style: "italic"
    });
    w.Promise
        .all([font1.check(), font2.check()])
        .then(function(){
            w.document.documentElement.className += " fonts-loaded";
        });
    }( this ));
    </script>
</body>
</html>

The first thing we do is to use Server Side Includes, a way to have the server generate pieces of content for the web, to add the fonts-loaded CSS class if the corresponding cookie has already been set. In this way the loader will only use the fonts if they’ve been already been loaded, otherwise it will not add the class and the process will continue.

<!--#if expr="$HTTP_COOKIE=/fonts\-loaded\=true/" -->
<html lang="en" class="fonts-loaded">
<!--#else -->
<html lang="en">

While still in the head of the document we load our fonts using the @font-face syntax we discussed earlier and associate the fonts with the css needed. Note that we have two classes for the body, a plain one where only system fonts are used and a version with the fonts-loaded class where the webfont is the primary and the system font is our backup.

  <style>
  @font-face {
    font-family: 'Lora';
      src: url('lora-regular.woff2') format('woff2'),
       url('lora-regular.woff') format('woff'),
       url('lora-regular.ttf') format('truetype');
    font-weight: 400;
    font-style: normal;
  }
  @font-face {
    font-family: 'Lora';
      src: url('lora-italic.woff2') format('woff2'),
       url('lora-italic.woff') format('woff'),
       url('lora-italic.ttf') format('truetype');
    font-weight: 400;
    font-style: italic;
  }

  body {
    font-family: serif;
  }
  .fonts-loaded body {
    font-family: Lora, serif;
  }
</style>

At the bottom of our pages, along with all the other scripts, we add a link to the fontfaceobserver library. The second script begins with a conditional check to see if the class-loaded class hs been added to the root element (html); if it has been then quit, there is nothing left to do.

We next define variables for each of the fonts we will use in our document. This will be used in the last part of the script, discussed below.

<script src="fontfaceobserver.js"></script>
<script>
(function( w ){
  if( w.document.documentElement.className.indexOf( "fonts-loaded" ) > -1 ){
      return;
  }
  var font1 = new w.FontFaceObserver( "Lora", {
      weight: 400
  });
  var font2 = new w.FontFaceObserver( "Lora", {
      weight: 400,
      style: "italic"
  });
    

The last part of the script uses a JavaScript promise. Once both promises fulfill it will add the fonts-loaded class to the document (root) element, in this case, html.

w.Promise
  .all([font1.check(), font2.check()])
  .then(function(){
      w.document.documentElement.className += " fonts-loaded";
  });
}( this ));
    </script>

The next result is that the fonts will be loaded asynchronously and that the system font assigned to an element will only change after the font has loaded. This prevents flashes of unstyled content and flashes of invisible content. But in the end which font loading strategy you use is up to you.

Links and Resources