miinideckmiinideck
PricingUse casesBlog
Sign in
How-to & formats

How to inline all CSS and JavaScript in an HTML file (2026)

Three paths to turn a multi-asset HTML page into a single self-contained file: a build-tool step, an LLM prompt, or a manual pass with DevTools. When each one fits.

By miinideck ai research team·June 23, 2026·7 min read
TL;DR
  • A self-contained HTML file is one chunk of HTML with every stylesheet, script, font, and image embedded inline. No external requests after the page loads.
  • Three reasonable paths get you there: a one-shot build-tool step (best for files that update regularly), an LLM prompt (fastest for one-off conversion), or a manual pass with browser DevTools (best when the source is already mostly inline and you're polishing the last few references).
  • The bottleneck is rarely the inlining itself — it's deciding which external assets to keep external (a font that's fine to load from Google) and which to embed (the chart library that should never depend on a CDN).
  • For files that need to ship as one attachment or live at a private link, the self-contained version is what travels; the modular version stays in the project repo.

You have an HTML file that pulls in five external things: a CSS framework via CDN, a chart library via CDN, a font from Google, two images from an asset host, and a JSON file for the data. It works on your machine. The first time someone opens it on a flight, four of the five fail to load.

The fix is to bundle everything into the HTML itself. The page becomes one bigger file that opens correctly with no network connection. The path to get there has three flavors depending on what tools you already have in front of you.

Path 1 — Build tool with an inliner plugin

For HTML files that are part of a recurring workflow — a report you regenerate weekly, a dashboard that updates with new data, a deliverable you ship to clients in a known pattern — a build step that inlines on every regeneration is the cleanest setup.

The shape that works across most stacks:

  • Webpack — html-bundler-webpack-plugin handles HTML as an entry point and inlines CSS, JS, and images per a config rule.
  • Vite — vite-plugin-singlefile rolls the whole output into a single HTML on vite build.
  • esbuild — the --bundle flag plus a small post-process that inlines the CSS output into the HTML.
  • Parcel — out-of-the-box single-file output when the entry is an .html file with relative-path imports.

Cost: an hour or two of initial setup. Win: every regeneration produces a portable file with zero extra steps. If the file ships more than three or four times, the setup pays for itself.

Path 2 — Ask an LLM to do it

For one-off conversion — you have an HTML file and you need a portable version once, not a recurring build — pasting the file into Claude / ChatGPT / Cursor and asking for inlining is faster than configuring a build tool.

The prompt that works:

Rewrite this HTML as a single self-contained file. Inline all CSS in <style> blocks (download external stylesheets and embed). Inline all JavaScript in <script> blocks (download CDN scripts and embed). Replace Google Font links with a system font stack. Base64-encode any small images and embed inline; for large images, ask whether to keep them external. Replace any fetch calls with the hardcoded data if I provide it; if I don't, flag them.

Output: one HTML file, no external HTTP requests.

The model usually handles this in one pass. For files with heavy framework dependencies (a Tailwind CDN, a full React build), the output gets verbose (~200-500KB) but the file is portable.

This is the same shape as the cross-tool portable-HTML prompts used at generation time — the conversion case is just the retroactive version. For Claude artifacts specifically, the export checklist covers the five categories that quietly stay external.

Path 3 — Manual pass with DevTools

For HTML that's already mostly inline and just has a few external references left, manual is sometimes the fastest path.

The walkthrough:

  1. Open the file in a browser. Open DevTools, Network tab, reload the page.
  2. List the external requests. Filter by font, css, js, img. Each row is a thing that needs to either be inlined or deliberately kept external.
  3. For each external resource:
    • Click the row in Network → Response tab → copy the content.
    • Open the HTML in an editor.
    • Replace the <link rel="stylesheet" href="..."> or <script src="..."> tag with the inline equivalent (<style> or <script>).
  4. For fonts: either embed a @font-face rule with the woff2 base64-encoded, or switch to a system font stack (the simpler choice for most cases).
  5. For images: small icons (under 50KB) base64-encode and paste as data:image/png;base64,.... Large images, decide whether they're worth embedding — sometimes the right answer is to keep them external and accept the dependency, or to swap them for inline SVG.

For files with five or fewer external references, this takes 10-15 minutes. For files with twenty references, switch to Path 1 or Path 2.

