The new template editor is loaded in an iframe iFrame is an acronym for an inline frame. An iFrame is used inside a webpage to load another HTML document and render it. This HTML document may also contain JavaScript and/or CSS which is loaded at the time when iframe tag is parsed by the user’s browser. to isolate it from the rest of the admin (and super admin) screen. This has the following benefits:
- Admin styles no longer affect the editor content, so there’s no need to reset any of these rules.
- Content styles no longer affect the admin screen, so block Block is the abstract term used to describe units of markup that, composed together, form the content or layout of a webpage using the WordPress editor. The idea combines concepts of what in the past may have achieved with shortcodes, custom HTML, and embed discovery into a single consistent API and user experience. and theme CSS Cascading Style Sheets. rules no longer need to be prefixed.
- Viewport relative CSS units will work correctly. The dimensions of the editor content is usually not the same as the dimensions of the admin page, so without an iframe units like
vw
will be relative to the admin page. - Media queries will also work natively, without needing to fake them, as we did before, which is fragile.
- In general, it makes the lives of block and theme authors easier because styles from the front-end can be dropped in with very little, if nothing, to adjust. This also applies to lighter blocks, where the editor DOM structure matches the front-end, which we highly recommend when possible.
- With a separate window for the editor content, it’s possible for the selection in the editor to remain visible while also having a (collapsed) selection in the editor UI User interface, for example an input field for a URL A specific web address of a website or web page on the Internet, such as a website’s URL www.wordpress.org.
We currently only iframe new editors. While the new template editor has been iframed, the post editor remains unchanged. We do this to gradually test how existing blocks from plugins work within an iframed editor, since there are cases where a block could look broken or (less likely) error. We hereby urge plugin A plugin is a piece of software containing a group of functions that can be added to a WordPress website. They can extend functionality or add new features to your WordPress websites. WordPress plugins are written in the PHP programming language and integrate seamlessly with WordPress. These can be free in the WordPress.org Plugin Directory https://wordpress.org/plugins/ or can be cost-based plugin from a third-party authors to test their blocks with the new template editor and contact us if they need help to adjust blocks to work in the iframe.
Document and window
The iframe will have a different document
and window
than the admin page, which is now the parent window. Editor scripts are loaded in the admin page, so accessing the document
or window
to do something with the content will no longer work.
Most blocks written in React React is a JavaScript library that makes it easy to reason about, construct, and maintain stateless and stateful user interfaces. https://reactjs.org/. should continue to work properly, except if you rely on document
or window
. To fix, you need to create ref to access the relative document (ownerDocument
) or window (defaultView
). Regardless of the iframe, it is good practice to do this and avoid the use of globals.
const ref = useRef();
useEffect( () => {
const { ownerDocument } = ref.current;
const { defaultView } = ownerDocument;
// Set ownerDocument.title for example.
}, [] );
const props = useBlockProps( { ref } );
If you attach event handlers, remember that the useEffect
callback will not be called if the ref changes, so it is good practice to use the new useRefEffect
API An API or Application Programming Interface is a software intermediary that allows programs to interact with each other and share data in limited, clearly defined ways., which will call the given callback if the ref change in addition to any dependencies passed.
const ref = useRefEffect( ( element ) => {
const { ownerDocument } = element;
const { defaultView } = ownerDocument;
defaultView.addEventListener( ... );
return () => {
defaultView.removeEventListener( ... );
};
}, [] );
const props = useBlockProps( { ref } );
Other frameworks and libraries
For the editor, scripts such as jQuery are loaded in the parent window (admin page), which is fine. When using these to interact with a block in the iframe, you should pass the element reference.
const ref = useRefEffect( ( element ) => {
jQuery( element ).masonry( … );
return () => {
defaultView.jQuery( element ).masonry( 'destroy' );
}
}, [] );
const props = useBlockProps( { ref } )
But what if the library is using the global window or document and it’s out of your control?
Submit an issue or PR for the library to use ownerDocument
and defaultView
instead of the globals. Ideally, any library should allow initialisation with an element in an iframe as the target. It’s never impossible. Feel free to contact us to mention the issue.
In the meantime, you can use the script that is loaded inside the iframe. We’ve loaded all front-end scripts in the iframe to fix these cases, but note that ideally you shouldn’t use scripts loaded in the iframe at all. You can use defaultView
to access the script.
const ref = useRefEffect( ( element ) => {
const { ownerDocument } = element;
const { defaultView } = ownerDocument;
// Use the script loaded in the iframe.
// Script are loaded asynchronously, so check is the script is loaded.
// After the dependencies have loaded, the block will re-render.
if ( ! defaultView.jQuery ) {
return;
}
defaultView.jQuery( element ).masonry( … );
return () => {
defaultView.jQuery( element ).masonry( 'destroy' );
}
} );
const props = useBlockProps( { ref } );
And that’s it! In summary, any problem that a block might have in the iframe is caused by using the document
or window
global at the root of it, either in the block’s code or a third party library. Ideally, all code uses the ownerDocument
and defaultView
relative properties.
#5-8, #dev-notes, #gutenberg