WordPress 7.1: el editor de entradas dentro de un iframe
ES

WordPress 7.1: el editor de entradas dentro de un iframe

Última verificación: 9 de agosto de 2026
15 min de lectura
Guía
500+ proyectos WP
Desarrollador full-stack

Si publicas bloques propios, o mantienes sitios de clientes donde corren bloques ajenos, el trabajo de esta semana cabe en un grep y una instalación de prueba. En WordPress 7.1 el editor de entradas va siempre dentro de un iframe. La nota para desarrolladores de Aki Hamano, publicada el 3 de agosto de 2026, lo plantea sin matices: “Starting in WordPress 7.1, the post editor is always iframed, regardless of the theme type, the block API versions of the registered blocks, or the block API versions of the blocks in the content.” No hay forma de desactivarlo ni capa de compatibilidad. Cualquier parte de tu JavaScript del editor que recurra al document o al window globales para tocar el contenido de un bloque apunta ya a la página equivocada, y cualquier hoja de estilos registrada en enqueue_block_editor_assets que debía dar formato al contenido dejará de aplicarse en silencio. WordPress 7.1 llega el 19 de agosto de 2026, así que el sitio donde conviene enterarse es una release candidate.

#Lo que se rompe sin que salte ni un error

El motivo cabe en una frase de esa misma nota: “the iframe has its own document and window, separate from the admin page where editor scripts run.”

El componente edit de tu bloque lo sigue renderizando React desde la página exterior de administración, pero los nodos del DOM que produce viven dentro del iframe. Componente y marcado dejan de compartir document. Una llamada a document.querySelector() desde dentro de un bloque interroga a post.php, no al lienzo. No lanza ninguna excepción. Devuelve null o, peor, algún nodo ajeno del armazón del editor, y el código continúa sobre una premisa falsa.

Esa diferencia decide cuánto cuesta la migración. Una excepción sale en la consola el primer día. Una consulta que devuelve null sale semanas después, como una clase que no se aplica, y llega descrita por teléfono como “el editor se ve raro”.

En React no cambia nada. En block.json no cambia nada. Lo que cambia es que toda una categoría de suposiciones que solía ser cierta casi siempre pasa a ser falsa siempre.

#Por qué ya no queda interruptor

El razonamiento del PR #74042 de Gutenberg, fusionado el 10 de julio de 2026, merece leerse entero, pero la frase operativa es: “far more breakage is caused by the inconsistency than blocks not functioning well with iframe.”

Es una decisión de ingeniería defendible: dos entornos de renderizado con un conmutador en tiempo de ejecución son un contrato peor que un único entorno que a veces resulta incómodo. También significa que las salidas de emergencia están cerradas: el pull request elimina la ruta sin iframe, y un revisor anota que switchToLegacyCanvas() “does nothing anymore.” Si tenías previsto comprar un ciclo de versiones con un filtro, no queda filtro al que recurrir.

La presión en contra es real y está documentada. En la incidencia de seguimiento #70743, el desarrollador principal de Meta Box escribió: “Switching to version 3 is impossible at the moment, as most of the JS the plugins use are using jQuery with DOM manipulation.” No es el problema de un plugin suelto. Describe una parte considerable del ecosistema comercial de metacajas y campos personalizados sobre el que se apoyan muchos sitios construidos por agencias.

#Por qué esto no dolía hasta ahora

El iframe no es nuevo. Lo nuevo es que han desaparecido las condiciones que lo mantenían apagado.

VersiónComportamiento
5.8El editor de plantillas va dentro de un iframe.
6.3El editor de entradas va dentro de un iframe solo si todos los bloques registrados declaran Block API versión 3 o superior. enqueue_block_assets empieza a llegar al lienzo.
6.9Aparecen avisos en consola para apiVersion 2 o inferior con SCRIPT_DEBUG. El esquema de block.json limita los bloques nuevos a la versión 3.
7.0La comprobación se reduce a los bloques realmente insertados en la entrada. La nota para desarrolladores de 7.0, de Ella Van Durpe, dice sin rodeos que en 7.0 el iframe no se fuerza.
7.1Siempre dentro de un iframe.

