@css-inline/css-inline

中文文档
0.23.2发布于 2026/10/27MITTypeScriptCommonJS零依赖构建来源已验证近 30 天下载 164.4万

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

原始使用文档
文档目录9 节
  1. Playground
  2. Installation
  3. Node.js
  4. Usage
  5. Configuration
  6. Errors
  7. WebAssembly
  8. Performance
  9. License

css-inline

build status npm codecov.io gitter

css-inline inlines CSS into HTML style attributes. Use it to prepare HTML emails or to embed HTML into third-party web pages.

It turns this HTML:

<html><head><style>h1 { color:blue; }</style></head><body><h1>Big Text</h1></body></html>

into:

<html><head></head><body><h1 style="color: blue;">Big Text</h1></body></html>

css-inline keeps whitespace text nodes from the input, so indented HTML stays indented in the output.

  • Builds on Mozilla Servo components (html5ever, cssparser, selectors)
  • Inlines CSS from style and link tags
  • Removes style and link tags
  • Resolves external stylesheets (including local files)
  • Optionally caches external stylesheets
  • Works on Linux, Windows, macOS and Android
  • Supports HTML5 & CSS3
  • Tested on Node.js 20 & 22

Playground

Try css-inline in the WebAssembly-powered playground.

Installation

Node.js

Install with npm:

npm i @css-inline/css-inline

The package ships TypeScript types (index.d.ts).

npm installs a prebuilt binary for your platform, so you don't need Rust. Prebuilt targets: linux-x64-gnu, linux-x64-musl, linux-arm64-gnu, linux-arm64-musl, linux-arm-gnueabihf, darwin-x64, darwin-arm64, win32-x64-msvc, win32-arm64-msvc, android-arm64, android-arm-eabi.

Usage

import { inline } from "@css-inline/css-inline";
// CommonJS: const { inline } = require("@css-inline/css-inline");

const inlined = inline(
  "<html><head><style>h1 { color:red }</style></head><body><h1>Test</h1></body></html>",
);
// <html><head></head><body><h1 style="color: red;">Test</h1></body></html>

inline adds missing html, head and body tags, so the output is a complete HTML document.

inlineFragment(html, css, options?) inlines the css string into an HTML fragment. It never adds <html>, <head> or <body>; if the input has them, it keeps only their contents. Use inline to keep the full document structure:

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

const inlined = inlineFragment(
  "<main><h1>Hello</h1><section><p>who am i</p></section></main>",
  "p { color: red; } h1 { color: blue; }",
);
// <main><h1 style="color: blue;">Hello</h1><section><p style="color: red;">who am i</p></section></main>

Configuration

Pass options as the second argument to inline or the third to inlineFragment.

  • inlineStyleTags. Inline CSS from style tags. Default: true
  • keepStyleTags. Keep style tags after inlining. Default: false
  • keepLinkTags. Keep link tags after inlining. Default: false
  • keepAtRules. Keep at-rules (@media, @font-face, ...) after inlining. Default: false
  • minifyCss. Remove trailing semicolons and spaces between properties and values. Default: false
  • baseUrl. Base URL for resolving relative URLs. Use the file:// scheme to load stylesheets from the filesystem; end directory URLs with / (file:///path/to/styles/), or css-inline resolves relative to the parent directory. Default: null
  • loadRemoteStylesheets. Load stylesheets from link tags, over the network or from file:// paths. false skips every link tag. Default: true
  • cache. LRU cache for external stylesheets, keyed by resolved URL. size is the number of stylesheets to keep and must be greater than zero, e.g. { size: 5 }. Default: null
  • extraCss. Extra CSS to inline. Default: null
  • preallocateNodeCapacity. Advanced. Number of HTML nodes to preallocate during parsing. Set it to your expected node count to avoid reallocations. Default: 32
  • removeInlinedSelectors. Remove selectors that were inlined from <style> blocks. Default: false
  • applyWidthAttributes. Add width HTML attributes from CSS width properties on table, td, th and img. Default: false
  • applyHeightAttributes. Add height HTML attributes from CSS height properties on table, td, th and img. Default: false
  • resolveCssVariables. Replace var() references with the values of the custom properties they refer to and drop the --* declarations. Default: false

To skip inlining for a tag, add the data-css-inline="ignore" attribute:

<html>
<head>
    <style>h1 { color:blue; }</style>
</head>
<body>
    <!-- The tag below won't receive additional styles -->
    <h1 data-css-inline="ignore">Big Text</h1>
</body>
</html>

The same attribute on a link or style tag excludes its styles:

<head>
  <!-- Styles below are ignored -->
  <style data-css-inline="ignore">h1 { color:blue; }</style>
</head>
<body>
  <h1>Big Text</h1>
</body>

To keep a style tag in the output, add data-css-inline="keep". Use it to keep @media queries for responsive emails in separate style tags. css-inline keeps such tags even when keepStyleTags is false.

<head>
  <!-- Styles below are not removed -->
  <style data-css-inline="keep">h1 { color:blue; }</style>
</head>
<body>
  <h1>Big Text</h1>
</body>

At-rules cannot be inlined into HTML, so css-inline removes them by default. Set keepAtRules: true to keep them in style tags and inline the remaining styles. css-inline keeps these tags even when keepStyleTags is false.

<head>
  <!-- With keepAtRules: true, "color: blue" goes into <h1> and @media stays in <style> -->
  <style>h1 { color: blue; } @media (max-width: 600px) { h1 { font-size: 18px; } }</style>
