Etiqueta frameset en HTML: obsoleta y diseños actuales
La etiqueta <frameset> está obsoleta y no debe usarse en páginas nuevas. Dividía la ventana en marcos que mostraban documentos distintos, por ejemplo un menú junto a una lección. Hoy ese diseño suele resolverse con un documento estructurado y CSS Grid o Flexbox. El estándar vigente exige abandonar los marcos antiguos; esta guía explica cómo reconocerlos y migrarlos.
Ejemplo histórico: menú y lección separados
Este fragmento documenta código antiguo; no es una demostración para ejecutar ni una recomendación actual:
<frameset cols="25%,75%">
<frame src="menu.html" title="Menú">
<frame src="leccion.html" name="contenido" title="Lección">
</frameset>
Pretendía reservar un cuarto de la ventana al menú y tres cuartos a la lección. menu.html y leccion.html eran documentos independientes, con carga y desplazamiento propios; sus nombres describen archivos antiguos, no recursos que debas descargar para esta guía.
En HTML 4.01 Frameset, <frameset> aparecía después de <head> y sustituía a <body>. Contenía uno o más <frame> o conjuntos <frameset> anidados y, opcionalmente, un <noframes> con contenido alternativo. Tenía apertura y cierre; <frame> era vacío. Esa estructura no es válida para autoría actual bajo <!DOCTYPE html>.
Cómo funcionaban rows, cols y los destinos
Los dos atributos específicos de distribución recibían listas separadas por comas:
| Atributo histórico | Qué repartía | Ejemplo |
|---|---|---|
cols | Anchura entre columnas | cols="240,*": una columna de 240 píxeles y otra con el espacio restante |
rows | Altura entre filas | rows="20%,80%": dos filas con esas proporciones |
Aceptaban números en píxeles, porcentajes y proporciones como * o 2*. cols="*,2*" repartía el espacio relativo en proporción 1:2. Si faltaba un atributo, su valor histórico era 100%: una sola fila o columna. Podían combinarse para formar una cuadrícula. Son reglas de distribución histórica, no sintaxis de CSS.
src y name pertenecían a <frame>, no a <frameset>. Un enlace con target="contenido" cargaba su destino en el marco llamado contenido. El nombre identificaba el destino; title lo describía. La navegación entre marcos podía cambiar la lección sin cambiar el menú. Compartir la URL exterior no siempre reproducía esa combinación, y varias zonas con desplazamiento complicaban la lectura en pantallas pequeñas.
Los atributos globales id, class y title no eran atributos de distribución. En la solución actual, grid-template-columns y gap son propiedades CSS; no atributos HTML ni instrucciones JavaScript. Tampoco 1fr equivale automáticamente al antiguo *: Grid reparte espacio dentro de un diseño con sus propias reglas de tamaño.
Migración actual con CSS Grid
Guarda este documento completo como leccion.html, con codificación UTF-8, y ábrelo en un navegador. Incluye todo el contenido y CSS; no necesita otros archivos, un servidor ni JavaScript.
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Cultivar albahaca</title>
<style>
* { box-sizing: border-box; }
body {
max-width: 70rem;
margin: auto;
padding: 1rem;
font-family: system-ui, sans-serif;
line-height: 1.6;
color: #172b3a;
background: #fff;
}
a { color: #074f85; }
:focus-visible { outline: 3px solid #074f85; outline-offset: 3px; }
.pagina { display: grid; gap: 1.5rem; margin-top: 1rem; }
nav, main { min-width: 0; }
nav { padding: 1rem; background: #edf4f8; }
footer { grid-column: 1 / -1; border-top: 1px solid #8798a4; }
@media (min-width: 48rem) {
.pagina { grid-template-columns: minmax(12rem, 1fr) minmax(0, 3fr); }
}
</style>
</head>
<body>
<a href="#contenido">Saltar al contenido</a>
<div class="pagina">
<nav aria-label="Temas de la lección">
<h2>Temas</h2>
<ul>
<li><a href="#siembra">Siembra</a></li>
<li><a href="#cuidados">Cuidados</a></li>
</ul>
</nav>
<main id="contenido" tabindex="-1">
<h1>Cultivar albahaca</h1>
<section id="siembra">
<h2>Siembra</h2>
<p>Prepara una maceta con drenaje y coloca las semillas en el sustrato.</p>
</section>
<section id="cuidados">
<h2>Cuidados</h2>
<p>Comprueba la humedad de la tierra antes de regar.</p>
</section>
</main>
<footer>
<p>Cuaderno de cultivo: lección de albahaca.</p>
</footer>
</div>
</body>
</html>
En una ventana de al menos 48rem aparecen menú y contenido en dos columnas, con el pie <footer> debajo de ambos. En móvil se apilan: navegación, contenido y pie. Ese mismo orden está en el HTML; no depende de una reordenación visual. El enlace inicial lleva al contenido, cuyo tabindex="-1" permite recibir el foco sin añadirlo al recorrido habitual de Tab.
Prueba los enlaces con Tab y Enter, estrecha la ventana y desactiva JavaScript: la lectura y la navegación deben seguir disponibles. Desactivar el bloque <style> deja un documento comprensible en una columna. Retirar solo grid-template-columns también apila el contenido; no elimina ninguna lección. En el código antiguo, retirar <frameset> no fusionaba los archivos: había que migrar su contenido.
Qué debe cambiar además del diseño
Traslada los enlaces de menu.html a <nav> y el contenido útil de leccion.html a <main>. Los encabezados, imágenes y textos alternativos siguen siendo necesarios. Revisa rutas relativas, identificadores repetidos y scripts que dependían de parent, top o de nombres de marcos.
Aquí se carga un único documento. Los enlaces #siembra y #cuidados cambian el fragmento de la URL y permiten volver con el historial; no solicitan otro archivo. Puedes copiar leccion.html#cuidados para abrir directamente ese tema. Si el sitio tiene muchas lecciones, conserva páginas completas con URLs propias y genera la navegación compartida mediante plantillas. Mantén las URLs antiguas importantes o configura redirecciones en el alojamiento: cambiar el layout no las conserva por sí solo.
Errores frecuentes y preguntas
¿Frameset va dentro de body? No en su modelo histórico: sustituía al cuerpo del documento. Ponerlo dentro de <body> o copiar un doctype antiguo no lo convierte en una técnica vigente.
¿Cómo hago columnas sin frameset? Usa estructura HTML apropiada y CSS Grid, como arriba, o Flexbox. Elige tamaños según el contenido y el ancho disponible; cambiar cols por una propiedad CSS exige diseñar la adaptación.
¿Conviene sustituir cada marco por un iframe? Usa <iframe> solo si necesitas incrustar un documento independiente. No lo uses como sustitución automática para el menú y las lecciones: conservarías documentos separados y tendrías que resolver sus límites de navegación y acceso.
<frame> representaba cada marco; <noframes> ofrecía su alternativa histórica. Hoy <nav> identifica la navegación y <main> el contenido principal. Un <div> puede agruparlos para aplicar el layout, pero no sustituye su significado.
Compatibilidad y fuentes
Fuentes revisadas el 4 de octubre de 2026. El Living Standard: funciones obsoletas prohíbe usar <frameset> en contenido nuevo. MDN: <frameset> también lo marca como obsoleto y advierte sobre una posible retirada. Que un navegador todavía interprete marcos no hace válido ese código.
La sintaxis antigua se contrasta con W3C: marcos en HTML 4.01. La migración utiliza CSS Grid: cuadrícula explícita, con contenido que permanece disponible si no se aplica CSS.