Esa regla de 6.3 explica casi toda la confusión que uno encuentra en producción. Como bastaba un único bloque registrado con apiVersion 2 en cualquier rincón del sitio para devolver el editor entero a la ruta sin iframe, un plugin podía estar completamente roto dentro del iframe sin que nadie lo viera nunca, mientras un solo bloque heredado impidiera que el iframe entrase en juego. La condición funcionaba como un silenciador de informes de error, con una consecuencia incómoda: que un plugin no haya fallado en tres años no dice nada sobre si está listo.

El editor del sitio, en cambio, ha ido siempre dentro de un iframe: de ahí que el mismo plugin se comporte de forma distinta según la pantalla en la que trabaje quien edita.

#Los fallos y sus correcciones

La referencia es la página del manual sobre migración de bloques para compatibilidad con el iframe. Así son las correcciones en la práctica.

#Búsquedas contra el document global

Esta categoría produce respuestas erróneas en silencio en lugar de errores. La incidencia #55947 de Gutenberg es un ejemplo limpio: un script encolado con enqueue_block_editor_assets lee document.body.classList y obtiene el documento exterior de post.php, así que la clase que comprueba nunca está ahí.

Antes:

import { useEffect } from '@wordpress/element';

export default function Edit( { attributes } ) {
	useEffect( () => {
		// `document` is the admin page. This finds nothing in 7.1.
		const heading = document.querySelector( '.wp-block-my-plugin-hero h2' );
		if ( heading && document.body.classList.contains( 'is-dark-theme' ) ) {
			heading.dataset.contrast = 'inverted';
		}
	}, [ attributes.style ] );

	return <div className="wp-block-my-plugin-hero">{ /* ... */ }</div>;
}

Después:

import { useRefEffect } from '@wordpress/compose';

export default function Edit( { attributes } ) {
	const ref = useRefEffect(
		( element ) => {
			// Resolve the canvas from a node that is already inside it.
			const canvas = element.ownerDocument;
			const heading = element.querySelector( 'h2' );
			if ( heading && canvas.body.classList.contains( 'is-dark-theme' ) ) {
				heading.dataset.contrast = 'inverted';
			}
		},
		[ attributes.style ]
	);

	return <div ref={ ref } className="wp-block-my-plugin-hero">{ /* ... */ }</div>;
}

Han cambiado dos cosas. element.ownerDocument devuelve el documento que contiene realmente ese nodo, sea cual sea, de modo que el mismo código sirve en el editor de entradas, en el editor del sitio y en cualquier superficie futura. Y la búsqueda del encabezado queda acotada al elemento del propio bloque en lugar de recorrer un documento entero, que era lo correcto desde el principio.

#Medidas y escuchas ancladas al window equivocado

Todo lo que se mide sobre window sufre lo mismo, y resulta más peligroso porque window.innerWidth devuelve un número real. Solo que es el número equivocado: el del viewport del navegador y no el del lienzo, que en un editor a dos paneles con la barra lateral de ajustes abierta puede ser varios cientos de píxeles más estrecho que el área donde se renderiza el bloque.

Antes:

import { useState, useEffect } from '@wordpress/element';

export default function Edit() {
	const [ width, setWidth ] = useState( 0 );

	useEffect( () => {
		const onResize = () => setWidth( window.innerWidth );
		onResize();
		window.addEventListener( 'resize', onResize );
		return () => window.removeEventListener( 'resize', onResize );
	}, [] );

	return <div>{ width }</div>;
}

Después:

import { useState } from '@wordpress/element';
import { useRefEffect } from '@wordpress/compose';

