Improved PHP performance for core blocks registration

WordPress 6.1 also comes with a considerable performance improvement for handling blocks in plugins and in the WordPress backend (PHPPHP The web scripting language in which WordPress is primarily architected. WordPress requires PHP 5.6.20 or higher).

Early block.json Registration Method

Starting with WordPress 5.8, extenders were encouraged to begin to utilize block.json to register blocks through a unified registration process. The benefits offered by this update provide consistency and convenience when registering blocks through PHP or JavaScriptJavaScript JavaScript or JS is an object-oriented computer programming language commonly used to create interactive effects within web browsers. WordPress makes extensive use of JS for a better user experience. While PHP is executed on the server, JS executes within a user’s browser. https://www.javascript.com/..

However, while this block.json scanning convention is extremely convenient, it does add additional processing when coreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress. blocks are instantiated. On each page load, blockBlock 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. registration undergoes the following steps:

  • Scan folders for block.json files.
  • When a block.json file is found, read its contents into memory.
  • Call json_decode on the file contents to convert it to a PHP array.
  • Register the block using the decoded data.

With over 70 core block files to scan and load, this presented an opportunity for optimization.

Core Block Registration Update

To reduce filesystem reads and processing of block.json files, which should benefit all WordPress sites and improve performance, block registration has been updated to:

  • Introduce a new Grunt task (copy:block-json) that scans and converts core block.json files to PHP arrays and stores them in a single blocks-json.php at build time.
  • Use the new blocks-json.php file in the register_block_type_from_metadata() function.
  • Assign the block registration data to a static variable (cache) so that it’s only loaded once per request.

The addition of an extra build task to compile the decoded JSONJSON JSON, or JavaScript Object Notation, is a minimal, readable format for structuring data. It is used primarily to transmit data between a server and web application, as an alternative to XML. data to PHP reduces block registration filesystem reads from ~70 files to just a single file. And since blocks-json.php is a native PHP array, it can be used directly without additional conversion.

The conversion from block.json files to PHP arrays is achieved through the json2php package, which is already utilized in Core and GutenbergGutenberg The Gutenberg project is the new Editor Interface for WordPress. The editor improves the process and experience of creating new content, making writing rich content much simpler. It uses ‘blocks’ to add richness rather than shortcodes, custom HTML etc. https://wordpress.org/gutenberg/.

References

Props to @aristath for source material and collaboration, and to @milana_cap for review of this dev notedev note Each important change in WordPress Core is documented in a developers note, (usually called dev note). Good dev notes generally include a description of the change, the decision that led to this change, and a description of how developers are supposed to work with that change. Dev notes are published on Make/Core blog during the beta phase of WordPress release cycle. Publishing dev notes is particularly important when plugin/theme authors and WordPress developers need to be aware of those changes.In general, all dev notes are compiled into a Field Guide at the beginning of the release candidate phase..

#6-1, #dev-notes, #dev-notes-6-1, #performance

Improvements to WP_Query performance in 6.1

Adding caching to database queries in WP_Query

WordPress 6.1 includes an improvement to how database queries are performed in the WP_Query class, resulting in database queries will be cached. This means that if the same database query is run more than once, the result will be loaded from cache. For those using persistent object caching, this will mean that the database query will not run again until caches are invalidated, resulting in far fewer queries to the database. Sites using in-memory caching will also see the benefit of not repeating these queries, though the performance improvement will not be as significant. 

For those doing custom development, please ensure that you are using coreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress. functions such as wp_insert_post to add posts to the database. These functions are well-maintained, and by using them, you ensure that caches are correctly invalidated. If you are updating the database directly, then it is strongly recommended that you call the clean_post_cache function after updating the database row. 

It is worth noting that by default, all calls to WP_Query will be cached going forward. It is possible to opt out of caching queries by simply passing the cache_results parameter as false. See example:

$args = array(
   'posts_per_page' => 50,
   'cache_results'  => false
);
$query = new WP_Query( $args );

It is also possible to globally disable caching, using a filterFilter Filters are one of the two types of Hooks https://codex.wordpress.org/Plugin_API/Hooks. They provide a way for functions to modify data of other functions. They are the counterpart to Actions. Unlike Actions, filters are meant to work in an isolated manner, and should never have side effects such as affecting global variables and output.:

function disable_caching( $wp_query ) {
   $wp_query->query_vars['cache_results'] = false;
}
add_action( 'parse_query', 'disable_caching' );

