Question

Include One HTML File in Another HTML File

htmljavascriptdominclude

Question

I have two HTML files, a.html and b.html, and I want to display or reuse the contents of b.html inside a.html.

In JSF, this can be done with:

<ui:include src="b.xhtml" />

This inserts the content of b.xhtml into a.xhtml. What is the equivalent way to include one file inside another when using plain .html files?

Short Answer

Plain HTML has no built-in equivalent to JSF's <ui:include>. The appropriate solution depends on your goal: use an <iframe> to embed a separate document, or use server-side templates, static-site build tools, or JavaScript to reuse shared page fragments such as headers and footers.

Concept

HTML is a document format interpreted by a browser. When a browser loads a.html, it parses that one document; it does not provide a standard HTML element that reads b.html and inserts its markup directly into the current page.

JSF is different because it runs on a server. Before sending the final page to the browser, JSF processes <ui:include> and generates one combined HTML response.

For plain HTML projects, choose an approach based on the result you need:

  • Embed a complete independent page: use <iframe>.
  • Reuse partial markup such as a navigation bar or footer: use a server-side template engine, Server Side Includes (SSI), or a static-site generator/build tool.
  • Load a fragment after the page starts: use JavaScript fetch().

This distinction matters because embedding a document and inserting markup into the current document have different behavior for styles, scripts, links, accessibility, browser history, and SEO.

Mental Model

Think of a plain HTML page as a printed sheet of paper. The browser reads the sheet you give it, but it does not have an instruction like “paste the contents of this other sheet here.”

An <iframe> is like placing another complete sheet inside a picture frame on the first sheet. It remains a separate document.

A server-side include or template is like assembling several paper fragments—header, content, and footer—into one final sheet before handing it to the reader.

JavaScript fetch() is like receiving the main sheet first, then asking someone to bring another fragment and attaching it afterward.

Take Quiz

Syntax and Examples

For a complete separate HTML document, use an <iframe>:

<!-- a.html -->
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Page A</title>
  </head>
  <body>
    <h1>This is a.html</h1>

    <iframe src="b.html" title="Content from b.html"></iframe>
  </body>
</html>

b.html is loaded as its own page inside the frame:

<!-- b.html -->
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Page B</title>
  </head>
  <body>
    <p>This content comes from b.html.</p>
  </body>
</html>

The title attribute is important because it tells assistive technologies what the frame contains.

If b.html is intended to be a reusable fragment rather than a full page, JavaScript can load it:

<!-- a.html -->
<div id="site-header"></div>

<script>
  fetch("header.html")
    .then((response) => {
      if (!response.ok) {
        throw new Error("Could not load header.html");
      }
      return response.text();
    })
    .then((html) => {
      document.querySelector("#site-header").innerHTML = html;
    })
    .catch((error) => {
      console.error(error);
    });
</script>

Here, header.html should contain only the reusable fragment, for example:

<header>
  <a href="index.html">Home</a>
  <a href="about.html">About</a>
</header>

Do not put a second <!doctype html>, <html>, <head>, or <body> document inside a fragment that you plan to insert with innerHTML.

Step by Step Execution

Consider this JavaScript fragment loader:

<div id="footer"></div>

<script>
  fetch("footer.html")
    .then((response) => response.text())
    .then((html) => {
      document.querySelector("#footer").innerHTML = html;
    });
</script>

Execution flow:

  1. The browser parses the <div id="footer">. It is initially empty.
  2. The browser runs the script.
  3. fetch("footer.html") sends a request for the fragment file.
  4. When the file arrives, response.text() reads its contents as a string of HTML.
  5. The second .then() receives that HTML string.
  6. document.querySelector("#footer") finds the empty footer container.
  7. Assigning to innerHTML parses the fragment markup and displays it inside the container.

The page may briefly show an empty footer while the request is still loading. This is one reason server-side or build-time templates are often preferred for shared layout content.

Real World Use Cases

Common uses for reusable HTML content include:

  • Shared navigation: keep the same menu on every page.
  • Footers: reuse copyright text, support links, and legal links.
  • Documentation sites: assemble pages from a common layout and individual article content.
  • Marketing pages: reuse banners, cookie notices, and contact sections.
  • Legacy systems: use an iframe to display an existing page that cannot easily be integrated into the current application.
  • Dashboards: embed an isolated report or third-party tool in an iframe when allowed by its security policy.
Take Quiz

Real Codebase Usage

In production codebases, developers usually avoid manually copying a header into every .html file. Instead, they use a layout system that combines templates before deployment or before a server responds.

Common patterns include:

  • Server-side templates: A Node.js, PHP, Python, Java, or .NET application renders a layout plus page-specific content into one HTML response.
  • Static-site generators: Tools such as Jekyll, Eleventy, Hugo, or Astro build reusable layouts and partials into static HTML files.
  • Component frameworks: React, Vue, Angular, and similar tools model headers and footers as reusable components.
  • Web components: A custom element can provide browser-native component encapsulation when appropriate.
  • JavaScript fragment loading: Used for small static sites, prototypes, or progressively enhanced content, but requires careful error handling.