export default function Edit() {
	const [ width, setWidth ] = useState( 0 );

	const ref = useRefEffect( ( element ) => {
		const view = element.ownerDocument.defaultView;
		const onResize = () => setWidth( view.innerWidth );
		onResize();
		view.addEventListener( 'resize', onResize );
		return () => view.removeEventListener( 'resize', onResize );
	}, [] );

	return <div ref={ ref }>{ width }</div>;
}

element.ownerDocument.defaultView es la window que pertenece al lienzo. Enlaza las escuchas a través de ella, desde una callback de ref y no desde un efecto que no sabe contra qué documento se ejecuta.

Pasar de useRef más useEffect a useRefEffect no es cosmética. La callback de useEffect no se vuelve a llamar cuando cambia la ref, y en un editor dentro de un iframe la ref cambia de verdad: el nodo del lienzo se crea, se sustituye y se desmonta a lo largo de una misma sesión de edición. Un efecto que se ejecutó una sola vez contra un nodo que ya no existe es la vía directa a tener escuchas sobre un documento muerto y una limpieza que nunca llega a ejecutarse. El PR #52588 de Gutenberg convierte ese desmontaje en algo concreto, con un Cannot read properties of null (reading 'getComputedStyle') lanzado justo cuando el iframe desaparece.

#jQuery, select2 y todo lo que tira de un global

Esta es la categoría que describía el comentario de Meta Box, y es donde se acumula la mayor parte del código que mantienen las agencias. La incidencia #47924 documenta cómo se rompen dentro del iframe el select2 de ACF y el datepicker de jQuery UI.

Antes:

import { useEffect } from '@wordpress/element';

export default function Edit( { clientId } ) {
	useEffect( () => {
		jQuery( `#my-plugin-select-${ clientId }` ).select2( { width: '100%' } );
	}, [ clientId ] );

	return <select id={ `my-plugin-select-${ clientId }` }>{ /* ... */ }</select>;
}

Después:

import { useRefEffect } from '@wordpress/compose';

export default function Edit() {
	const ref = useRefEffect( ( element ) => {
		const $ = element.ownerDocument.defaultView.jQuery;
		if ( ! $ ) {
			return;
		}
		const $select = $( element );
		$select.select2( { width: '100%' } );
		return () => {
			$select.select2( 'destroy' );
		};
	}, [] );

	return <select ref={ ref }>{ /* ... */ }</select>;
}

La corrección la sostienen tres cambios. La biblioteca se resuelve desde la window del lienzo en lugar de desde un global, que es el patrón defaultView.jQuery(element). El elemento se pasa directamente en vez de buscarse por identificador, así que no queda ninguna búsqueda entre documentos. Y la limpieza devuelta destruye el widget cuando el nodo desaparece, que es justo la parte que omite casi todo el código existente, porque antes del iframe el nodo prácticamente no desaparecía nunca.

Si jQuery no está presente en la window del lienzo, el problema es de encolado y no de JavaScript, lo que lleva a la última categoría.

#Estilos y scripts encolados en la superficie equivocada

La regla de la página del manual sobre encolado de recursos en el editor es un reparto limpio. enqueue_block_editor_assets es para la interfaz del editor: barras laterales, barras de herramientas, paneles de plugins, botones de formato. enqueue_block_assets es para el contenido, y llega tanto al lienzo como al frontend.

Antes:

add_action( 'enqueue_block_editor_assets', function () {
	wp_enqueue_style(
		'my-plugin-blocks-editor',
		plugins_url( 'build/blocks.css', __FILE__ ),
		array(),
		'1.4.0'
	);
} );

Después:

// Editor interface only: panels, toolbars, sidebar controls.
add_action( 'enqueue_block_editor_assets', function () {
	wp_enqueue_style(
		'my-plugin-blocks-panels',
		plugins_url( 'build/panels.css', __FILE__ ),
		array(),
		'1.4.0'
	);
} );

