or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

index.mddocs/

Critters

Critters is a fast and lightweight critical CSS inlining library that processes HTML documents to inline critical CSS rules directly into style tags and lazy-loads remaining stylesheets. Unlike solutions that rely on headless browsers, Critters analyzes CSS selectors against reconstructed DOM structures for speed and efficiency, making it ideal for improving first paint performance in Single Page Applications and server-side rendered websites.

Package Information

  • Package Name: critters
  • Package Type: npm
  • Language: JavaScript/TypeScript
  • Installation: npm install critters

Core Imports

import Critters from "critters";

For CommonJS:

const Critters = require("critters");

Basic Usage

import Critters from "critters";

const critters = new Critters({
  path: "/path/to/css/files",
  pruneSource: false,
  preload: "swap"
});

const html = `
  <html>
    <head>
      <link rel="stylesheet" href="/styles.css">
    </head>
    <body>
      <h1>Hello World!</h1>
      <p class="content">This is a paragraph</p>
    </body>
  </html>
`;

const inlinedHtml = await critters.process(html);
console.log(inlinedHtml);
// Output: HTML with critical CSS inlined and remaining CSS lazy-loaded

Architecture

Critters is built around several key components:

  • Main Class: Critters class that handles the complete critical CSS processing workflow
  • CSS Processing: PostCSS-based stylesheet parsing, rule filtering, and optimization
  • DOM Analysis: HTML parsing and CSS selector existence checking without headless browsers
  • Preload Strategies: Multiple lazy-loading strategies for non-critical CSS (media, swap, js, etc.)
  • Font Handling: Critical font-face inlining and font preloading capabilities
  • Configuration System: Extensive options for customizing critical CSS extraction behavior

Capabilities

Critical CSS Processing

Core functionality for processing HTML documents to inline critical CSS and lazy-load remaining stylesheets.

class Critters {
  /**
   * Create an instance of Critters with custom options.
   * The process() method can be called repeatedly to re-use this instance and its cache.
   */
  constructor(options?: Options);

  /**
   * Process an HTML document to inline critical CSS from its stylesheets.
   * @param html - String containing a full HTML document to be parsed
   * @returns A modified copy of the provided HTML with critical CSS inlined
   */
  process(html: string): Promise<string>;

  /**
   * Read the contents of a file from the specified filesystem or disk.
   * Override this method to customize how stylesheets are loaded.
   */
  readFile(filename: string): Promise<string> | string;

  /**
   * Given a stylesheet URL, returns the corresponding CSS asset.
   * Overriding this method requires doing your own URL normalization, 
   * so it's generally better to override readFile().
   */
  getCssAsset(href: string): Promise<string | undefined> | string | undefined;
}

Usage Examples:

import Critters from "critters";

// Basic usage with file system paths
const critters = new Critters({
  path: "./dist/css",
  external: true,
  inlineThreshold: 0
});

const result = await critters.process(htmlString);

// Custom file reading for different environments
const crittersCustom = new Critters();
crittersCustom.readFile = async (filename) => {
  // Custom logic to read from CDN, database, etc.
  return await fetch(filename).then(res => res.text());
};

// Webpack integration example
const critters = new Critters({
  path: path.resolve(__dirname, 'dist'),
  publicPath: '/assets/',
  pruneSource: true,
  mergeStylesheets: true
});

Configuration Options

Comprehensive configuration options for customizing critical CSS processing behavior.

