Blog

Code Snippet: Oxygen Page Width in Gutenberg Editor

Version: 1.1.1 (May 23, 2024)

Introduction

Oxygen Builder allows to define the page width both in the global settings and individually in single templates.

Gutenberg Editor has a default width of 580 pixels (before WordPress 5.9) or 840 pixels (after WordPress 5.9).
This is fine for editing simple text posts.
However, if more complex content is to be designed, such as columns or blocks arranged side by side, the narrow Gutenberg Editor is a hindrance.

Solution

The code snippet presented here determines the page width defined in Oxygen and displays the Gutenberg Editor in this width.

The snippet first determines the page width defined in the global Oxygen settings.
Then it checks if a different page width is defined for the currently used template. The snippet takes into account the standard templates (start page, blog archive, page and post templates, search results, …) as well as templates individually assigned to the current page.
The determined page width is then applied to the Gutenberg Editor via CSS adjustment.

Please note that the snippet only determines the defined page width. Sidebars, margins or paddings defined in the template cannot be determined.
The page width defined for the Gutenberg Editor does not correspond to a pixel-exact representation. However, the changed page width allows a better assessment of the available space during page editing.

Download

This JSON download can be imported directly into the plugins Code Snippets or Advanced Scripts. Don't forget to activate the snippet after import.
If you are using a different snippet plugin, you can copy the source code instead and create a new snippet yourself.

ma-oxygen-gutenberg-editor-width.code-snippets.json
Version 1.1.1, 2024-05-23

Donation

I enjoy developing code snippets and solving requirements with them. I provide the snippets free of charge.

If you like, you can honor my many hours of work with a small coffee donation via PayPal.

  When clicking the button, a connection to PayPal is established.

Your donation will of course be taxed properly by me.

Disclaimer

I developed the snippet to the best of my knowledge and tested with the most current versions of WordPress and Oxygen.
I provide the code snippet for free use.
I cannot give a guarantee for the functionality in all conceivable WordPress environments.
Download and use of this code snippet is at your own risk and responsibility.

Change Log

See "Version History" in Source Code

Source Code

