# The “frame” element is obsolete. Use the “iframe” element and CSS instead, or use server-side includes.

> Canonical HTML version: https://rocketvalidator.com/html-validation/the-frame-element-is-obsolete-use-the-iframe-element-and-css-instead-or-use-server-side-includes
> Attribution: Rocket Validator (https://rocketvalidator.com)
> License: CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/)

The `<frame>` element is obsolete, so the content each frame loads has to move into the page itself or into an `<iframe>` inside a normal `<body>`.

A `<frame>` only works inside a `<frameset>`, where it loads a separate HTML file into one pane of the browser window. The validator reports this message once for every `<frame>` on the page, and the `<frameset>` around them gets a message of its own. Moving the frames into a `<body>` doesn't help: the parser drops a `<frame>` there and reports it as a stray start tag. The frames and the frameset have to be replaced together, and when the frameset only wraps another site in a single frame, an HTTP redirect to that site replaces both.

What replaces each frame depends on what it holds. A header or menu that every page shares belongs in the page itself, written directly or pulled in with a server-side include or a template, so it lives at the same URL as the content around it. A document that has to stay separate can load in an `<iframe>`. Iframes take `src` and `name` just as frames did, so links with a matching `target` keep loading into them, and the validator stops warning that `name` is never allowed on `<frame>`. Give each iframe a `title` describing what it shows, since screen readers announce it.

The presentation attributes of a frame don't carry over. On an `<iframe>`, `frameborder`, `scrolling`, `marginwidth` and `marginheight` are obsolete too, and the validator warns about each one. Remove the border with `border: 0` in CSS. Scrollbars and margins belong to the document loaded inside, so set `overflow` and `margin` in that document's own stylesheet. `noresize` needs no replacement, since an iframe has no draggable border between panes.

## Invalid example

A header frame above a catalog frame:

```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Garden supplies</title>
  </head>
  <frameset rows="80,*">
    <frame src="header.html" scrolling="no" noresize frameborder="0">
    <frame src="catalog.html" frameborder="0">
  </frameset>
</html>
```

## Valid example

The header is part of the page (on a real site it would come from an include), and the catalog keeps loading from its own file in an iframe:

```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Garden supplies</title>
    <style>
      iframe {
        width: 100%;
        height: 80vh;
        border: 0;
      }
    </style>
  </head>
  <body>
    <header>
      <a href="/">Garden supplies</a>
    </header>
    <iframe src="catalog.html" name="catalog" title="Product catalog"></iframe>
  </body>
</html>
```