The SingleFile browser extension (Chrome / Firefox) automates a chunk of this — it captures whatever the browser currently sees as one HTML file with assets inlined. Useful for pages that render correctly in the browser but came from a build system you don't control.

The five categories worth checking

Whichever path you take, the same five things tend to stay external if you don't name them explicitly:

CategoryInline how
CSS files<style> block with the file contents
JavaScript files<script> block with the file contents
Fonts@font-face + base64 woff2 OR system font stack
Imagesdata:image/...;base64,... for small; inline SVG for icons
Fetch / API callsHardcoded JSON literal at the top of the script

The fifth one — fetch calls — is the one that breaks portability hardest because it fails at runtime, not load time. The HTML loads fine; the page sits empty waiting for data that never arrives. For a snapshot deliverable, hardcoding the data at export time is the right shape.

Once the file is inlined, drop it at a private link in under 60 seconds — useful for confirming the file actually opens cleanly on a different network than the one you built it on. Free, no card, 7-day self-destruct.

Try it free (no signup)

How to verify the file is portable

Three checks, in order of how often each catches a real issue:

  1. Open the file with the network disabled. macOS Network preferences → turn Wi-Fi off, open the file in a fresh browser tab, watch what renders. If anything is missing or broken, that's a remaining external dependency.
  2. Search the file for https://. Open in an editor, search the text for https://. Every hit is a reference that may need inlining (or be acceptable to leave external). Reasonable exceptions: schema.org URLs in JSON-LD, deliberate links the user is meant to click, references in comments.
  3. Search for fetch( and XMLHttpRequest. Any runtime data load needs to either be inlined as a hardcoded constant or be deliberate.

A file that passes all three opens identically on every device that has a browser.

When inlining is the wrong call

A few cases where the external dependency is the right shape:

  • Genuinely shared library code — a JavaScript framework loaded from CDN is cached across many sites the user has visited; inlining it makes your file bigger and the user's network usage worse.
  • Live data the page is built to query — a dashboard that polls a real API is a different product than a snapshot; inlining the data would defeat its purpose.
  • Large media — videos, high-res images, anything over a few hundred KB usually doesn't belong base64-encoded in the HTML; it belongs on an asset host with a stable URL.

The split is roughly: inline anything the page can't function without; keep external anything that's optional, shared, or genuinely large.

What this is not

Inlining isn't a build system. For a real web project with multiple pages, shared components, ongoing development, and team workflows — the modular structure (separate CSS, JS, asset files; build step; deploy pipeline) is correct and pays off.

The inline pass is for the moment of delivery, when the file leaves the project repo and becomes something one person opens on their machine. For the delivery channel decision afterward — private link, public host, attachment — the file shape matters less than where it lands. The self-contained file is what makes any of those channels work cleanly.

One caution worth pairing with this: inlining moves weight into the file rather than removing it. Inline a CDN framework you barely use and the page is self-contained and several megabytes. Trimming the page before you inline it is the pass that keeps the result light enough to open instantly on cellular.

More in How-to & formats

You attached an HTML file and it opened as raw code (2026)

The attachment arrived, nothing was blocked, and your recipient sees markup instead of the page. That's three different email failures people keep merging into one. Here's which one you hit, and why the fix isn't a different attachment.

August 5, 2026·4 min read

You put an HTML file in Google Drive and it shows the code (2026)

Upload an .html file to Drive, open it, and you get a wall of markup instead of the page. Nothing is broken — Drive is doing exactly what a filing cabinet does. Here's the mechanism, the workarounds people try, and what actually renders it.

August 5, 2026·5 min read

Sending a 50MB HTML file when email refuses (2026)

Email providers cap attachments around 20-25MB. The fix when the file is bigger isn't to compress harder — it's to send the URL instead.

August 4, 2026·7 min read

Send your own private link.

miinideck turns a single HTML file into an unguessable link with optional password and expiry. Default-private, never indexed.

Try it free →See pricing
miinideck

HTML files, finally as links — for AI builders, agencies, and consultants. Default-noindex, default-private, default-yours.

Product

  • Pricing
  • Use cases
  • Try it free

Resources

  • Blog
  • Featured on
  • Report abuse

Legal

  • Privacy
  • Terms
© 2026 miinideckMade for people who don't want their work indexed.