CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-css-inline--css-inline

High-performance library for inlining CSS into HTML 'style' attributes

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

CSS Inline

CSS Inline is a high-performance library for inlining CSS into HTML 'style' attributes. It's designed for scenarios such as preparing HTML emails or embedding HTML into third-party web pages where external stylesheets cannot be loaded.

Package Information

  • Package Name: @css-inline/css-inline
  • Package Type: npm
  • Language: JavaScript/TypeScript
  • Installation: npm install @css-inline/css-inline

Core Imports

import { inline, inlineFragment, version } from "@css-inline/css-inline";

For CommonJS:

const { inline, inlineFragment, version } = require("@css-inline/css-inline");

For WebAssembly (browser):

import { initWasm, inline, inlineFragment, version } from "@css-inline/css-inline/wasm-binding";

Basic Usage

import { inline } from "@css-inline/css-inline";

// Inline CSS from a complete HTML document
const html = `
<html>
  <head>
    <style>h1 { color: blue; }</style>
  </head>
  <body>
    <h1>Big Text</h1>
  </body>
</html>
`;

const inlinedHtml = inline(html);
// Result: <html><head></head><body><h1 style="color: blue;">Big Text</h1></body></html>

Architecture

CSS Inline operates through two execution environments:

  • Node.js Native: Uses Rust-based native bindings via NAPI for maximum performance
  • WebAssembly: Provides browser compatibility with limited functionality (no caching, no remote/local stylesheet loading)

The library processes HTML documents by:

  1. Parsing HTML and CSS using components from Mozilla's Servo project
  2. Applying CSS selectors to matching HTML elements
  3. Converting matched CSS rules to inline style attributes
  4. Removing original <style> and <link> tags (configurable)

Capabilities

HTML Document Inlining

Complete HTML document processing that inlines CSS from <style> tags and external stylesheets referenced by <link> tags.

/**
 * Inline CSS styles from <style> tags to matching elements in the HTML tree
 * @param html - Complete HTML document to process
 * @param options - Configuration options for inlining behavior
 * @returns HTML document with CSS inlined into style attributes
 */
function inline(html: string, options?: Options | undefined | null): string;

Usage Examples:

import { inline } from "@css-inline/css-inline";

// Basic inlining
const result = inline(`
<html>
  <head>
    <style>
      h1 { color: red; }
      p { font-size: 14px; }
    </style>
  </head>
  <body>
    <h1>Title</h1>
    <p>Paragraph</p>
  </body>
</html>
`);

// With external stylesheet
const resultWithExternalCSS = inline(`
<html>
  <head>
    <link href="styles.css" rel="stylesheet">
  </head>
  <body>
    <h1>Title</h1>
  </body>
</html>
`, { baseUrl: "file:///path/to/stylesheets/" });

// With caching for performance
const resultWithCache = inline(html, {
  cache: { size: 10 },
  loadRemoteStylesheets: true
});

HTML Fragment Inlining

Process HTML fragments (partial HTML without full document structure) by applying provided CSS styles directly.

/**
 * Inline CSS styles into an HTML fragment
 * @param html - HTML fragment to process (no <html>, <head>, or <body> required)
 * @param css - CSS styles to apply to the fragment
 * @param options - Configuration options for inlining behavior
 * @returns HTML fragment with CSS inlined into style attributes
 */
function inlineFragment(html: string, css: string, options?: Options | undefined | null): string;

Usage Examples:

import { inlineFragment } from "@css-inline/css-inline";

// Process a fragment
const fragment = `
<main>
  <h1>Hello</h1>
  <section>
    <p>Content here</p>
  </section>
</main>
`;

const css = `
h1 { color: blue; }
p { color: red; font-size: 16px; }
`;

const result = inlineFragment(fragment, css);
// Result: <main><h1 style="color: blue;">Hello</h1><section><p style="color: red; font-size: 16px;">Content here</p></section></main>

Version Information

Get the current package version for debugging or compatibility checks.

/**
 * Get the package version
 * @returns Package version string
 */
function version(): string;

WebAssembly Initialization

Initialize the WebAssembly module before using WASM variant functions. Required for browser usage.

/**
 * Initialize Wasm module (WASM variant only)
 * @param module_or_path - WebAssembly Module or .wasm file URL
 * @returns Promise that resolves when initialization is complete
 * @throws Error if called multiple times
 */
function initWasm(module_or_path: Promise<InitInput> | InitInput): Promise<void>;

Usage Example:

import { initWasm, inline } from "@css-inline/css-inline/wasm-binding";
import { promises as fs } from "fs";

// Initialize WASM module first (only once per session)
await initWasm(fs.readFile("path/to/index_bg.wasm"));

// Now use the API normally (no remote stylesheets or caching supported)
const result = inline(htmlContent);

WASM Limitations:

  • No remote stylesheet loading (HTTP/HTTPS URLs not supported)
  • No local file system access
  • No caching support
  • Different error messages for unsupported operations

