Etiqueta frame en HTML: obsoleta y migración de marcos
La etiqueta <frame> está obsoleta y no debe usarse en páginas nuevas. Cargaba un documento en una región de un <frameset>, por ejemplo un menú junto a otra página con el contenido. Hoy se rediseña esa estructura con HTML y CSS; se reserva <iframe> para un documento que realmente necesite incrustarse. El HTML Living Standard prohíbe la autoría de frame, frameset y noframes.
Ejemplo histórico y contexto de frame
Este bloque sirve para reconocer código antiguo; no es HTML vigente ni una demostración ejecutable:
<frameset cols="220,*">
<frame src="menu.html" name="menu" title="Navegación">
<frame src="contenido.html" name="contenido" title="Contenido">
</frameset>
El diseño pretendía mostrar dos documentos: menu.html en una columna de 220 píxeles y contenido.html en el espacio restante. Los archivos se cargaban por separado; no eran hijos escritos dentro de <frame>. No se exige que un navegador actual reproduzca este diseño.
En HTML 4.01 Frameset, <frame> era un elemento vacío: no contenía texto ni llevaba </frame>. Su padre era <frameset>, que podía anidarse y ocupaba el lugar de <body> en el documento contenedor. No se colocaba dentro del cuerpo de una página moderna. La referencia histórica de W3C documenta esta sintaxis.
Cambiar src cambiaba el documento inicial del marco; cambiar cols afectaba a la distribución, porque era un atributo de <frameset>. Retirar un <frame> no integra automáticamente el contenido de su archivo en la página.
Frame, frameset e iframe
<frameset> repartía la ventana en marcos y cada <frame> seleccionaba un documento. <iframe> es un elemento vigente que incrusta otro documento dentro del contenido de una página con <body>. Tiene apertura y cierre: <iframe …></iframe>.
Por tanto, frame e iframe no son la misma etiqueta. Sustituir todos los marcos por iframes conservaría documentos separados y sus problemas de navegación; no crea por sí solo una página adaptable o accesible. Para un menú y contenido propios, reúne la estructura en una página con <nav> y <main>. Si el sitio tiene varias páginas, comparte la navegación mediante una plantilla durante su generación o en el servidor.
Migración a navegación y contenido principal
Guarda este documento como biblioteca.html en UTF-8 y ábrelo en el navegador. Incluye todo el CSS y no necesita servidor, otros archivos ni JavaScript.
<!doctype html>
<html lang="es">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Biblioteca del barrio</title>
<style>
body {
margin: 0;
padding: 1rem;
font-family: sans-serif;
line-height: 1.6;
color: #222;
background: #fff;
}
a { color: #0645ad; }
a:focus-visible { outline: 3px solid #0645ad; outline-offset: 3px; }
.pagina { max-width: 64rem; margin-inline: auto; }
nav ul { padding-inline-start: 1.5rem; }
main { min-width: 0; }
@media (min-width: 48rem) {
.pagina {
display: grid;
grid-template-columns: 14rem minmax(0, 1fr);
gap: 2rem;
}
}
</style>
</head>
<body>
<a href="#contenido">Saltar al contenido</a>
<div class="pagina">
<nav aria-label="Biblioteca">
<ul>
<li><a href="#talleres">Talleres</a></li>
<li><a href="#horarios">Horarios</a></li>
</ul>
</nav>
<main id="contenido" tabindex="-1">
<h1>Biblioteca del barrio</h1>
<h2 id="talleres" tabindex="-1">Talleres</h2>
<p>El club de lectura se reúne los miércoles a las 17:00.</p>
<h2 id="horarios" tabindex="-1">Horarios</h2>
<p>Abrimos de lunes a viernes, de 9:00 a 18:00.</p>
</main>
</div>
</body>
</html>
<nav> identifica la navegación principal y <main> el contenido dominante. Hay un solo main. Los destinos admiten foco mediante tabindex="-1" sin añadir paradas a la secuencia de Tab.
En móvil verás navegación y contenido uno debajo del otro. Desde 48rem, la consulta de ancho activa dos columnas con CSS Grid. La lectura del HTML conserva el mismo orden.
Los enlaces cambian la URL a biblioteca.html#talleres o #horarios; Atrás y Adelante recorren esos destinos. Para documentos distintos, utiliza sus URL reales: se cargará la página completa. Desaparece la dependencia de target="contenido", que antes dirigía enlaces al marco nombrado. Revisa también un posible <base target="contenido"> heredado. Conserva o redirige las URL antiguas cuando publiques la migración.
Prueba Tab y Enter para saltar al contenido y abrir ambos destinos. Comprueba foco, URL e historial a 375 y 1280 píxeles, con JavaScript deshabilitado. Retira el CSS: permanece todo el contenido en el orden de lectura, sin columnas.
Iframe solo para un documento independiente
Si los horarios deben mantenerse como documento separado, guarda este archivo como horarios.html junto a biblioteca.html:
<!doctype html>
<html lang="es">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Horarios de la biblioteca</title>
</head>
<body>
<h1>Horarios de la biblioteca</h1>
<p>De lunes a viernes, de 9:00 a 18:00.</p>
</body>
</html>
Añade este fragmento dentro del main del primer ejemplo, sustituyendo su sección de horarios. Conserva un destino horarios para el enlace del menú:
<h2 id="horarios" tabindex="-1">Horarios</h2>
<iframe
src="horarios.html"
title="Horarios de la biblioteca"
style="width: 100%; height: 12rem; box-sizing: border-box; border: 1px solid #555;"
></iframe>
<p><a href="horarios.html">Abrir los horarios como página completa</a>.</p>
Verás el segundo documento dentro de una región con borde y un enlace para abrirlo directamente. El atributo title describe el iframe para sus usuarios; no sustituye al <title> del documento ni a su contenido accesible. Comprueba que puedes entrar y salir con el teclado.
Los estilos externos no se aplican al documento incrustado. Su altura tampoco se ajusta automáticamente al contenido. Un servidor externo puede impedir la incrustación mediante sus políticas; añadir un iframe no concede permiso. El enlace exterior debe seguir disponible si se bloquea la carga: no se trata de contenido alternativo dentro de <iframe>.
Atributos antiguos y reemplazos
Los siguientes valores corresponden a HTML 4.01, no a recomendaciones actuales:
| Atributo de frame | Efecto histórico | Decisión al migrar |
|---|---|---|
src | URL del documento inicial | Integrar su contenido o usar src de iframe si procede |
name | Nombre para destinos de enlaces | Quitar los target antiguos y usar URL o fragmentos |
scrolling | auto por defecto; yes forzaba desplazamiento, no lo impedía | Permitir leer el contenido completo; revisar el desbordamiento |
frameborder | 1 por defecto; 0 pedía ocultar separadores | Controlar los bordes mediante CSS |
noresize | Booleano: presente impedía redimensionar; ausente no lo impedía | Diseñar un tamaño adaptable |
marginwidth, marginheight | Márgenes internos en píxeles positivos; valor predeterminado del navegador | Definir espacio con CSS en el documento correspondiente |
title, id y class eran atributos comunes, no exclusivos de los marcos. name no era el título legible del marco. No traslades automáticamente los atributos antiguos a iframe: scrolling, frameborder y los márgenes también son obsoletos allí; noresize no es un atributo vigente de iframe.
border, padding y grid-template-columns son propiedades CSS. element.style.border es acceso al estilo mediante JavaScript; no convierte un atributo histórico en válido.
Errores frecuentes y preguntas
¿Qué reemplaza los marcos de una página? Normalmente un documento con navegación, contenido y CSS. Usa iframe únicamente para una incrustación necesaria, con un título descriptivo y una salida mediante enlace.
¿Por qué no aparece frame dentro de body? Revisa primero el contexto: pertenecía a <frameset>. En una página actual, reconstruye la estructura; añadir un cierre o cambiar atributos no corrige su obsolescencia.
Evita dejar enlaces dirigidos a marcos inexistentes, ocultar contenido con scrolling="no" o asumir que eliminar un marco conserva sus datos. <noframes> era una alternativa para la arquitectura antigua, no un mecanismo moderno de fallback. Para escribir los enlaces de la migración, consulta la guía de <a>.
Compatibilidad y fuentes
Estado revisado el 3 de octubre de 2026. MDN marca <frame> como obsoleto. El estándar mantiene reglas de procesamiento para documentos heredados, lo cual no permite usarlo en autoría nueva ni garantiza un resultado idéntico entre navegadores. La sintaxis histórica se contrasta con HTML 4.01; la migración utiliza las fuentes actuales de HTML, CSS y accesibilidad enlazadas en la guía.