interface Options {
  /** Base path location of the CSS files (default: '') */
  path?: string;
  /** Public path of the CSS resources. This prefix is removed from the href (default: '') */
  publicPath?: string;
  /** Inline styles from external stylesheets (default: true) */
  external?: boolean;
  /** Inline external stylesheets smaller than a given size (default: 0) */
  inlineThreshold?: number;
  /** If the non-critical external stylesheet would be below this size, just inline it (default: 0) */
  minimumExternalSize?: number;
  /** Remove inlined rules from the external stylesheet (default: false) */
  pruneSource?: boolean;
  /** Merge inlined stylesheets into a single <style> tag (default: true) */
  mergeStylesheets?: boolean;
  /** Glob for matching other stylesheets to be used while looking for critical CSS */
  additionalStylesheets?: string[];
  /** Which preload strategy to use */
  preload?: PreloadStrategy;
  /** Add <noscript> fallback to JS-based strategies */
  noscriptFallback?: boolean;
  /** Inline critical font-face rules (default: false) */
  inlineFonts?: boolean;
  /** Preload critical fonts (default: true) */
  preloadFonts?: boolean;
  /** Shorthand for setting inlineFonts + preloadFonts */
  fonts?: boolean;
  /** Controls which keyframes rules are inlined */
  keyframes?: KeyframeStrategy;
  /** Compress resulting critical CSS (default: true) */
  compress?: boolean;
  /** Controls log level of the plugin (default: 'info') */
  logLevel?: LogLevel;
  /** Evaluate inline styles for critical CSS (default: true) */
  reduceInlineStyles?: boolean;
  /** Provide a custom logger interface */
  logger?: Logger;
  /** Function or RegExp to filter stylesheets for processing */
  filter?: (href: string) => boolean | RegExp;
  /** Array of CSS selectors (string or RegExp) that should always be included in critical CSS */
  allowRules?: (string | RegExp)[];
}

Preload Strategies

Multiple strategies for lazy-loading non-critical CSS with different performance characteristics.

/**
 * The mechanism to use for lazy-loading stylesheets.
 * JS indicates a strategy requiring JavaScript (falls back to <noscript> unless disabled).
 */
type PreloadStrategy = 
  | "default"    // Move stylesheet links to end and insert preload meta tags
  | "body"       // Move all external stylesheet links to end of document
  | "media"      // Load asynchronously by adding media="not x" and removing once loaded (JS)
  | "swap"       // Convert stylesheet links to preloads that swap to rel="stylesheet" once loaded (JS)
  | "swap-high"  // Use <link rel="alternate stylesheet preload"> and swap to rel="stylesheet" once loaded (JS)
  | "js"         // Inject asynchronous CSS loader similar to LoadCSS and use it to load stylesheets (JS)
  | "js-lazy"    // Like "js", but the stylesheet is disabled until fully loaded
  | false;       // Disables adding preload tags

Usage Examples:

// Default preload strategy
const critters = new Critters({
  preload: "default" // or omit for default behavior
});

// Media-based lazy loading with JavaScript fallback
const critters = new Critters({
  preload: "media",
  noscriptFallback: true
});

// High-performance swap strategy
const critters = new Critters({
  preload: "swap-high",
  noscriptFallback: true
});

// Disable preloading entirely
const critters = new Critters({
  preload: false
});

Font Handling

Advanced font processing capabilities for critical font-face rules and font preloading.

// Font-related options in the Options interface
{
  /** Inline critical font-face rules (default: false) */
  inlineFonts?: boolean;
  /** Preload critical fonts (default: true) */
  preloadFonts?: boolean;
  /** Shorthand for setting inlineFonts + preloadFonts */
  fonts?: boolean;
}

Usage Examples:

// Enable both font inlining and preloading
const critters = new Critters({
  fonts: true // shorthand for inlineFonts: true, preloadFonts: true
});

// Custom font handling
const critters = new Critters({
  inlineFonts: true,  // Inline critical @font-face rules
  preloadFonts: false  // Don't preload fonts
});

// Only preload fonts, don't inline
const critters = new Critters({
  inlineFonts: false,
  preloadFonts: true
});

CSS Rule Control

Fine-grained control over which CSS rules are included or excluded from critical CSS processing.

CSS Comments:

/* critters:include */
.always-critical {
  /* this rule will be included in critical CSS */
}

/* critters:exclude */
.never-critical {
  /* this rule will be excluded from critical CSS */
}

/* critters:include start */
.critical-section-1 { }
.critical-section-2 { }
/* critters:include end */

/* critters:exclude start */
.non-critical-section-1 { }
.non-critical-section-2 { }
/* critters:exclude end */

Keyframe Management

Control over CSS keyframe rule processing for animations.

/**
 * Controls which keyframes rules are inlined.
 */
