npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

onfontready

v1.1.0

Published

Font load and parse detection with minimal size and maximum compatibility.

Downloads

15

Readme

onfontready 1.1.0

Font load and parse detection with minimal size and maximum compatibility.

Features

Install

Installation via NPM:

npm install --save onfontready

Installation via yarn:

yarn add onfontready

Pre-built distribution versions from the dist directory:

Basic Usage

Here is a very simple example usage that prevents FOIT, but will timeout the font loading attempt after 5 seconds. For more advanced usage, read Recipes and Usage Patterns.

  1. Import the desired font.

    • Describe a @font-face in CSS. (Using Font-Face at CSS-Tricks).

      @font-face {
          font-family: 'MyWebFont';
          src: url('myTheme/fonts/webfont.woff2') format('woff2'),
               url('myTheme/fonts/webfont.woff') format('woff');
      }
    • Or import the font using a web font service, such as Google Fonts.

      <link href="https://fonts.googleapis.com/css?family=Comfortaa" rel="stylesheet">
  2. Include onfontready.

    • Inline onfontready at the bottom of the HTML (recommended).

      <html>
          ...
          <script>
              // From onfontready.min.js
              window.onfontready=...;
          </script>
      </html>
    • Or use script src to import onfontready at the bottom of the HTML.

      <html>
          ...
          <script src="dist/onfontready.min.js"></script>
      </html>
    • Or include onfontready into Javascript codebase via CommonJS.

      var onfontready = require('onfontready');
  3. Call onfontready with appropriate options. This pattern attempts to load the font, but will timeout after 5 seconds. Read Recipes and Usage Patterns for more options and usage patterns.

    onfontready('MyWebFont', function() {
        document.documentElement.className += " fontLoaded";
    }, {
        timeoutAfter: 5000, // 5 seconds in milliseconds
        onTimeout: function() {
            document.documentElement.className += " fontNotLoaded";
        }
    });
  4. Define actions to take upon successful load (onReady is called) and/or load failure (options.onTimeout is called). In this pattern, fancyFontElement initially uses a sans-serif font. If the font loads successfully, the element will use the MyWebFont font. If the font fails to load, the element will use the monospace font and have grey text.

    .fancyFontElement {
        font-family: sans-serif;
    }
    
    .fontNotLoaded .fancyFontElement {
        font-family: monospace;
        color: #ddd;
    }
    
    .fontLoaded .fancyFontElement {
        font-family: 'MyWebFont', sans-serif;
    }

There are many other patterns possible. For example:

  • localStorage APIs can be used to optimize for second load.
  • Emulate font loading behavior of other browsers.
  • FOUT flickering can be prevented on first load.
  • Generic font family support can be detected.
  • Local installs of fonts can be detected.
  • Multiple fonts can be loaded or timed out as a unit.

Read Recipes and Usage Patterns for more.

API

By default, the onfontready function is attached to the window object. Using CommonJS, the function becomes available via the require() syntax. The function has two required arguments and one optional argument.

onfontready(fontName, onReady, [options={}])
  • fontName - (string) Name used in @font-face declaration, font name on the local client machine, or generic font family name.
  • onReady - (function callback) Called upon successful detection of the font's load and parse by the browser. No parameters.
  • options - (Object) Optional object for settings.
    • options.timeoutAfter - (number) Milliseconds waited before calling options.onTimeout callback. onfontready will wait indefinitely if options.timeoutAfter is unset or 0. Negative numbers are allowed and act as a "fast" timeout.
    • options.onTimeout - (function callback) Called after options.timeoutAfter milliseconds have elapsed without an onReady call.
    • options.generic - (boolean) Causes onfontready to detect generic font families like fantasy, cursive, san-serif, or BlinkMacSystemFont if set to true.
    • options.sampleText - (string) Text used for font width testing. This option should only be used for fonts that have no space character. There is only one known font without a space character.

Foundational Structure