For JavaScript loading, production code should validate the response:

async function loadFragment(selector, url) {
  const response = await fetch(url);

  if (!response.ok) {
    throw new Error(`Failed to load ${url}: ${response.status}`);
  }

  const html = await response.text();
  document.querySelector(selector).innerHTML = html;
}

loadFragment("#site-footer", "footer.html")
  .catch((error) => console.error(error));

Only insert HTML from trusted sources. Inserting untrusted text with innerHTML can create cross-site scripting (XSS) security vulnerabilities.

Common Mistakes

Expecting a nonexistent HTML include tag

This is not a standard HTML feature:

<!-- This does not work in standard HTML -->
<include src="b.html"></include>

Use an iframe, a template/build process, or JavaScript instead.

Using an iframe for a page fragment

An iframe is best for a full, independent document. It creates a separate browsing context, so its CSS and JavaScript do not naturally become part of the parent page.

<iframe src="header.html"></iframe>

This is usually a poor way to add a site header because the frame needs sizing, has separate styling, and can complicate navigation.

Opening files directly with file://

fetch() may fail when you double-click an HTML file and open it from your filesystem due to browser security restrictions.

Instead, run a local web server. For example, with Python:

python -m http.server 8000

Then visit http://localhost:8000/a.html.

Ignoring failed requests

This code does not detect HTTP failures such as 404 Not Found:

fetch("header.html")
  .then((response) => response.text());

Check response.ok before reading the body.

Inserting untrusted HTML with innerHTML

Avoid this when html comes from a user or an unknown external source:

container.innerHTML = html;

Untrusted markup may contain harmful content. Use trusted local fragments, sanitize content, or create DOM nodes safely.

Assuming scripts in inserted HTML will run

Scripts added through innerHTML generally do not execute as normal page scripts. Put required behavior in JavaScript modules or initialize the inserted fragment explicitly.

Comparisons

ApproachBest forResultImportant trade-off
<iframe>Showing a complete, separate pageNested documentSeparate CSS, scripts, history, and sizing
JavaScript fetch()Small reusable fragments in a static siteMarkup inserted after loadingRequires JavaScript, a server, and safe HTML handling
Server-side include/templateShared layouts in web applicationsOne complete HTML responseRequires server or template setup
Static-site generatorMulti-page static sitesHTML assembled during buildRequires a build step
Copy and pasteVery small one-off pagesDuplicated markupUpdates become error-prone

<object> and <embed> can also load external resources, but they are generally not the preferred tools for building a page layout. For HTML content, use an iframe when you truly need an embedded document.

Take Quiz

Cheat Sheet

  • Plain HTML has no standard <include> element.
  • Use <iframe src="b.html" title="Description"> to embed a complete separate page.
  • Use server-side templates or a static-site generator for shared headers, navigation, and footers.
  • Use fetch() to load a trusted HTML fragment after the page loads.
  • A fetched fragment should normally contain markup such as <header> or <footer>, not another full <html> document.
  • Check response.ok when using fetch().
  • Test fetch() through http://localhost, not by opening files with file://.
  • Do not insert untrusted content using innerHTML.
  • Iframes are isolated documents; their styles and scripts are not the parent page's styles and scripts.

FAQ

Is there an HTML equivalent of JSF <ui:include>?

No. Plain HTML does not have a standard include directive. JSF performs inclusion on the server before the browser receives the page.

Can I use an iframe to include another HTML file?

Yes. An iframe can display another HTML file, but it embeds a separate document rather than merging its markup into the parent document.

How do I reuse the same header on multiple HTML pages?

For a small site, load a trusted header.html fragment with JavaScript. For a larger or production site, use templates or a static-site generator.

Why does fetch("header.html") fail when I double-click my HTML file?

Browsers restrict requests made from file:// pages. Run the site through a local web server instead.

Can b.html contain <html>, <head>, and <body> when using fetch()?

Technically the browser may parse parts of it, but it is not the right structure for an inserted fragment. Put only the reusable markup in the fragment file.

Is loading HTML with innerHTML safe?

It is safe only when the HTML is trusted and controlled by your application. Never insert arbitrary user-provided or unknown HTML without sanitizing it.

Which option is best for SEO and initial page load?

Server-side rendering or static build-time templates are generally best because the complete page content exists in the initial HTML response.

Take Quiz

Mini Project

Description

Create a small multi-page static site that loads one shared navigation bar and one shared footer. This demonstrates HTML fragment reuse with the Fetch API while keeping each page's main content separate.

Goal

Build a page that inserts header.html and footer.html into index.html when the page loads.

Requirements

Create a header.html file containing navigation markup only.

Take Quiz

Keep learning

Related questions

View more