type KeyframeStrategy = 
  | "critical"  // (default) inline keyframes rules that are used by the critical CSS
  | "all"       // Inline all keyframes rules
  | "none";     // Remove all keyframes rules

Usage Examples:

// Include only keyframes used by critical CSS (default)
const critters = new Critters({
  keyframes: "critical"
});

// Include all keyframes
const critters = new Critters({
  keyframes: "all"
});

// Remove all keyframes
const critters = new Critters({
  keyframes: "none"
});

Logging and Debugging

Configurable logging system for monitoring critical CSS processing.

/**
 * Controls log level of the plugin. Specifies the level the logger should use.
 * A logger will not produce output for any log level beneath the specified level.
 */
type LogLevel = 
  | "info"     // (default)
  | "warn"
  | "error"
  | "trace"
  | "debug"
  | "silent";

/**
 * Custom logger interface
 */
interface Logger {
  trace?: (message: string) => void;
  debug?: (message: string) => void;
  info?: (message: string) => void;
  warn?: (message: string) => void;
  error?: (message: string) => void;
}

Usage Examples:

// Set log level
const critters = new Critters({
  logLevel: "warn" // Only show warnings and errors
});

// Custom logger
const critters = new Critters({
  logger: {
    info: (msg) => console.log(`[CRITTERS] ${msg}`),
    warn: (msg) => console.warn(`[CRITTERS WARNING] ${msg}`),
    error: (msg) => console.error(`[CRITTERS ERROR] ${msg}`)
  }
});

// Silent mode
const critters = new Critters({
  logLevel: "silent"
});

CSS Rule Filtering

Control which stylesheets are processed and which CSS rules are always included in critical CSS.

Usage Examples:

// Filter stylesheets by URL pattern
const critters = new Critters({
  filter: (href) => href.includes('critical') || href.endsWith('.critical.css')
});

// Use RegExp filter
const critters = new Critters({
  filter: /\.(critical|inline)\.css$/
});

// Always include specific selectors in critical CSS
const critters = new Critters({
  allowRules: [
    '.always-critical',
    /^\.btn-/,  // All button classes
    '.header', '.footer'
  ]
});

// Combined filtering
const critters = new Critters({
  filter: (href) => !href.includes('vendor'),
  allowRules: ['.critical-component', /^\.layout-/]
});

Types

/**
 * Main Critters class for critical CSS processing
 */
export default class Critters {
  constructor(options?: Options);
  process(html: string): Promise<string>;
  readFile(filename: string): Promise<string> | string;
  getCssAsset(href: string): Promise<string | undefined> | string | undefined;
}

/**
 * Configuration options for Critters constructor
 */
export interface Options {
  path?: string;
  publicPath?: string;
  external?: boolean;
  inlineThreshold?: number;
  minimumExternalSize?: number;
  pruneSource?: boolean;
  mergeStylesheets?: boolean;
  additionalStylesheets?: string[];
  preload?: PreloadStrategy;
  noscriptFallback?: boolean;
  inlineFonts?: boolean;
  preloadFonts?: boolean;
  fonts?: boolean;
  keyframes?: KeyframeStrategy;
  compress?: boolean;
  logLevel?: LogLevel;
  reduceInlineStyles?: boolean;
  logger?: Logger;
  /** Function or RegExp to filter stylesheets for processing */
  filter?: (href: string) => boolean | RegExp;
  /** Array of CSS selectors (string or RegExp) that should always be included in critical CSS */
  allowRules?: (string | RegExp)[];
}

/**
 * Custom logger interface
 */
export interface Logger {
  trace?: (message: string) => void;
  debug?: (message: string) => void;
  info?: (message: string) => void;
  warn?: (message: string) => void;
  error?: (message: string) => void;
}

/**
 * Preload strategy for lazy-loading stylesheets
 */
export type PreloadStrategy = 
  | "default" | "body" | "media" | "swap" | "swap-high" | "js" | "js-lazy" | false;

/**
 * Keyframe processing strategy
 */
export type KeyframeStrategy = "critical" | "all" | "none";

/**
 * Logging level specification
 */
export type LogLevel = "info" | "warn" | "error" | "trace" | "debug" | "silent";