Disabling caching like this should only be done in extreme cases. For best performance, it is highly recommended to keep caching enabled and invalidate caches using the clean_post_cache function. 

Cache keys are generated using the parameters passed to the WP_Query class instance. However, the following parameters are ignored:

  • suppress_filters
  • cache_results
  • fields
  • update_post_meta_cache
  • update_post_term_cache
  • update_menu_item_cache
  • lazy_load_term_meta

These parameters do not affect the database query that is run. The most important ignored parameter is fields. This means that if you run the following: 

$args1 = array(
	'posts_per_page' => 50,
	'fields'  => 'ids'
);
$query1 = new WP_Query( $args1 );

$args2 = array(
	'posts_per_page' => 50,
	'fields'  => 'all'
);
$query2 = new WP_Query( $args2 );

In both cases, the query will now request all fields, so that the result can be cached and then be used regardless of the fields parameter. Prior to this change, the database query for those two was different, but keeping it like that would have resulted in multiple caches for effectively subsets of the same data. This means that there is now less of a performance improvement when limiting fields ids than there was in the previous version of WordPress. 

This change also means that the update_post_meta_cache and update_post_term_cache caches are always respected. 

In cases where caching was added to WP_Query by using plugins such as advanced-post-cache, Enhanced Post Cache or Cache WP_Query, it is recommended that these plugins are disabled and removed as they are no longer required.

For more info, see TracTrac An open source project by Edgewall Software that serves as a bug tracker and project management tool for WordPress. ticketticket Created for both bug reports and feature development on the bug tracker. #22176

Prime users cache in WP_Query

WordPress 6.1 introduces a new function, update_post_author_caches. Prior to 6.1, sites with multiple authors required several single database queries to get author information, as the user is loaded as part of the loopLoop The Loop is PHP code used by WordPress to display posts. Using The Loop, WordPress processes each post to be displayed on the current page, and formats it according to how it matches specified criteria within The Loop tags. Any HTML or PHP code in the Loop will be processed on each post. https://codex.wordpress.org/The_Loop.. Instead of loading each user one by one, user (author) caches are now primed in a single database call by calling update_post_author_caches at the start of the loop, resulting in far fewer database queries. 

This function accepts an array of post objects and will prime user caches. Calls to update_post_author_caches have also been added in key parts of the codebase to improve database performance.

For more info, see Trac ticket #55716

Prime linked objects for menu items

A new function has been added to core called update_menu_item_cache. It accepts an array of post objects and will prime caches for post or terms referenced in a menu item. A new parameter for WP_Query has been added called update_menu_item_cache. When set to true it will call update_menu_item_cache which will allow you to prime menu items in a two database queries (one for posts and one for terms). 

For more info, see Trac ticket #55620

get_page_by_title now uses WP_Query

The function get_page_by_title now uses WP_Query. Previously,  this function used a raw database query to get the page by title. As noted above, WP_Query is now cached, meaning that calls to get_page_by_title will also be cached. This also has the benefit of running through all the filters in WP_Query

For more info, see Trac ticket #36905 

Thanks to @flixos90@milana_cap@peterwilsoncc for peer review and @mxbclang for proofreading.

#6-1, #dev-notes, #dev-notes-6-1, #performance

Introducing “Update URI” theme header in WordPress 6.1

WordPress 6.1 introduces a new headerHeader The header of your site is typically the first thing people will experience. The masthead or header art located across the top of your page is part of the look and feel of your website. It can influence a visitor’s opinion about your content and you/ your organization’s brand. It may also look different on different screen sizes. available for theme authors. This allows third-party themes to avoid accidentally being overwritten with an update of a theme of a similar name from the WordPress.orgWordPress.org The community site where WordPress code is created and shared by the users. This is where you can download the source code for WordPress core, plugins and themes as well as the central location for community conversations and organization. https://wordpress.org/ Theme Directory.

Previously, any custom theme which used the same slug as a theme hosted on WordPress.org was taking a significant risk of being overwritten by an update of the latter.

WordPress 6.1 introduces a new Update URI theme header field. If the value of this new field matches any URI other than https://wordpress.org/themes/{$slug}/ or w.org/theme/{$slug}, WordPress will not attempt to update it.

If set, the Update URI header field should be a URI and have a unique hostname.

Some examples include:

  • https://wordpress.org/themes/example-theme/
  • https://example.com/my-theme/
  • my-custom-theme-name

