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

use-font-metrics

v0.3.0

Published

React hooks for font metrics

Downloads

22

Readme

use-font-metrics - React hooks for font metrics

Features

  • Measure text width, font baseline, and other font metrics, for Win or Typo metrics on node.js and in the browser
  • Metrics extracted from font files using @pdf-lib/fontkit. Does not use the HTML5 Canvas API

Install

npm install use-font-metrics

Quickstart

Lets write a React component that measures the width of Hello World rendered in Inter 16px:

  1. Place a stylesheet referencing the font at src/fonts.css:
    @font-face {
      font-family: Inter;
      src: url(./fonts/Inter-Regular.otf);
    }
  2. Add the font file to your bundle - place the otf font file at src/fonts/Inter-Regular.otf. You can download it from google fonts. You could also set the font source to some cloud font provider. Metrics will be available for every font found in a @font-face rule.
  3. Wrap your component with a FontManager context. Using the top-level src/index.tsx for example:
    import { withFontManager, FontProvider } from 'use-font-metrics';
    import './fonts.css'; // @font-face fonts will be loaded
    
    withFontManager(
      fm => void ReactDOM.render(
        <FontProvider fontManager={fm}>
          <App />
        </FontProvider>
      ),
      document.getElementById('root'),
    );
  4. With a font manager in context, any component under <FontProvider> can use the font metric hooks:
import { useHMetrics } from 'use-font-metrics';

export const MyComponent = () => {
  const { width } = useHMetrics({
    fontFamily: 'Inter',
    fontSize: 16, // px
    text: 'Hello World',
  });
  return <div>“Hello World” width: {width}px</div>;
}

Demo screenshots

Demos

  1. Quickstart - the Quickstart example source
  2. Horizontal Metrics - measure text width and chop off advanceWidth source
  3. Vertical Metrics - display font baseline and xHeight source
  4. Fit Text Height - Resize the browser window to see text capHeight sizing to DOM element height source

Motivation

Some HTML layout problems require font metrics. For example:

  • Fit text to an area
  • Align text horizontally despite the tiny advanceLeft/advanceRight browsers add around glyphs
  • Resize multi-font text, required because equal fontSize does not imply equal capHeight

There are hacks for doing this with no font metrics, and without hurting accuracy much, but there are also hacks that allow you to scratch your upper back with your foot. These are all highly sub-optimal, so W3C added text metrics to the Canvas API.

Support as of 2021 AD is still incomplete, and there are some other issues:

  • Requires Canvas. Would be nice to get these directly from the font file. Should not cost anything because we are surely loading the font if we need its metrics
  • API encapsulates away the distinction between the two sets of metrics browsers use, as explained here
  • Sometime you need all the metrics

This is a stopgap until browsers do this.

How It Works

A tiny React/Typescript wrapper around this fork of the fontkit library, wired to load remote fonts, and pass their metrics to any inquiring hooks.

Usage

Loading Fonts

The hooks expect a FontContext in scope, holding a FontManager. The font manager caches loaded fonts.

The easiest way to load the fonts and provide the context is shown in the Quickstart above: add your fonts to a stylesheet, use withFontManager to create a font manager, and <FontProvider> to inject it into the context. For other use cases you may want to create your own font manager and explicitly set loaded fonts.

Node

In Node you can load local fonts:

import { FetchFont, FontManager, loadLocalFonts } from 'use-font-metrics';

const fonts: FetchFont[] = [
  {
    fontFamily: 'myfont',
    src: 'path/to/font.ttf',
  },
];
const fontManager: FontManager = loadLocalFonts(...fonts);

Browser

In the browser you can load remote fonts using loadFontsAsync:

import { FontManager, loadFontsAsync } from 'use-font-metrics';

const fonts: FetchFont[] = [
  {
    fontFamily: 'myfont',
    src: 'http://url/of/font.ttf',
  },
];
const fontManager: Promise<FontManager> = loadFontsAsync(...fonts);

If your fonts are already defined in the @font-face rules of some loaded stylesheet, you can create a font manager from all the rules of all loaded stylesheets using:

import { FontManager, loadStyleSheetFonts } from 'use-font-metrics';

const fontManager: FontManager = loadStyleSheetFonts();

Hooks

You can access the loaded fonts and their metrics directly from the font manager, as in this demo, or you can use one of the hooks:

  • useWinBaseline/useMacBaseline(fontFamily: string, fontSize: number, lineHeight: number = 1) - distance between top of text line and font baseline
  • useHMertics({fontFamily: string; fontSize: number, text: string}) - returns text horizontal measurement in a record with numeric width and textIndent keys in pixel
  • useHMerticsStyle({fontFamily: string; fontSize: number; text: string;}) - same as useHMetrics but returns a CSS Style object that you can use for the element of the measured text

See Also