HTML & CSS

The HTML frameset tag, with an example, and what to use instead

HTML & CSS · · Published 2026-10-23

<frameset> split a browser window into several independent documents, each in its own <frame>. It was common in the late 1990s for sites with a fixed menu on the left and content on the right. It is obsolete in HTML5, but you still meet it in old intranet applications and in documentation generators, so it helps to know how it works and how to replace it.

How a frameset page is built

A frameset document has no <body>. In its place, <frameset> divides the window into rows or columns, and each <frame> loads a separate HTML file. Framesets can nest to create a grid.

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN"
  "http://www.w3.org/TR/html4/frameset.dtd">
<html>
<head>
  <meta charset="utf-8">
  <title>Manual</title>
</head>
<frameset rows="70,*">
  <frame src="header.html" name="top" scrolling="no" noresize>
  <frameset cols="220,*">
    <frame src="menu.html" name="menu">
    <frame src="welcome.html" name="content">
  </frameset>
  <noframes>
    <body>
      <p>This manual uses frames. <a href="menu.html">Open the table of contents</a>.</p>
    </body>
  </noframes>
</frameset>
</html>

The menu file opens its links in the right-hand frame by naming it in target:

<!-- menu.html -->
<ul>
  <li><a href="install.html" target="content">Installation</a></li>
  <li><a href="usage.html" target="content">Usage</a></li>
  <li><a href="faq.html" target="content">FAQ</a></li>
</ul>

Save the four files in one folder and open the frameset file: browsers still render framesets for compatibility, even though the element is no longer valid HTML.

Attributes

ElementAttributeMeaning
framesetrows, colsComma-separated sizes: pixels (200), percentages (25%) or relative shares (*, 2*).
framesrcThe document shown in the frame.
framenameThe name used by target on links and forms.
framenoresizeStops the user from dragging the border.
framescrollingyes, no or auto.
frameframeborder, marginwidth, marginheightPresentation, nowadays done with CSS.

Special target values work across frames: _top replaces the whole frameset (use it for links leaving the site), _parent the parent frameset, _self the current frame, _blank a new window or tab.

Why frames were abandoned

The HTML Living Standard lists frame, frameset and noframes as obsolete features that authors must not use.

Replacement 1: one page with a CSS grid layout

The most common reason for frames, a header and a fixed menu, is a layout problem, and CSS solves it in a single document:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Manual: Installation</title>
<style>
  body {
    margin: 0;
    display: grid;
    grid-template-columns: 220px 1fr;
    grid-template-rows: 70px 1fr;
    grid-template-areas: "head head" "menu main";
    height: 100vh;
  }
  header { grid-area: head; padding: 1rem; border-bottom: 1px solid #ccc; }
  nav    { grid-area: menu; overflow-y: auto; border-right: 1px solid #ccc; }
  main   { grid-area: main; overflow-y: auto; padding: 1rem 2rem; }

  @media (max-width: 640px) {
    body { display: block; height: auto; }
    nav { border-right: 0; border-bottom: 1px solid #ccc; }
  }
</style>
</head>
<body>
  <header>Manual</header>
  <nav>
    <ul>
      <li><a href="install.html" aria-current="page">Installation</a></li>
      <li><a href="usage.html">Usage</a></li>
      <li><a href="faq.html">FAQ</a></li>
    </ul>
  </nav>
  <main>
    <h1>Installation</h1>
    <p>…</p>
  </main>
</body>
</html>

Each page has its own URL and title, and the menu and content scroll independently as they did in frames. On narrow screens the layout falls back to a single column.

Replacement 2: share the menu without copying it

Frames were also used to avoid repeating the menu in every file. Server-side templates do that properly:

The menu control described in How to use the ASP.NET Menu control is typically placed in a master page for this reason.

Replacement 3: iframe, for embedding

<iframe> is not obsolete: it embeds one document inside another, such as a map, a video player or a payment form from another origin. Use it for embedding, not for site layout, and add title for screen readers. For untrusted content, the sandbox attribute restricts what the embedded page may do.

<iframe src="https://example.org/widget" title="Opening hours widget"
        width="400" height="300" loading="lazy" sandbox="allow-scripts"></iframe>

Migrating an old frameset site

  1. List the frame documents and identify the shared parts (header, menu).
  2. Move the shared parts into a layout (master page, template or include).
  3. Turn each content frame document into a full page using that layout.
  4. Redirect the old frameset URL to the new start page with a permanent redirect.
  5. Remove target="content" from links; they now open in the same window.

Frames inside ASP.NET applications

Older intranet applications sometimes load an .aspx page in each frame. Two behaviours surprise developers when maintaining them. First, Response.Redirect only changes the frame that made the request; to leave the frameset, the response has to run script such as window.top.location = "…", which is also what a login page must do when a session expires inside a frame. Second, modern browsers block third-party cookies in frames more strictly, so a frame showing pages from another domain may lose its session. Both are good reasons to migrate to a single-document layout as described above.

References