<?php
/*
Plugin Name:  MA Oxygen Gutenberg Editor Width
Description:  Set Gutenberg editor width to page width defined in Oxygen
Author:       <a href="https://www.altmann.de/">Matthias Altmann</a>
Project:      Code Snippet: Apply Oxygen page width to Gutenberg editor
Version:      1.1.1
Description:  en: https://www.altmann.de/en/blog-en/code-snippet-oxygen-page-width-in-gutenberg-editor/
              de: https://www.altmann.de/blog/code-snippet-oxygen-seitenbreite-im-gutenberg-editor/
Copyright:    © 2020-2024, Matthias Altmann

TESTED WITH:
Product		Versions
--------------------------------------------------------------------------------------------------------------
PHP 		7.4, ..., 8.1
WordPress	5.9, ..., 6.4.2, 6.4.3, 6.5, 6.5.3
Oxygen		4.0, ..., 4.8.1, 4.8.2, 4.8.3
--------------------------------------------------------------------------------------------------------------


VERSION HISTORY
Date		Version		Description
--------------------------------------------------------------------------------------------------------------
2024-05-23	1.1.1		Changes:
						- Improved page width evaluation, now including nested templates
2024-05-22	1.1.0		Changes:
						- Code redesign as class
						- Removed jQuery dependency
						- Compatibility to Oxygen 4.8.3 with changed post meta keys
2022-05-18	1.0.4		Changes:
						- Migrated JavaScript to ES6
2022-02-12				Tested with PHP 8.0, WordPress 5.9, Oxygen 4.0 beta 1
						Changes:
						- Adaptions for WP 5.9: Gutenberg editor class of post header to show width adaptions
						  (Reverted with 1.0.4, since WP now has same class again)
2021-10-03	1.0.3		Bug Fix:
						- Fixed max-width for Gutenberg full-width Group element
2021-03-21	1.0.2		Bug Fix: 
						- Only initialize if Oxygen plugin is active
                          (Thanks to Adrien Robert for reporting!)
2020-12-10	1.0.1		Bug Bixes:
						- Removed alert script (left behind by mistake!)
						- Optimized editor ready detection
						  (Thanks to Nico Weinreich for reporting and the improved script!)
2020-11-16	1.0.0		Initial Release for the Oxygen community


==============================================================================================================
Description
==============================================================================================================
Gutenberg editor has a default page width of 580 pixels (before WP 5.9) or 840px (as of WP 5.9). 
While that is fine for standard blogging websites, it's difficult to create page content without having a clue 
about the actual available page width.

This Code Snippet tries to evaluate the actual page width from Oxygen settings and changes the Gutenberg editor 
width accordingly.

Page Width Evaluation:
1) Read default page width from global Oxygen settings
2) Evaluate default post/page template's width
3) Detect specific template for this page
   - either any type of special template like front page, archive, etc.
   - or the template assigned manually to this post/page, 
   and check for template specific page width
4) If no width specified in template, also check for parent templates (nested templates)
5) Emit CSS to adapt Gutenberg editor to the max-width evaluated by the previous steps, 
   and JS to show a notice in the top bar about the width and where it is defined

Limitations:
This snippet reads the page width defined in global settings or from a specific template and applies that page 
width to the Gutenberg editor. 
The snippet DOES NOT detect any paddings, margins, sidebars etc. in the actual template that might influence 
the final available space. 
That means the width defined for the Gutenberg editor is only a better guessing of available space and sure 
not pixel perfect. Do not rely on the width of the Gutenberg editor for pixel perfect design but use it as a 
rough frame to get a better idea of the available width while editing. 

Performance:
The snippet is only called when creating a new or editing an existing post or page.
The Oxygen global settings as well as the post details have already been retrieved from the database at this 
point. The evaluation of the Oxygen template to be used will require a few other database requests, depending 
on the template nesting levels. 
There should be no noticeable performance impact: Runtime on a local test setup was around 0.02 sec.
*/

if (!class_exists('MA_OxygenGutenbergEditorWidth')) :
class MA_OxygenGutenbergEditorWidth {
	const TITLE							= 'MA Oxygen Gutenberg Editor Width';
	const SLUG							= 'ma-oxygen-gutenberg-editor-width';
	const SHRT 							= 'maogew';
	const VERSION						= '1.1.1';

	//-------------------------------------------------------------------------------------------------------------------
	function __construct(){
		add_action('wp_loaded', [$this,'init']);
	}
	//-------------------------------------------------------------------------------------------------------------------
	/**
	 * Initializes functionality if Gutenberg editor is to be shown.
	 */
	public function init(){
		if (!defined('CT_VERSION')) return;
		
		// check if on edit page
		global $pagenow;
		$editor = false;
		if ($pagenow == 'post-new.php') $editor = true;
		if (($pagenow == 'post.php') && ($_REQUEST['action']??'' == 'edit')) $editor = true;
		if (!$editor) return;
		
		// check if post type supports Gutenberg
		$post_id = isset($_REQUEST['post']) ? $_REQUEST['post'] : 0;
		$edit_with_gutenberg = true;
		if ( isset($_REQUEST['post_type']) ) {
			if ( !post_type_supports($_REQUEST['post_type'], 'editor') ) {$edit_with_gutenberg = false;}
		} else if ( $post_id > 0 ) {
			$post = get_post($post_id);
			if ( $post != null && !post_type_supports($post->post_type, 'editor') ) {$edit_with_gutenberg = false;}
		}
		if (!$edit_with_gutenberg) return;

		add_action('admin_head', [$this, 'set_gutenberg_editor_width']);
	}