// Content: applies inside the canvas and on the front end.
add_action( 'enqueue_block_assets', function () {
	wp_enqueue_style(
		'my-plugin-blocks-content',
		plugins_url( 'build/blocks.css', __FILE__ ),
		array(),
		'1.4.0'
	);
} );

Equivocarse aquí no genera ningún error. La hoja de estilos se carga, el navegador informa de un 200 y las reglas no encuentran nada en el lienzo, porque se inyectaron en otro documento. La incidencia #53236 de Gutenberg recoge exactamente eso: una hoja encolada para el editor deja de aplicarse al lienzo sin avisar.

El mismo reparto vale para los scripts: lo que deba ejecutarse contra nodos de contenido hay que cargarlo donde viven esos nodos.

#Las metacajas clásicas ya no dejan el editor fuera del iframe

Registrar metacajas clásicas era una de las vías que en la práctica mantenían el editor de entradas fuera del iframe. En 7.1 deja de serlo. La guía de campo de 7.1, publicada el 5 de agosto de 2026, lo dice en una línea: “WordPress 7.1 completes the move to an iframe-based post editor, including for sites that register legacy meta boxes.” En castellano: el paso al editor dentro de un iframe alcanza también a los sitios que registran metacajas heredadas.

Para una agencia es la superficie de fallo más incómoda, porque no afecta a los bloques propios sino a la cartera ya entregada: metacajas a medida en el tema hijo, grupos de campos de ACF renderizados a la manera clásica, paneles de plugins de tienda. Son pantallas que llevan años abriéndose sin iframe y que, por eso mismo, nunca se han probado dentro de uno.

#Qué revisar en una cartera de sitios ajenos