Update URI: false also works, and unless there is code handling the false hostname, the theme will never get an update notification.

If the header is present, the WordPress.org APIAPI 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. will currently only return updates for the theme if it matches the following format:

  • https://wordpress.org/themes/{$slug}/
  • w.org/theme/{$slug}

If the header has any other value, the API will not return a result and will ignore the theme for update purposes.

Additionally, WordPress 6.1 introduces the update_themes_{$hostname} filterFilter Filters are one of the two types of Hooks https://codex.wordpress.org/Plugin_API/Hooks. They provide a way for functions to modify data of other functions. They are the counterpart to Actions. Unlike Actions, filters are meant to work in an isolated manner, and should never have side effects such as affecting global variables and output., which third-party themes can use to offer updates for a given hostname. They can be used to filter the update response in multiple use cases.

This new hook filters the update response for a given theme hostname. The dynamic portion of the hook name, $hostname, refers to the hostname of the URI specified in the Update URI header field.

The hook has four arguments:

  • $update: The theme update data with the latest details. Default false.
  • $theme_data: The list of headers provided by the theme.
  • $theme_stylesheet: The theme stylesheet.
  • $locales: Installed locales to look translations for.

Please note that authors of themes hosted by WordPress.org don’t need to use this new header.

For reference, see tickets #14179, and changeset [53933].

Special thanks to @audrasjb and @sergeybiryukov as this post closely plagarizes Introducing “Update URI” plugin header in WordPress 5.8 and the commit message. Thanks to @costdev and @pbiron for review.

#6-1, #dev-notes, #dev-notes-6-1

New cache Site Health checks in WordPress 6.1

As part of the WordPress 6.1 release, the Performance Team has added two Site Health checks (Persistent Object Cache and Page Cache). These checks were previously tested in the Performance Lab plugin. You can read more about them in the original proposal.

Both checks will run only in a production environment.

Persistent Object Cache

This new check determines whether the site uses a persistent object cache or not and recommends it if it makes sense for the site. It also links to a support resource created for the check.

A few filters have been included aiming for hosting providers to provide more specific steps regarding their environment.

Hosts may use the site_status_persistent_object_cache_url filterFilter Filters are one of the two types of Hooks https://codex.wordpress.org/Plugin_API/Hooks. They provide a way for functions to modify data of other functions. They are the counterpart to Actions. Unlike Actions, filters are meant to work in an isolated manner, and should never have side effects such as affecting global variables and output. to replace the original WordPress guide with their own guide.

/**
 * Filter the Persistent object cache URL.
 */
add_filter( 'site_status_persistent_object_cache_url', function() {
	return 'https://awesomewphosting.com/optimization/persistent-object-cache';
} );

Hosts may use the site_status_persistent_object_cache_notes filter to customize the notes to recommend their preferred object cache solution.

/**
 * Update the persistent object cache notes.
 */
add_filter( 'site_status_persistent_object_cache_notes', function( $notes ) {
	$notes = __( 'The updated notes can go here as text.', 'text-domain' );

	return $notes;
} );

The site_status_persistent_object_cache_thresholds filter allows modifying the thresholds above WordPress considers using a persistent object cache beneficial.

/**
 * Override the whole $thresholds array, or any specific indexes as required.
 */
add_filter( 'site_status_persistent_object_cache_thresholds', function( $thresholds ) {
	$thresholds = array(
		'alloptions_count' => 600,
		'alloptions_bytes' => 200000,
		'comments_count'   => 2000,
		'options_count'    => 2000,
		'posts_count'      => 2000,
		'terms_count'      => 2000,
		'users_count'      => 2000,
	);

	return $thresholds;
} );

Alternatively, site_status_should_suggest_persistent_object_cache is a short-circuit filter that allows using entirely custom logic to determine whether a persistent object cache would make sense for the site.

/**
 * Opt in for suggesting the persistent object cache
 */
add_filter( 'site_status_should_suggest_persistent_object_cache', '__return_true' );

For additional context on this new check, see #56040.

Full Page Cache

This new check determines whether the site is using a full page cache solution and if the response time is acceptable.

It also adds a couple of filters aiming for hosting companies to customize the response threshold and add their own cache headers to be detected.

The site_status_good_response_time_threshold filter allows modifying the current threshold of 600ms. Everything below this will be considered acceptable.

/**
 * Filter the response time threshold
 */
add_filter( 'site_status_good_response_time_threshold', function() {
	return 200;
} );

