Skip to content

iveelsm/astro-font-loader

Repository files navigation

Astro Font Loader

typescript astro

astro-font-loader hooks into the astro build process to copy selected fonts from installed font packages into the local build artifacts.

Installation

# Using npm
npm i astro-font-loader

# Using yarn
yarn add astro-font-loader

# Using pnpm
pnpm add astro-font-loader

How It Works

  1. Setup Phase: During Astro's config setup, the integration:

    • Locates the specified font packages in your node_modules
    • Applies the filter function (if provided) to select fonts
    • Prepares the list of fonts to be copied
  2. Build Phase: After Astro completes the build:

    • Copies the filtered font files to the output directory
    • Transforms CSS imports to reference the copied fonts
    • Ensures fonts are available in your production build

Usage

Basic Setup

Add the integration to your astro.config.mjs or astro.config.ts file:

import { defineConfig } from 'astro/config';
import { fontsIntegration } from 'astro-font-loader';

export default defineConfig({
  site: 'https://example.com',
  integrations: [
    fontsIntegration({
      packages: ["@company/design-system-fonts"],
    }),
  ],
});

Filtering Fonts

Use the filter option to selectively include only specific fonts from your font packages. This is useful when you have a large font library but only need certain fonts for your project:

import { defineConfig } from 'astro/config';
import { fontsIntegration } from 'astro-font-loader';

// Define a filter function to select specific fonts
const fontFilter = (filename: string) => {
  const name = filename.toLowerCase();
  return name.includes("hatton") || 
         name.includes("berkeleymono");
};

export default defineConfig({
  site: 'https://example.com',
  integrations: [
    fontsIntegration({
      packages: ["@company/design-system-fonts"],
      filter: fontFilter,
    }),
  ],
});

Custom Output Directory

By default, fonts are copied to a fonts directory in your build output. You can customize this:

fontsIntegration({
  packages: ["@company/design-system-fonts"],
  filter: fontFilter,
  outputDir: "assets/fonts", // Custom output directory
})

Multiple Font Packages

You can load fonts from multiple packages:

fontsIntegration({
  packages: [
    "@company/design-system-fonts",
    "@fontsource/roboto",
    "@custom/typefaces"
  ],
  filter: (filename) => {
    // Only include specific fonts from all packages
    const name = filename.toLowerCase();
    return name.includes("hatton") ||
           name.includes("berkeleymono") ||
           name.includes("roboto-400");
  },
})

FontLoader Component

The library provides a FontLoader Astro component that generates <link rel="preload"> tags and inline @font-face CSS for your fonts. Use it alongside the integration — the integration copies font files to the build output, while the component injects the HTML needed to load them.

---
// src/layouts/Layout.astro
import FontLoader from 'astro-font-loader/FontLoader.astro';
---
<html>
  <head>
    <FontLoader packages={['@company/design-system-fonts']} />
  </head>
  <body><slot /></body>
</html>

The component accepts the same filter and outputDir options as the integration:

---
import FontLoader from 'astro-font-loader/FontLoader.astro';

const fontFilter = (filename: string) =>
  filename.toLowerCase().includes('roboto');
---
<FontLoader
  packages={['@company/design-system-fonts']}
  filter={fontFilter}
  outputDir="assets/fonts"
/>

Selective Preloading with Media Queries

The preload prop accepts an array of configurations for fine-grained control over which fonts are preloaded and with what media queries. This is useful for responsive font loading — for example, preloading a bold weight only on desktop:

---
import FontLoader from 'astro-font-loader/FontLoader.astro';

const fontFilter = (filename: string) =>
  filename.toLowerCase().includes('roboto');
---
<FontLoader
  packages={['@company/design-system-fonts']}
  filter={fontFilter}
  preload={[
    {
      filter: (f) => f.includes('roboto-regular'),
    },
    {
      filter: (f) => f.includes('roboto-bold'),
      media: '(min-width: 641px)',
    },
  ]}
/>
Prop Type Default Description
packages string[] (required) Font package names to load
filter (filename: string) => boolean undefined Filter function to select font files
outputDir string "fonts" Output directory name in generated URLs
preload boolean | PreloadConfig[] true Whether/how to generate preload link tags
root string process.cwd() Root directory for resolving font packages

PreloadConfig

Property Type Required Description
filter (filename: string) => boolean Yes Filter to select which fonts to preload
media string No Media query for the preload link

Additional Documentation

About

Loads fonts from custom font packages

Topics

Resources

License

Stars

Watchers

Forks

Contributors