Configuration

Options Interface

interface Options {
  /** Whether to inline CSS from "style" tags (default: true) */
  inlineStyleTags?: boolean;
  /** Keep "style" tags after inlining (default: false) */
  keepStyleTags?: boolean;
  /** Keep "link" tags after inlining (default: false) */
  keepLinkTags?: boolean;
  /** Base URL for resolving relative stylesheet URLs */
  baseUrl?: string;
  /** Whether remote stylesheets should be loaded (default: true) */
  loadRemoteStylesheets?: boolean;
  /** LRU cache for external stylesheets (Node.js only) */
  cache?: StylesheetCache;
  /** Additional CSS to inline beyond document styles */
  extraCss?: string;
  /** Pre-allocate HTML node capacity for performance (default: 32) */
  preallocateNodeCapacity?: number;
}

StylesheetCache Interface

interface StylesheetCache {
  /** Cache size - must be integer greater than zero */
  size: number;
}

WebAssembly Types

interface InlineOptions {
  /** Whether to inline CSS from "style" tags (default: true) */
  inlineStyleTags?: boolean;
  /** Keep "style" tags after inlining (default: false) */
  keepStyleTags?: boolean;
  /** Keep "link" tags after inlining (default: false) */
  keepLinkTags?: boolean;
  /** Keep "at-rules" like @media after inlining (default: false) */
  keepAtRules?: boolean;
  /** Base URL for resolving relative stylesheet URLs (limited support in WASM) */
  baseUrl?: string;
  /** Whether remote stylesheets should be loaded (NOT supported in WASM) */
  loadRemoteStylesheets?: boolean;
  /** Additional CSS to inline beyond document styles */
  extraCss?: string;
  /** Pre-allocate HTML node capacity for performance (default: 32) */
  preallocateNodeCapacity?: number;
}

type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;

Advanced Configuration

HTML Element Control

Control inlining behavior per HTML element using data attributes:

<!-- Skip inlining for this element -->
<h1 data-css-inline="ignore">Won't receive styles</h1>

<!-- Keep the style tag (don't remove it) -->
<style data-css-inline="keep">h1 { color: blue; }</style>

<!-- Ignore this style tag entirely -->
<style data-css-inline="ignore">h1 { color: red; }</style>

External Stylesheet Handling

// Load stylesheets from local filesystem
const result = inline(html, {
  baseUrl: "file:///path/to/project/",
  loadRemoteStylesheets: true
});

// Load from remote URLs with caching
const result = inline(html, {
  baseUrl: "https://example.com/assets/",
  cache: { size: 5 }, // Cache up to 5 stylesheets
  loadRemoteStylesheets: true
});

// Add extra CSS beyond document styles
const result = inline(html, {
  extraCss: "body { margin: 0; padding: 0; }"
});

Performance Optimization

// Pre-allocate capacity for large documents
const result = inline(html, {
  preallocateNodeCapacity: 1000 // If you expect ~1000 HTML nodes
});

// Cache external stylesheets for performance
const result = inline(html, {
  cache: { size: 10 }, // Cache up to 10 stylesheets
  loadRemoteStylesheets: true
});

Error Handling

The library throws errors with different behaviors depending on the execution environment:

Node.js Native Errors

  • InvalidArg: Invalid argument values (e.g., malformed baseUrl)
  • GenericFailure: Processing failures (e.g., invalid CSS syntax, malformed HTML)
try {
  const result = inline(html, { baseUrl: "invalid-url" });
} catch (error) {
  console.log(error.code); // "InvalidArg"  
  console.log(error.message); // "relative URL without a base: invalid-url"
}

WASM Errors

WASM variant throws string errors without structured codes:

try {
  const result = inline(html, { baseUrl: "invalid-url" });
} catch (error) {
  console.log(error); // "relative URL without a base: invalid-url"
}

// WASM-specific errors for unsupported operations
try {
  const result = inline(`<link href="http://example.com/style.css" rel="stylesheet">`);
} catch (error) {
  console.log(error); // "Loading remote stylesheets is not supported on WASM: http://example.com/style.css"
}

Platform Support

  • Node.js: Native performance on Linux, Windows, macOS, FreeBSD, Android
  • Architectures: x64, arm64, ia32, armv7
  • Browsers: WebAssembly support (no caching or filesystem access)
  • Minimum Version: Node.js 10+

Performance

Built on Mozilla Servo components, CSS Inline significantly outperforms JavaScript alternatives:

  • 3x faster than most alternatives in typical scenarios
  • Efficient stylesheet caching reduces network requests
  • Optional memory pre-allocation for large documents
  • Lazy evaluation and optimized CSS parsing

Install with Tessl CLI

npx tessl i tessl/npm-css-inline--css-inline
Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/@css-inline/css-inline@0.17.x
Publish Source
CLI
Badge
tessl/npm-css-inline--css-inline badge