Cuando mantienes sitios que no construiste, la pregunta que bloquea no es “¿está listo nuestro código?”, sino “¿de qué parte del código de estos sitios ya no responde nadie?”. Ese inventario es trabajo de ingeniería y conviene hacerlo antes de que alguien llame diciendo que la maquetación se ve mal.

  • Levanta el inventario de bloques. Para cada sitio, anota qué plugins y temas registran bloques y qué apiVersion declara cada uno. Subir el número no arregla el comportamiento en 7.1, pero el recuento de bloques en versión 2 indica por dónde empezar a mirar.
  • Separa lo mantenido de lo abandonado. Para cada plugin afectado, comprueba la fecha de la última versión y si el desarrollador ha dicho algo sobre la compatibilidad con el iframe. Un plugin mantenido significa esperar y probar. Uno abandonado significa elegir entre un parche local, un fork o un sustituto, y esa decisión tiene su plazo de ejecución.
  • Rastrea tu propio código. Busca en cada plugin y tema a medida de la cartera las apariciones de document. y window. en los bundles del editor, además de jQuery( y de cualquier manejador de enqueue_block_editor_assets que registre estilos de contenido. Es una pasada rápida y mecánica con un resultado concreto.
  • Mira aparte la capa de metacajas. ACF, Meta Box y herramientas equivalentes están en la franja de mayor riesgo, y suelen estar instaladas justo en los sitios donde la redacción detecta antes cualquier avería.
  • Haz una segunda pasada por las pantallas con metacajas. Tras la prueba de bloques, abre cada tipo de contenido que registre metacajas clásicas: rellena los campos, guarda, recarga y comprueba que los valores han vuelto. Va aparte porque son las pantallas que hasta 7.1 se abrían sin iframe.
  • Prueba el flujo de edición, no solo la carga de la página. Los fallos de desmontaje solo salen a la luz cuando los bloques se insertan, se mueven y se borran. Una prueba de humo que abre una entrada y la mira pasará sin problemas en una instalación rota.
  • Ordena el trabajo por carga editorial. Un sitio cuyo equipo publica a diario tiene que estar limpio antes del 19 de agosto. Un sitio corporativo que se edita dos veces al año, no.

Nada de esto es exótico: un inventario, un grep y una matriz de pruebas, que pertenecen a un ciclo planificado y no a una urgencia. Si prefieres delegarlo dentro de una colaboración continua, encaja en un programa de mantenimiento de WordPress, donde probar las versiones del núcleo ya está en el calendario. El presupuesto es siempre individual, porque depende del número de sitios y de cuánto código sin dueño arrastran.

#La prueba de diez minutos

Para saber si tienes un problema no hace falta una auditoría completa. Hace falta una instalación.

  1. Fuerza el iframe hoy mismo, sin esperar a la versión. La misma nota para desarrolladores deja constancia de que “since Gutenberg 22.6, when the plugin is active the post editor is forced to be iframed regardless of the theme type or the block API versions in use”, es decir, desde la 22.6 basta con tener activo el plugin Gutenberg para que el editor de entradas vaya dentro del iframe, sea cual sea el tipo de tema o las versiones de la Block API en uso. Instálalo en un staging y tendrás el comportamiento de 7.1 sobre el núcleo actual. La vía alternativa sigue siendo un sitio desechable con WordPress 7.1 RC, un contenedor local o un staging temporal bastan.
  2. Activa un plugin que registre un bloque con apiVersion 2. Sirve cualquier bloque heredado de tu propio catálogo, o uno de un sitio de cliente.
  3. Abre el editor de entradas e inserta el bloque.
  4. Abre la consola del navegador y déjala abierta mientras trabajas con el bloque: escribe dentro, cambia un ajuste en la barra lateral, salta a otro bloque y vuelve, y por último bórralo.
  5. Lee lo que sale. Lecturas de propiedades sobre null al desmontar, selectores que devuelven null, estilos que faltan en el lienzo y que en el frontend aparecen correctamente.

Dos advertencias para interpretar el resultado. Activa SCRIPT_DEBUG, porque los avisos de apiVersion añadidos en 6.9 solo aparecen con esa constante. Y comprueba los estilos con la vista, no solo la consola: el desvío de recursos descrito arriba es completamente mudo.

Diez minutos dan un sí o un no por plugin, y con eso se dimensiona el trabajo real.

#Fuentes

Siguiente paso

Transforma el artículo en una implementación real

Este bloque refuerza el enlazado interno y lleva al lector al siguiente paso más útil dentro de la arquitectura del sitio.

¿Quieres implementar esto en tu sitio?

Si quieres transformar el artículo en mejoras concretas, rediseño o un plan de implementación, puedo cerrar el alcance y ejecutar.

¿Se puede desactivar el iframe en WordPress 7.1?#
No. El PR 74042 de Gutenberg eliminó la ruta del editor sin iframe, y un revisor de ese pull request dejó constancia de que switchToLegacyCanvas() ya no hace nada. No hay filtro para desactivarlo ni capa de compatibilidad.
¿Hay que migrar todos los bloques a la versión 3 de la Block API?#
En 7.1 el valor de apiVersion ya no decide si el editor va dentro de un iframe, así que subir el número por sí solo no arregla nada. La versión 3 es una declaración de que el bloque funciona dentro del iframe, y el trabajo real consiste en eliminar las suposiciones sobre el document y la window globales.
¿Por qué una hoja de estilos del editor dejó de aplicarse al contenido?#
Los estilos registrados en enqueue_block_editor_assets se cargan en el documento exterior de administración, que es donde vive la interfaz del editor. Los estilos que deben afectar al contenido en sí van en enqueue_block_assets, que sí llega al lienzo. La incidencia 53236 de Gutenberg recoge exactamente ese síntoma.
¿En qué versión de WordPress el editor de entradas pasó a estar siempre dentro de un iframe?#
En WordPress 7.1. La nota para desarrolladores de 7.0 afirma sin rodeos que en 7.0 el iframe no se fuerza, y que allí la comprobación solo se redujo a los bloques realmente insertados en la entrada.

¿Necesitas un FAQ adaptado a tu sector y mercado? Preparamos una versión alineada con tus objetivos de negocio.

Hablemos

Artículos Relacionados