Additional custom cache headers ( and optionally their verification callbacks) can be added through the site_status_page_cache_supported_cache_headers filter.

/**
 * Filter the page cache supported cache headers
 * $cache_headers contains List of client caching headers and their (optional) verification callbacks.
 */
add_filter( 'site_status_page_cache_supported_cache_headers', function( $cache_headers  ) {
	// Add new header to the existing list.
	$cache_headers['cf-cache-status'] = static function ( $header_value ) {
		return false !== strpos( strtolower( $header_value ), 'hit' );
	};
	return $cache_headers;
});

For additional context on this new check, see #56041.

Thanks to @flixos90, @milana_cap, @spacedmonkey for peer review, and @pushpakpop for the code examples.

#6-1, #core-site-health, #dev-notes, #dev-notes-6-1, #performance, #performance-lab, #site-health

Block-based “template parts” in traditional themes

Starting in WordPress 6.1, traditional WordPress themes can adopt the usage of blockBlock 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.-based template parts in their themes. To enable this feature a theme needs to specify the block-template-parts theme support. The theme developer can add block-based template parts by placing HTMLHTML HyperText Markup Language. The semantic scripting language primarily used for outputting content in web browsers. files containing the block template into the /parts folder inside the root directory of the theme.

function add_block_template_part_support() {
    add_theme_support( 'block-template-parts' );
}

add_action( 'after_setup_theme', 'add_block_template_part_support' );

These block-based template parts can now be used in the traditional PHPPHP The web scripting language in which WordPress is primarily architected. WordPress requires PHP 5.6.20 or higher templates by using the block_template_part function.

Example:

If a theme developer wants to make the site footer editable using blocks, they can create a new file called footer.html inside the my-theme/parts/ directory. This file should contain the default markup of the blocks used to build the footer.

<!-- wp:group {"layout":{"inherit":true}} -->
<div class="wp-block-group">
	<!-- wp:group {"style":{"spacing":{"padding":{"top":"80px","bottom":"30px"}}}} -->
	<div class="wp-block-group" style="padding-top:80px;padding-bottom:30px">
		<!-- wp:paragraph {"align":"center"} -->
		<p class="has-text-align-center">Proudly Powered by <a href="https://wordpress.org" rel="nofollow">WordPress</a></p>
		<!-- /wp:paragraph -->
	</div>
	<!-- /wp:group -->
</div>
<!-- /wp:group -->

To actually use this template part the theme author then needs to call the block_template_part function and pass the name of the template part as the first and only parameter.

<?php block_template_part( 'footer' ); ?>

Props to @mamaduka, @bph, and @annezazu for reviewing this post.

#6-1, #dev-notes, #dev-notes-6-1

Fluid font sizes in WordPress 6.1

In WordPress 6.1, “Fluid font sizes” make their debut. This enables font sizes to adapt to changes in screen size, for example, by growing larger as the viewport width increases, or smaller as it decreases.

Fluid Typography has been tested via theme.jsonJSON JSON, or JavaScript Object Notation, is a minimal, readable format for structuring data. It is used primarily to transmit data between a server and web application, as an alternative to XML. since the GutenbergGutenberg The Gutenberg project is the new Editor Interface for WordPress. The editor improves the process and experience of creating new content, making writing rich content much simpler. It uses ‘blocks’ to add richness rather than shortcodes, custom HTML etc. https://wordpress.org/gutenberg/ pluginPlugin 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 releases 13.8 and 13.9.

Fluid font sizes in action. Video taken from Testing and Feedback for the Fluid Typography Feature. Props @greenshady

How to use fluid font size in your theme

Fluid font sizes can be activated for blockBlock 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.-based themes and classic themes via a theme.json file.

The new boolean settings.typography.fluid acts as a toggle that, when set to true, will convert the following values to a clamp() function:

  • font size preset values within settings.typography.fontSizes 
  • custom font sizes, whether defined in theme.json or the editor

The clamp() function contains an upper, lower and preferred font size. The latter will adjust itself according to the width of the viewport.

For presets, individual font sizes can be defined by their minimum and maximum values, which determine the smallest and largest values of a font size. Moreover, individual preset font sizes can opt out by setting settings.typography.fontSizes[].fluid to false.

In the absence of explicit minimum and maximum values, the editor will scale the existing size value up and down to calculate smallest and largest values automatically using computed lower and upper font size values based on the single value.

Consider the following example theme.json:

{
	"version": 2,
	"settings": {
		"typography": {
			"fluid": true,
			"fontSizes": [
				{
					"size": ".9rem",
					"fluid": {
						"min": "0.9rem",
						"max": "1.2rem"
					},
					"slug": "piccolino",
					"name": "Piccolino"
				},
				{
					"size": "2rem",
					"fluid": {
						"min": "1.8rem",
						"max": "3.3rem"
					},
					"slug": "in-mezzo",
					"name": "In Mezzo"
				},
				{
					"size": "2.8rem",
					"fluid": false,
					"slug": "neutrale",
					"name": "Neutrale"
				},
				{
					"size": "4.75rem",
					"slug": "grandone",
					"name": "Grandone"
				}
			]
		}
	},
	"styles": {
		"typography": {
			"fontSize": "16px"
		},
		"elements": {
			"h1": {
				"typography": {
					"fontSize": "4rem"
				}
			}
		},
		"blocks": {
			"core/post-date": {
				"typography": {
					"fontSize": "14px"
				}
			}
		}
	}
}

The above theme.json definition generates the following font size presets that you can use throughout your theme:

--wp--preset--font-size--piccolino: clamp(0.9rem, 0.9rem + ((1vw - 0.48rem) * 0.577), 1.2rem);

--wp--preset--font-size--in-mezzo: clamp(1.8rem, 1.8rem + ((1vw - 0.48rem) * 2.885), 3.3rem);

--wp--preset--font-size--neutrale: 2.8rem;

--wp--preset--font-size--grandone: clamp(3.5625rem, 3.5625rem + ((1vw - 0.48rem) * 6.851), 7.125rem);

When fluid typography is activated, custom font sizes in styles will also be converted to fluid font sizes values, resulting in the following CSSCSS Cascading Style Sheets.:

.wp-block-post-date{font-size: clamp(10.5px, 0.65625rem + ((1vw - 7.68px) * 1.262), 21px); ...}

h1{font-size: clamp(3rem, 3rem + ((1vw - 0.48rem) * 5.769), 6rem); ...}

body{font-size: clamp(12px, 0.75rem + ((1vw - 7.68px) * 1.442), 24px); ... }

Themes that don’t opt into the fluid font size enhancementenhancement Enhancements are simple improvements to WordPress, such as the addition of a hook, a new feature, or an improvement to an existing feature. will see no difference in the way fonts presently work. It is still possible to roll a custom clamp() or other fluid-like formula in the size and fontSize property values.

Applying fluid font sizes in the editor

Nothing changes in the way the typography UIUI User interface works or appears in the editor.

Where fluid font size presets have been defined in theme.json, users can apply these values using the font size picker:

Font size picker UI control with presets
Font size picker UI control with presets

Any custom value set in the editor will also be converted and saved as a clamp() value:

Adding a custom, fluid font size in the post editor.

Current issues and limitations

Fluid font sizes will only work where a font size is defined in px, em or rem units. For the purposes of computing a “preferred font size” the algorithm will convert font sizes in px to rem assuming a base size of `16px`, which is the equivalent of 1em or 1rem.