onfontready only detects when fonts are loaded and parsed by a browser. It is intended to do only one thing, and serve as the foundation for more sophisticated tools.

Compression

onfontready has been code-golfed for gzip output size, not minified size. It is probably the smallest font detection library possible without setTimeout polling. To achieve this, onfontready contains some 'bad-practice' code structures and lots of seemingly unnecessary repetition. Code should always be gzipped, so the gzip size is ultimately more important than the minified size.

As this table demonstrates, onfontready is significantly smaller than comparable font detection libraries. All values are in bytes.

| Compression | onfontready | onfontready legacy | FontFaceObserver ◦ | |-------------|---------------|----------------------|--------------------| | Minified * | 901 | 1393 | 3981 | | gzip † | 371 | 444 | 1479 | | zopfli ‡ | 368 | 434 | 1463 | | brotli ¶ | 277 | 327 | 1209 |

* - UglifyJS was used for minification.
† - gzip level 6, the default compression level.
‡ - Zopfli, an exhaustive search compression. It typically produces the smallest possible gzip-compatible output.
¶ - Brotli, a new higher-performing compression available to some modern browsers over HTTPS connections.
◦ - FontFaceObserver Standalone version 2.0.5 included for comparison. FontFaceObserver was already minified using the Google Closure compiler. For the table above, the minified code was run through UglifyJS to further compress it. Without UglifyJS, the compressed sizes would be larger for FontFaceObserver.

To learn more, read about the Compression Techniques used and read through the fully-commented source code.

Motivation

I was attempting to build a website with a size budget of less than 14KB gzipped for all HTML, CSS, JS, SVGs, and some inline images. I encountered a strange issue with inline SVGs (described below), which prompted me to research font loading in detail. The library I had been using, FontFaceObserver, while small, still accounts for over 1KB when gzipped, which was a huge dent in my size budget. Using ideas from Back Alley Coder's Element Resize Detector, font load detection can be done on any browser without resorting to setTimeout polling at a much smaller size.

Considerations

  • Several missing features in IE6, IE7, and IE8 necessitate the use of the legacy version of onfontready. IE9+ and all modern browsers can use standard onfontready. If IE8 or lower support is desired, use the legacy version.
  • Standard onfontready must create styled div and iframe elements. The legacy version of onfontready uses div, iframe, table, tbody, tr, and td tags. Any CSS styles applied via stylesheets or style tags that are applied globally to these elements, as well as any styles that directly influence page fonts (such as body { font-size: 0; }) may interfere with the font load detection. Please use CSS classes when specifying styling behavior for these elements to avoid incorrect detection.
  • onfontready takes steps to produce reasonable results even if the library is used incorrectly. However, IE6 and IE7 have several quirks when dealing with fallback fonts and generic font names that can cause some unintended results when using onfontready incorrectly. For full details, see the IE6 and IE7 notes in the Main Tests.

Known SVG Issue

A strange rendering bug can occur in Safari. This bug was the inspiration for the creation of onfontready.

In Safari, if...

  1. A font is switched at some critical moment during the page load process (such as with a font load detection library like onfontready), and
  2. The page contains inline SVGs that use remote SVG resources containing either SVG masks or SVG filters, and
  3. The remote reference SVG is positioned absolute or fixed, then
  4. The custom font may either render as invisible or as the fallback font until the next page repaint.

More details here. This can be mitigated by applying style="display:block;height:0" to the inline SVG tag acting as the remote SVG, rather than trying to absolutely position it.

Future Plans

  • Add ES module support once tooling becomes realistic.
  • Produce a new modern version specifically for browsers with ES6 (ES2015) native support as the world switches to those browsers.
  • Make note about the upcoming font-display feature, which can alleviate the need for much of onfontready in very new browsers.
  • Add support for ResizeObserver-based detection when it becomes more widely supported, using the iframe resize method as the fallback.
  • Investigate source-code permutation techniques to generate the smallest possible compressed sizes by mere rearrangement of order-independent code and alternate equivalent structures.