</head>
<body>
  <h1>Big Text</h1>
</body>

With minifyCss: true, css-inline removes trailing semicolons and spaces between properties and values in inlined styles.

<head>
  <!-- With minifyCss: true, <h1> gets style="color:blue;font-weight:bold" -->
  <style>h1 { color: blue; font-weight: bold; }</style>
</head>
<body>
  <h1>Big Text</h1>
</body>

Caching is off by default. Enable it to avoid fetching the same external stylesheet on every call:

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

const inlined = inline(
  `
  <html>
    <head>
      <link href="http://127.0.0.1:1234/external.css" rel="stylesheet">
      <style>h1 { color:red }</style>
    </head>
    <body>
      <h1>Test</h1>
    </body>
  </html>
  `,
  { cache: { size: 5 } },
);

inline and inlineFragment are synchronous. css-inline fetches remote stylesheets with a blocking HTTP request, so the call blocks the event loop until the fetch completes. inlineAsync and inlineFragmentAsync take the same arguments and return a Promise. They load all external stylesheets concurrently, off the event loop:

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

const inlined = await inlineAsync(html, { baseUrl: "https://example.com/" });

Set loadRemoteStylesheets: false to skip all link tags.

Errors

inline and inlineFragment throw an Error, and inlineAsync and inlineFragmentAsync reject with the same Error:

  • Invalid baseUrl: relative URL without a base: not a url
  • Failed fetch: error sending request for url (http://127.0.0.1:9/a.css): http://127.0.0.1:9/a.css
  • Missing local file: Missing stylesheet file: /path/to/missing.css
  • cache: { size: 0 }: Cache size must be an integer greater than zero

WebAssembly

@css-inline/css-inline-wasm runs css-inline in browsers. It is built with wasm-bindgen.

<iframe id="output"></iframe>
<script src="https://unpkg.com/@css-inline/css-inline-wasm"></script>
<script>
  // `initWasm` is async: wait for it before calling `inline`
  cssInline.initWasm(fetch('https://unpkg.com/@css-inline/css-inline-wasm/index_bg.wasm')).then(() => {
    const inlinedHtml = cssInline.inline(`<html>
  <head>
    <style>h1 { color:blue; }</style>
  </head>
  <body>
    <h1>Big Text</h1>
  </body>
</html>`);
    document.getElementById('output').srcdoc = inlinedHtml;
  });
</script>

NOTE: The WASM module loads remote stylesheets only through the async inlineAsync and inlineFragmentAsync, cannot read the filesystem, and has no cache option. See its README for npm install, Node.js setup and link tag handling. The unpkg URLs above load the latest release; pin a version (@css-inline/[email protected]) to match your installed package.

Performance

Native css-inline runs 3.09x to 15.19x faster than juice and inline-css on the cases below. The WASM build runs 1.50x to 1.65x slower than native.

Sizecss-inlinecss-inline-wasmjuiceinline-css
Basic230 B8.14 µs12.23 µs (1.50x)40.89 µs (5.02x)76.10 µs (9.35x)
Realistic-18.58 KB154.56 µs255.62 µs (1.65x)478.24 µs (3.09x)1.00 ms (6.50x)
Realistic-24.30 KB77.86 µs120.31 µs (1.55x)571.43 µs (7.34x)805.15 µs (10.34x)
GitHub page1.81 MB20.37 ms30.79 ms (1.51x)309.51 ms (15.19x)ERROR

inline-css fails on the GitHub page because it cannot parse its CSS: Error: Unexpected } (line 193, char 13771).

Inputs come from benchmarks/benchmarks.json: "Basic" is simple, "Realistic-1" and "Realistic-2" are big_email_1 and big_email_2, "GitHub page" is big_page. Ratios are relative to css-inline.

benches/bench.ts runs the suite with benny (mean time; css-inline 0.23.2, juice 11.0.3, inline-css 4.0.3), built with stable rustc 1.99 on Node.js v24.18.0, Ryzen 9 9950X.

License

Licensed under the MIT license.

版本与发布记录

@css-inline/css-inline 共发布 27 个版本,首次发布于 2023/12/29;过去 12 个月发布了 14 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.23.2latest2026/10/2714 天前
0.23.12026/10/1724 天前
0.23.02026/10/1725 天前
0.22.12026/10/1427 天前
0.22.02026/10/021 个月前
0.21.22026/08/242 个月前

关于 @css-inline/css-inline 的常见问题

@css-inline/css-inline 是什么?

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

如何安装 @css-inline/css-inline?

在项目目录运行 npm install @css-inline/css-inline,或使用 pnpm add / yarn add / bun add。

@css-inline/css-inline 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@css-inline/css-inline 支持 ESM 还是 CommonJS?

以 CommonJS 形式发布,可以直接 require();在 ES Module 项目中也可以用 import 引入(Node.js 会把 module.exports 作为默认导出)。

@css-inline/css-inline 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >= 10。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@css-inline/css-inline 可以商用吗?

@css-inline/css-inline 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@css-inline/css-inline 的下载量有多少?

根据 npm 官方下载统计,@css-inline/css-inline 在 2026/10/11 – 2026/11/09 这 30 天内被下载 1,644,459 次,日均约 54,815 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@css-inline/css-inline 还在维护吗?

最新版本 0.23.2 发布于 2026/10/27(14 天前);至今共发布 27 个版本,其中过去 12 个月发布了 14 个;首次发布于 2023/12/29。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。