	//-------------------------------------------------------------------------------------------------------------------
	public function set_gutenberg_editor_width() {
		$st = microtime(true);
		global $post;
		// exit if we don't have a post object
		if (!isset($post)) return;
		
		$post_id = get_the_id();
		$width = null; 
		$defined_by = '';
	
		// Oxygen pre or post 4.8.3?
		$meta_function_name = function_exists('oxy_get_post_meta') ? 'oxy_get_post_meta' : 'get_post_meta';

		// 1) Check Oxygen global settings for a defined page width
		$ct_global_settings = maybe_unserialize(get_option('ct_global_settings'));
		if ($ct_global_settings && is_array($ct_global_settings) && array_key_exists('max-width',$ct_global_settings)) {
			$width = $ct_global_settings['max-width'].'px';
			$defined_by = 'Oxygen Global Settings';
		}

		// 2) Get default post template
		$template = ct_get_posts_template($post_id);

		// 3a) special template for front or blog page?
		// front and blog page IDs will be automatically "translated" to teh correct language post ID by PolyLang
		$front_id = intval(get_option('page_on_front'));
		$blog_id = intval(get_option('page_for_posts'));
		if (in_array($post_id, [$front_id, $blog_id])) {
			$archives_template = ct_get_archives_template($post_id);
			if ($archives_template) $template = $archives_template;
		}


		// 3b) Check if manually assigned template
		$ct_other_template = intval(call_user_func($meta_function_name, $post_id, 'ct_other_template', true));
		if ($ct_other_template > 0) {
			// use manually assigned template
			$template = get_post($ct_other_template);
		}
		if ($ct_other_template == -1) { // -1 means "None"
			// no template, no editor width change
			return;
		}
		
		if ($template) {
			FIND_TEMPLATE:
			$template_meta = maybe_unserialize(call_user_func($meta_function_name, $template->ID, 'ct_page_settings', true));
			if ($template_meta && is_array($template_meta) && array_key_exists('max-width',$template_meta)) {
				if (!empty($template_meta['max-width'])) {
					$width = $template_meta['max-width'].'px';
					$defined_by = sprintf('template "%s"',$template->post_title);
				} else {
					// 4) any parent template?
					if ($parent_template = intval(call_user_func($meta_function_name, $template->ID, 'ct_parent_template', true))) {
						$parent_template = get_post($parent_template);
						if ($parent_template) {
							$template = $parent_template;
							goto FIND_TEMPLATE;
						}
					}
				}
			}
		}
	
		// 5) Emit CSS and JS
		if ($width) {	
			// style inspired by plugin "Editor Full Width Gutenberg" (https://wordpress.org/plugins/editor-full-width/)
			echo sprintf('<style id="%1$s-style">
				body.block-editor-page .editor-post-title__block, 
				body.block-editor-page .editor-default-block-appender, 
				body.block-editor-page :not(.wp-block) > .block-editor-block-list__block:not([data-align="full"]) {
					max-width: %2$s !important;
				}
				.block-editor__container .wp-block:not([data-align="full"] {
					max-width: %2$s;
				}
				/*code editor*/
				.edit-post-text-editor__body {
					max-width: %2$s !important;	
					margin-left: 2%%;
					margin-right: 2%%;
				}
				</style>',self::SHRT, $width);
			$shrt = self::SHRT;
			$script = <<<END_OF_SCRIPT
			<script id="{$shrt}-script">
			let blockLoadedInterval = setInterval(function () {
				let toolbars = document.getElementsByClassName('edit-post-header-toolbar');
				if (toolbars.length>0) {
					let toolbar = toolbars[0];
					let div = document.createElement('div');
					div.innerHTML = 'Editor width {$width} defined by {$defined_by}';
					toolbar.appendChild(div);
					clearInterval(blockLoadedInterval);
				}
			}, 500);
			</script>
			END_OF_SCRIPT;
			echo $script;
		}
		$et = microtime(true);
		// timing: error_log(sprintf('%s runtime: %.4f s.',self::TITLE, $et-$st));
	}
}
//===================================================================================================================
// Initialize
if (is_admin() && !wp_doing_ajax() && !wp_doing_cron() ) {
	new MA_OxygenGutenbergEditorWidth();
}
endif;
magnifier