This is to not only make the job of calculating the clamp formula easier, but to encourage the use of relative sizes: setting the font size to scale proportionally with whichever base size the browser sets will help to maintain accessibilityAccessibility Accessibility (commonly shortened to a11y) refers to the design of products, devices, services, or environments for people with disabilities. The concept of accessible design ensures both “direct access” (i.e. unassisted) and “indirect access” meaning compatibility with a person’s assistive technology (for example, computer screen readers). (https://en.wikipedia.org/wiki/Accessibility)

The first iteration has also made some base assumptions in relation to:

  • Minimum and maximum viewport widths (1600px and 768px).
  • Calculating minimum and maximum font sizes in the absence of specific values.
  • The rate of scale between minimum and maximum font size boundaries.

At the moment, static values exist for the purposes of generating clamp formulae. A follow-up pull request PR is exploring a way to make these parameters configurable.

These issues and more are being tracked via the [Feature] Typography label.

Future enhancements

Future iterations of fluid typography may look at areas such as:

  • Making the clamp formula more configurable.
  • Exploring the potential for filters to allow themes or plugins to customize font size output using available clamp values.
  • Designing fluid typography UI controls.
  • Introducing fluidity to other typography properties such as letter spacing.
  • Allowing configurable upper and lower font size limits, so that font sizes will not ever be too small or too big.

If you have any ideas for subsequent iterations, create an issue or a pull request.

Related reading

Props for review @webcommsat and @bph.

#6-1, #core-editor, #dev-notes, #dev-notes-6-1, #gutenberg

Navigation Block Fallback Behavior in WP 6.1

In WordPress 6.1 the navigation blockBlock 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. will have a new fallback behavior.

What is the fallback behavior?

When a theme uses a navigation block in a template part, it’s to control where the navigation should visually be located, for the theme’s UIUI User interface to be consistent, usable, and visually attractive. However, themes developers don’t know beforehand what menus the site has, how many pages, what they’re called and so on.

The fallback behavior is the small heuristics in the navigation block which tries to determine what the block should display by default, when a user activates a theme.

What is the new fall back behavior?

Starting with WordPress 6.1, theme developers and authors can lean on the following fallback behavior of the block:

If the navigation block has inner blocks, it will honor them and display them. If the navigation block is empty, however, then it will initialize the fallback behavior.

The fallback behavior (in both the editor and the front of the site) is:

  • If there are no block menus or classic menus, the block will display a list of available pages using the Page List block.
  • If there are multiple block menus, the navigation block will display the most recently created block menu.

The key changes can be summarized as follows:

  1. Improved consistency.
  2. Page List as default fallback.
  3. Selecting the most recent block menu.

Consistency: previously the fallback behavior was inconsistent between the fronted of the site and the editor. If a theme used an empty navigation block it would display a list of pages on the front, and an empty block in the editor. Now the behavior is consistent between both; the editor mirrors what visitors see on the frontend.

Defaulting to page list: previously, themes which wanted to default to a page list in the editor usually included a page list inner block within the Navigation block. With this update, this is no longer necessary. The navigation block, if empty, will automatically have consistent front and editor behavior, defaulting to a page list.

Selecting the most recent block menu: This part of the fallback behavior is new. In the event a site has multiple block menus, an empty navigation block will display the most recent one.

Theme developers should keep in mind.

Display only

The fallback behavior only affects what the empty navigation block will display. Unless the user edits the navigation block’s default fallback, adding a link, changing a label, converting a page list block to a list of links or selecting another menu, the markup of the template part is not changed.

Default content is still honored.

There is no change to how navigation blocks with inner blocks from theme markup behave. Themes  still include inner blocks in the markup in the event they want to showcase a specific situation, for instance a small three links menu, pointing to #, with some restriction on length of link labels – this will continue to work, just like before, rendering the uncontrolled inner blocks both on the front and in the editor.

Props: @get_dave for editing and technical review, @bph for review

#6-1, #block-themes, #dev-notes, #dev-notes-6-1, #navigation-block

New is_login() function for determining if a page is the login screen

In #19898 the is_login() function was introduced to allow for determining if a page is the login page.

The is_login() function determines if the current request is for the WordPress login screen returning true when the current screen matches and false for all other cases. This function will provide a quick and searchable way of checking if the login screen is being viewed. Custom login locations are also accounted for in this function. By checking $_SERVER['SCRIPT_NAME'] directly, instead of did_action( 'login_form_login' ) or $pagenow global, the function can work as early as possible, for example in a must-use pluginPlugin 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.

In the below example a check is happening on the init action to display a welcome message on the login page only. This check would account for pages that have custom login screens in non-standard locations.

function add_text_to_login() {
    if ( is_login() ) {
        echo( "<h1>Welcome to the login screen!</h1>" );
    }
}
add_action( 'init', 'add_text_to_login' );

For more information See #19898.

Props to @antpb for reviewing this dev-note.

#6-1, #dev-notes, #dev-notes-6-1

Moving Core block styling to JSON

An effort is currently underway in the GutenbergGutenberg The Gutenberg project is the new Editor Interface for WordPress. The editor improves the process and experience of creating new content, making writing rich content much simpler. It uses ‘blocks’ to add richness rather than shortcodes, custom HTML etc. https://wordpress.org/gutenberg/ pluginPlugin 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, to streamline and standardize the way that blocks are styled by moving key blockBlock 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. styling into Theme JSONJSON JSON, or JavaScript Object Notation, is a minimal, readable format for structuring data. It is used primarily to transmit data between a server and web application, as an alternative to XML..  This post lays out the reasoning behind this change and the impact it will have for both themes and block authors going forward.

What is theme.json?

Theme.json is a file which provides a single place to configure the behavior of  themes.

It plays an important role in the Full Site Editing project, by storing information about a site’s appearance and providing this in a machine readable format to be consumed by the Editor interface.

One of the key elements of this is the Global Styles interface within the Site Editor which allows users with a UIUI User interface to allow them to modify the default appearance settings provided by their chosen Theme.

Why use JSON to represent a theme’s styles?

Expressing a theme’s styles in JSON gives us several benefits:

  1. It enables users to modify the visual appearance of their site via the UI provided by Global Styles, without needing to write any CSSCSS Cascading Style Sheets..
  2. We have more control and consistency in how the theme CSS is output, so that we can ensure that user’s settings take priority over theme’s settings, and theme’s settings take priority over coreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress.’s settings.

What is changing?

To expand the number of customisation options available to users through the Global Styles UI, we need to configure the default visual appearance of blocks using the same tools that will be used to customize these blocks.  This will make it trivial for themes to overwrite the default styles of a block.

In practical terms this means we need to move the rules that define default block appearance from CSS files, to machine readable JSON files, such as `theme.json` & `block.json`.

How can blocks define styles in JSON?

To make the process of moving core block styles into JSON, some new affordances have been created. 

One of these is that the JSON rules for a block can be saved in the block.json file under a new `__experimentalStyles` key.

For example margins on the image block were expressed in CSS like this:

.wp-block-image {
	margin: 0 0 1em 0;
}

Since this change we can now define margins for image blocks in the block.json file like this:

{
	“__experimentalStyle”: {
		“spacing”: {
			“margin”: “0 0 1em 0”;
		}
	}
}

The CSS that is generated from this change is the same as the original CSS file.

For more details on this approach please see “merging block CSS with theme.json styles”. You can also see an example of how this would be implemented in “Block CSS: Move CSS from the stylesheet to the block definition”.

What are the benefits?

Styles are now customizable

The driving force of this change is to enable users to modify the visual appearance of their site via the UI provided by Global Styles, without needing to write any CSS

However this change also has some very important, and useful, side effects.

CSS specificity and performance

For a long time blocks and themes have been struggling with CSS specificity – blocks want to ensure that they provide enough rules that they look good, whilst themes want to override these rules so that different blocks have a consistent appearance (for example ensuring all your buttons look the same). 

This has meant that blocks have to be very careful about the specificity of the selectors in the CSS they provide, to enable themes to override them. 

By expressing visual styles in JSON, and compiling them as part of the main CSS output of global styles, the order and importance of each rule is clear and computable when the theme.json files are processed.

Global Styles processes the different levels of JSON settings, by merging each of these JSON objects together. Once all of the settings are combined, the Global Styles CSS is generated using the final merged result. This means that the resulting CSS only contains the rules the theme needs.

For those not familiar with how rules in Theme JSON files are turned into valid CSS rules here’s a quick refresher. There are x3 “levels” of JSON file:

  • WordPress Core Theme JSON – this holds the base level styles for WordPress.
  • Theme JSON – this is the `theme.json` file from the currently active Theme which provides theme-specific styles.
  • Custom User Styles – these are rules provided by the Global Styles user interface and have the highest level of importance.

When these different JSON representations of styles are merged together, we only preserve the rules for the uppermost setting for each rule before they are converted to CSS rules. 

By moving block CSS rules to JSON we effectively insert a new level into this hierarchy with WordPress Core `theme.json` being overridden by block styles in `block.json` which is overridden by the `theme.json` provided by the theme which is in turn overridden by custom user styles, created in the Global Styles UI.

For clarity the new rules hierarchy is:

  • WordPress Core Theme JSON
  • Block styles in Block JSON
  • Theme styles from Theme JSON
  • Custom User Styles from Global Styles UI.

This also means that the total CSS output of the system will be smaller, which is a performance benefit. 

Exposing default styles

Another benefit of this change is that the default styles for each block are now exposed in the Global Styles UI, before the user makes any changes, so the starting point is obvious and clear. Now that blocks can define most of their styles in JSON, these default styles can be more easily seen and  configured using the Global Styles interface.

Not only are the styles of blocks themselves configurable but the lower level elements used within blocks can also be exposed to the Global Styles UI.

What are elements?

Elements are low level components for themes and blocks, which don’t need the complexity of blocks.

Block composition has not reached a level of infinite composability, hence it is not always possible or good to use, say, the heading block instead of a HTMLHTML HyperText Markup Language. The semantic scripting language primarily used for outputting content in web browsers. heading element, or a button block instead of a HTML button element.

Some good examples of these are headings, links and buttons. 

Links are part of many blocks but do not have a block of their own. Headings and buttons are expressed as blocks but many times the block composition limits us, so we’re better off using an HTML heading or button element.

Also, elements are simpler than blocks; they can be used to express semantic features of blocks and enable users to share styles across multiple blocks. For example style rules for the button element will be used in the search block, the file block and the button block.

The number of elements is currently being expanded. Some new elements we expect to add are a caption element and form elements. It is likely some of them will be absorbed into blocks as the block composition APIAPI 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. gets better, so the implementation of element support is kept at a minimal state.

Putting it all together – exposing default element styles in the UI

If we put these two new concepts (setting default styles in JSON and element styles) together, we can see how the default styles for button elements are now visible in the Global Styles UI:

This helps users to understand the global styles interface more easily as it shows straight away the relationship between these settings and the visual appearance of the block.

Should I set style rules for blocks or for elements?

Theme authors have the option to set styles in `theme.json` for:

  • blocks themselves. 
  • elements within blocks
  • globally for elements shared by blocks.

 It’s important to understand the precedence of each of these options, so you know which one to choose.

  1. Global element styles apply to all instances of an element. These rules will apply across all blocks, to ensure a consistent appearance between all blocks. In some cases this will depend on blocks implementing the elements API to take effect. For example, this would be useful if you wanted to create a style rule that applied to all button elements on your site.
  2. Block styles apply to all instances of that specific block. This is useful if you want to target particular properties of the block itself. For example this could be used to modify the color of all the text within the search block.
  3. Element styles within blocks are the most specific use case. These rules will only apply to elements within a specific block. If users modify global element rules, these the specific customizations for elements within blocks will still take precedence due to their higher specificity, so the user’s global changes won’t apply unless they modify the element settings for that particular block. For this reason this use case should be uncommon. For example, this is useful if you wanted the buttons in your search form to be a different color to the other buttons on your site.

What does this mean for block authors?

Block authors can already take advantage of some of these changes.

Blocks can already start to use the elements API for composing their markup. Right now this only works for the button and captions elements, but as the number of elements is expanded, blocks will be able to compose their markup using these common elements, which will in turn enable them to be better supported by Global Styles.

Blocks can also start to define their style using the `block.json` file, which allows themes to override block styles using `theme.json`, rather than relying on CSS. Styling a block’s supported features within their JSON configuration enables users to modify them via the Global Styles UI.

What does this mean for themers?

This approach gives more tools to themers, to make it easier for themes to have a more consistent style across all blocks without the need for complex CSS. By using the elements section of the theme.json, themes can create style rules that will apply across all blocks that take advantage of these elements, which makes these rules simpler and easier to maintain.

Will this replace the theme’s CSS?

While simple themes may one day be able to replace all their CSS with theme.json settings, it is expected that most themes will still need to provide their own CSS for the more advanced aspects of their design – for example animations.

Is supports > __experimentalStyles the right place for this?

These styles were initially added to supports > __experimentalStyles so that we could begin this work, but ideally these settings would belong in the style key of block.json. There is an open PR to make this possible.

#dev-notes

Block Locking Settings in WordPress 6.0

WordPress 6.0 makes it easier to lock blocks using the new controls modal. The release also includes two new settings to choose who can access this option and when.

BlockBlock 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. Editor

The new canLockBlocks setting can disable the feature globally or conditionally. Example:

add_filter(
	'block_editor_settings_all',
	function( $settings, $context ) {
		// Allow for the Editor role and above - https://wordpress.org/support/article/roles-and-capabilities/.
		$settings['canLockBlocks'] = current_user_can( 'delete_others_posts' );

		// Only enable for specific user(s).
		$user = wp_get_current_user();
		if ( in_array( $user->user_email, [ 'user@example.com' ], true ) ) {
			$settings['canLockBlocks'] = false;
		}

		// Disable for posts/pages.
		if ( $context->post && $context->post->post_type === 'page' ) {
			$settings['canLockBlocks'] = false;
		}

		return $settings;
	},
	10,
	2
);

Blocks

The lock property allows hide controls on a block type level. Example:

{
	"apiVersion": 2,
	"supports": {
		"lock": false
	}
}

For more info see #39183.

An earlier post on this blogblog (versus network, site) covers, the Curated experiences with locking APIs & theme.json

#6-0, #dev-notes, #dev-notes-6-0