Nav Menu Improvements in the Customizer in 4.9

In our usability tests with prior releases, we identified two common problems users encountered when trying to create a menu.

  1. Clicking the Add a Menu button in an attempt to add a page to their new menu.
  2. Forgetting to assign the menu to a location.

In WordPress 4.9, we’ve updated the Customizer’s menu creation flow to address these issues.

An Updated Menus Panel

The Menus panel layout and copy have been updated for clarity. The panel now shows menus first and locations second. This puts menus front and center and allows the panel to adjust more easily to specific scenarios. For example, when there are no menus, the panel asks users to create a menu and explains the steps to be taken.

Before After

Menu Creation

When the user clicks Create New Menu, the Customizer opens a dedicated menu creation section. Using a dedicated section allows us to guide the user through each step of menu creation. We start by inviting the user to provide a clear name for the menu and to select its new location. Once the menu is created, we guide them to add menu items and highlight the Add Items button if the user doesn’t find it after a short time.

Create a Menu for a Location

The locations section now allows the user to create a menu for a location that has not been assigned a menu. When the user clicks a location’s Create New Menu link, the Customizer opens the Menu Creation section with the location preselected.

Deprecated UI Classes

With the addition of a dedicated menu creation section, a number of classes are no longer used and are being deprecated.

The following PHP classes have been deprecated along with their files:

  • WP_Customize_New_Menu_Control in
    wp-includes/customize/class-wp-customize-new-menu-control.php
  • WP_Customize_New_Menu_Section in
    wp-includes/customize/class-wp-customize-new-menu-section.php

The following JS class has been deprecated (but not its containing file):

  • api.Menus.NewMenuControl in
    wp-admin/js/customize-nav-menus.js

Related Tickets

  • #40104 Customizer: Improve menu creation flow
  • #36279 Add an “add new menu” button to the menu locations section in the customizer
  • #42114 Customize Menus: UX Improvements
  • #42116 Customize Menus: Add “It doesn’t look like your site has any menus yet” view
  • #42357 NewMenuControl class has been removed from trunk

#4-9, #customizer, #dev-notes

WordPress 4.9 Field Guide

WordPress 4.9 is officially the best release ever (that rhymes with Shore Joint Twine)!  Users have safer and more flexible ways to edit code, new and improved widgets, and improvements to customizing their site while developers will be able to take advantage of 188 enhancements and features added.  Let’s look at the many improvements coming in 4.9…

Widgets: now new and improved

Galleries aren’t just for posts anymore, now they can get all up in your sidebars. That’s a good thing, if you’re into that sort of thing. On top of that your text widget now supports shortcodes, images, galleries, videos, audio, and other media. Oh, and the text widget now supports embeds, so go ahead and drop a YouTube clip in that widget.

Introducing the Gallery widget

Widget Improvements in WordPress 4.9

WordPress and CodeMirror sitting in a tree…

Something something I-D-E. Ever wondered what an IDE would look like inside WordPress? Do you use Notepad as your IDE? No? Great, then you’ll love the syntax highlighting, linting, and auto-completion functionality within the Customizer’s Additional CSS feature, the Custom HTML widget, and the Plugin and Theme file editors!

Code Editing Improvements in WordPress 4.9

🔎, 🏗️, and 👓 Themes in the Customizer

That’s emoji for browsing, installing, and previewing, but you knew that already. The Customizer now includes a new experience theme browsing and live-previewing themes, as well as—for the first time—installing new themes from WordPress.org in the process. Don’t believe us? Then give it a try with your favorite theme!

A New Themes Experience in the Customizer

Changesets

Quick, what’s your favorite sequel? If you said Caddyshack 2, then we need to have a little chat. If you said Changesets 4.9, then you’re correct! Get ready to learn all about Drafting, Scheduling, Autoloading, and Linear/Branching Modes, Autosaving Auto-Drafts and Autosave Revisions, Post Locking, and Customization Drafts. Yes, all of that is in 4.9. You’re welcome.

New Features and Enhancements with Customizer Changesets in 4.9

Nav menu creation flow

Ever had problems working in the Customizer and adding a page to a menu or forgetting to assign a menu to a location when trying to create a menu? The Customizer’s menu creation flow has been updated to address these issues.

Nav Menu Improvements in the Customizer in 4.9

The A(PI)-Team

If you have a problem, if no one else can help, and if you can find them….maybe you can hire The A(PI)-Team. The Customizer JS API improvements in 4.9 fix many longstanding annoyances and shortcomings with the JS API. Additionally, a REST API update now effectively requires named URL parameters and thus no longer allows regular (numeric) matches.

Improvements to the Customize JS API in 4.9

Improvements in REST API request parameter regular expressions

Multisweet multisite multimprovements

Run a network of sites? Then pour yourself some coffee and dig into all the multigoodies in 4.9. New functions and filter, replaced functions, capability and role updates, and some security improvements all come along for the ride on the multisite train.

Multisite Focused Changes in 4.9

Users and security updates

Were you hoping for new capabilities for activating and deactivating plugins plus installing and updating language files, capability security hardening, changes to how multisite handles switching roles and capabilities, and security improvements to how email addresses get updated in 4.9? If so, you’re going to be happy. If not, you should still be happy.

Improvements for roles and capabilities in 4.9

Account Security Improvements in WordPress 4.9

Don’t Press That

Press This is no longer in core, but can be found via a “canonical” plugin. Cry if you want to, but the functionality still exists so cheer up!

Press This in 4.9

 

ME.js updates.js

If.js I.js could.js think.js of.js something.js witty.js related.js to.js the.js ME.js.js updates.js, then.js I.js would.js have.js wrote.js that.js here.js. Instead.js… .js.js all.js the.js things.js.

MediaElement upgrades in WordPress 4.9

Updates for screen readers

As usual, we saved the best for last! Modernization and standardization comes to the screen-reader-text CSS class.

Changes to the screen-reader-text CSS class in WordPress 4.9

But Wait, There is More!

Roughly 400 bugs, 181 enhancements, 7 feature requests, and 42 blessed tasks have been marked as closed in WordPress 4.9.

Please, test your code. That bears repeating: Please, test your code. Fixing issues now, before 4.9 is released, helps you and helps millions of WordPress sites. Please. Test. Your. Code.

#4-9, #dev-notes, #field-guide

New Features and Enhancements with Customizer Changesets in 4.9

In WordPress 4.7 the concept of changesets was introduced in the Customizer (#30937). To understand the new Customizer improvements in 4.9, you must first go back and review what was proposed and implemented a year ago:

Customize Changesets Technical Design Decisions

Changesets are a way to persistently store changes made via the Customizer framework. Changesets contain the pending changes for any number of settings, and a setting can model any object in WordPress—whether options, theme mods, nav menu items, widgets, or even posts/pages and their postmeta. Changesets are identified by UUID (which is the post_name for the customize_changeset post type that stores the data as JSON in post_content). When a request is made to WordPress with the customize_changeset_uuid request param—whether to the frontend or to the REST API—the Customizer framework will bootstrap and all of the values from the changeset will be read and applied to the response via WordPress filters added by the settings’ respective WP_Customize_Setting::preview() methods.

Only an authorized user can write changes into a changeset for a given setting (according to its respective capability). But once it has been written then anyone can preview the site with the changes in the changeset applied: all that is needed is the UUID. Since previewing a changeset is now a readonly operation (whereas before 4.7 it was always a POST request), a changeset can be previewed on a site by authenticated and unauthenticated users alike. With the changeset UUID supplied when opening the Customizer, a user can keep iterating on a set of changes over several days or longer and only publish them once stakeholders are satisfied. Now, freelancers and agencies will be better able to communicate and collaborate on site changes with clients.

Once a customize_changeset post transitions to the publish status then all of the values in the changeset will be passed into their respective WP_Customize_Setting::update() methods to publish (“go live”) on the site: in version control terminology, the staged values from the changeset get committed and pushed. All of the changes go live together in a batch save operation (originally changesets were termed “transactions”).

As noted in the 4.7 merge proposal:

For the initial core merge, no UI changes are being proposed. The feature will only be exposed as the new query parameter on the URL. Adding a UI to this feature will happen in a future release.

The future [release] is now. Where the infrastructure of changesets was merged from the Customize Changesets feature plugin in 4.7, the key UI features from the plugin are now being merged in 4.9 after a significant number of design iterations.

This dev note contains sections on the following:

Continue reading

#4-9, #customize, #dev-notes

Press This in 4.9

In WordPress 4.9, Press This has found a new home as a “canonical” plugin.

Proposed in #41689 and committed in r41584, Press This and the supporting functions are no longer in Core at all. This is notably different than the Link Manager deprecation, which left all of the code in Core but deactivated behind a filter. If you are extending the WP_Press_This class, you will need to update your plugin or theme as it is no longer present in Core.

When someone visits wp-admin/press-this.php, they are given a prompt to install the new plugin or to notify their administrator to install it:

If installing it through the prompt above, the activation flow will return them to Press This:

If you are extending Press This or are depending on functionality from it, you can see how to check for plugin availability via 4.9’s wp-admin/press-this.php and please comment on #37938 discussing if some of the parsing functionality of Press This would be beneficial ported back into Core.

In the new plugin, older bookmarklets will no longer function and this feature is discontinued. Usage of bookmarklets across the web has decreased significantly and bad actors attempting to trick users to preform unsavory actions increased over the years. Coupled with advancing toward a new editing in experience in Core, we decided it was a suitable time to make these changes in one swift move.

Continued development of Press This will happen at https://github.com/WordPress/press-this/ and I hope those who like the streamline editing experience will continue to contribute. Short-term goals include switching to the REST API instead of admin-ajax and tweaking the current experience.

#4-9, #dev-notes

Improvements to the Customize JS API in 4.9

There are many user-facing Customizer improvements in 4.9, including: drafting/scheduling of changesets, autosave revisions, changeset post locking, frontend public previews, a new experience for browsing and installing themes, updated nav menu creation UX, and the code editing improvements for the Custom HTML widget and Additional CSS. But in addition to all of these, there are also many improvements for developers which will make extending the Customizer much more pleasant.

Something important to remember about the Customizer is that it is a single page application that is powered by JavaScript. Many developers may only interact with the PHP API for registering controls, settings, sections, panels, and partials. But controls, sections, and panels do not need to be registered in PHP at all. The PHP API for registration is essentially a wrapper for the underlying JS API. When you load the Customizer all of the params for the PHP-registered constructs are exported to the client for the JavaScript API to instantiate and initially add to the UI, but this JS API can dynamically instantiate additional constructs at any time thereafter in a Customizer session. This is how new widgets, nav menus, and nav menu items are added without requiring the entire Customizer to reload. You can also avoid statically registering settings and partials in PHP by instead adding filters to dynamically recognize settings and partials, allowing them to be registered on demand. All of this allows the Customizer application to scale out to be able to customize and preview an unlimited number of things on a site (e.g. any post or page with their postmeta in the Customize Posts feature plugin). The point here is that in order for the Customizer to scale, the JavaScript API must be used directly. So this is why the Customizer JS API improvements in 4.9 are important as they fix many longstanding annoyances and shortcomings with the JS API.

This dev note contains the following sections:

Continue reading

#4-9, #customize, #dev-notes

MediaElement upgrades in WordPress 4.9

MediaElement has been upgraded to 4.2.6 (see #39686), which includes many bug fixes as well as:

  • Removal of all dependencies to jQuery in code to make it more portable
  • Updated UI, using flexbox
  • Improved accessibility for player controls
  • Dropped support for older browsers (supports IE11+, Chrome, FF, Safari, Android 4+ and iOS 8+), keep in mind that ME.js applies to the front end and not just WP Admin
  • Upgraded YouTube and Vimeo renderers to use new APIs (for Vimeo, it uses now https://player.vimeo.com/api/player.js, since Froogaloop is deprecated)
  • Added support for iOS 10 and Mac OS on websites using HTTPS

With this upgrade, a couple of things must be considered:

  1. In order to create themes compatible with it, it is required to add the classPrefix: mejs- in the player configuration, since latest version of MEJS switched to BEM naming convention, so make sure it is set correctly.
  2. player.options.mode has been removed completely.
  3. Although jQuery was removed from the core package, a MediaElement migration file has been included to provide full backward compatibility between themes and development of new features.

A full list of changes in MediaElement.js is available in the project’s GitHub repository.

Props to @rafa8626 for helping write this Dev Note.

#4-9, #dev-notes, #mediaelement

Improvements in REST API request parameter regular expressions

With WordPress 4.9, a bug has been fixed which would cause unexpected numeric results to be included in the parsed URL parameters for a REST API request. Prior to this change, calling WP_REST_Request::get_params() for a request like /wp/v2/users/(?P<id>[\d]+) with an ID of 10 would return array( 'id' => 10, 1 => '10' ), where the latter numeric key is unnecessary and a result of PCRE matching against a named subpattern (see preg_match() documentation). The fix ensures that the above request now only returns array( 'id' => 10 ) instead. This helps for example to verify that a request does not include more than a few specific parameters.

The WP REST API docs have always been using named URL parameters, using regular (numeric) matches was never recommended. With this bug fix in place, using named parameters is now effectively required, for example /my-namespace/my-endpoint/(?P<numeric_param>[\d]+) must be used instead of /my-namespace/my-endpoint/(\d+). For background discussion on these changes, see #40704.

#4-9, #dev-notes, #rest-api

Widget Improvements in WordPress 4.9

On the heels of adding TinyMCE rich editing to the Text widget and the media widgets in 4.8, there are another round of improvements coming to the Text widget and Video widget in 4.9, among other improvements to widgets.

Shortcodes in Text Widget

One very longstanding request—for over 8 years—has been to support shortcodes in the Text widget (#10457). This is finally implemented in WordPress 4.9. It is no longer required to have plugins and themes do add_filter( 'widget_text', 'do_shortcode' ). Core now will do_shortcode() at the widget_text_content filter (added in 4.8) in the same way it is applied in the_content at priority 11, after wpautop() and shortcode_unautop(). If a plugin has added do_shortcode() to widget_text then this filter will be suspended while the widget runs to prevent shortcodes from being applied twice. If a Text widget is in legacy mode then it will manually do_shortcode() as well.

One reason for the long delay with adding shortcode support in Text widgets was due to many shortcodes looking for a global $post when they run. Since the global $post varies depending on whatever the main query is, the shortcodes in a Text widget could render wildly different on different templates of a site. The solution worked out was to temporarily nullify the global $post before doing the shortcodes so that they will consistently have the same global state, with this global $post then restored after the shortcodes are done. So if you have shortcodes that depend on a global $post—or call get_post()—then you should make sure that they short-circuit when $post is null in order for them to behave properly if used in the Text widget.

As of [42185] this nullification of $post is only done for archive (non-singular) queries; for singular queries, the $post will instead be set to be the current main queried post via get_queried_object(). This ensures that the global $post is consistent and explicit. This setting of the $post global while applying filters (and shortcodes) is also now implemented for the Custom HTML widget. Additionally, to ensure that gallery shortcodes that lack ids do not end up listing out every attachment in the media library, a shortcode_atts_gallery filter has been added which makes sure the shortcode’s id attribute is set to -1 when the widget is rendered on archive templates. This allows you to embed the gallery for any currently queried post in the sidebar. You should make sure such a Text widget is not displayed on an archive template by either adding it exclusively to a sidebar that appears on singular templates, or by using a feature like Jetpack’s Widget Visibility to hide the widget on non-singular templates.

Media in Text Widget

One reason why shortcode support in the Text widget was needed in this release is because 4.9 also allows media to be embedded in the Text widget (#40854). There is now the same “Add Media” button in the rich Text widget as on the post editor, allowing you to add images, galleries, videos, audio, and other media. To support these, core also needed to support shortcodes like captionaudiovideo, and gallery. Note there are also dedicated widgets (Image, Audio, Video, and Gallery) for these media types as well.

Having separate media-specific widgets helps with discovery and allows us to provide streamlined interfaces for each media type. For example, the Image widget now has a field specifically for supplying the link URL (see #41274), and the Video widget now provides more guidance to users when supplying external URLs (#42039). The media-specific widgets are closely aligned with blocks in Gutenberg; the existence of media inside the Text widget will align with eventual nested blocks in Gutenberg, and would be treated as Classic Text blocks in any future migration from widgets to blocks.

Embeds in Text Widget and Video Widget

One shortcode not mentioned above is embed. This one was more difficult to support because oEmbeds have not been supported anywhere other than post content. This was because there were dependencies on having a post as context for the sake of caching, as the responses to oEmbed requests get stored in postmeta. However, as of #34115 if there is no post as context the oEmbeds will now get cached in an oembed_cache custom post type instead. Since a Text widget will explicitly nullify the global $post while shortcodes are processed, this means oEmbeds will get cached in this custom post type. Similarly to how do_shortcode() now applies in the widget_text_content filter like it applies on the_content, so too now WP_Embed::autoembed() and WP_Embed::run_shortcode() both also now run on widget_text_content.

In WordPress 4.8 the Video widget was introduced with support for displaying an uploaded video file, a YouTube video, or a video from Vimeo. Each of these were displayed using MediaElement.js. Just as oEmbeds are now able to be displayed in the Text widget, so too now the Video widget has been expanded to support any oEmbed provider for video. See #42039.

Theme Styling Changes

As with the previously-introduced media widgets (#32417) and the new Gallery widget (#41914), some themes will need to be updated to ensure the proper styling is applied to media and embeds that appear in the widget area context, since previously they would only appear in post content. Please follow #42203 and #41969 for style changes that are made to the core bundled themes, as you may need to make similar changes to your themes.

Improved Theme Switching

A longstanding difficulty with widgets has been where they end up when switching from one theme to another. With #39693 this experience is improved in 4.9 by having logic that is able to better map widgets between the themes’ widget areas. As noted by @obenland in [41555], there are three levels of mapping:

  1. If both themes have only one sidebar, they gets mapped.
  2. If both themes have sidebars with the same slug (e.g. sidebar-1), they get mapped.
  3. Sidebars that (even partially) match slugs from a similar kind of sidebar will get mapped. For example, if one theme as a widget area called “Primary” and another theme has “Main” then the widgets will be mapped between these widget areas. Similarly, widgets would get mapped from “Bottom” to “Footer”.

The names for the widget areas used for the mapping groups were obtained by gathering statistics from all the themes on WordPress.org.

Widget Saved State on Admin Screen

With #23120 there is now an indication for whether or not changes to a given widget has been saved on the widgets admin screen. (Widgets in the Customizer already had a saved state by virtue of being registered as regular settings.) When first opening a widget, the button will say “Saved” and appear disabled. Once a change is made to the widget (e.g. a change event triggered), then the button will become enabled and say “Save”. If you try leaving the admin screen at this point, an “Are you sure?” message will appear alerting that if you leave your changes will be lost. If you cancel, then the first widget with unsaved changes will be scrolled into view, expanded, and focused. Upon hitting “Save” the spinner will appear and then upon a successful save it will switch to “Saved” and become disabled. The “Close” link has been changed to “Done” and it only appears when the changes have been saved. Note that the HTML5 checkValidity method will now be called on the widget form prior to attempting to submit, and submitting will be blocked if it returns false. If you have JavaScript-based fields in the widget, make sure that you trigger change events whenever changes are written into any hidden inputs; this was already a requirement for widgets in the Customizer.

Related Tickets

  • #10457: Parse shortcodes in text widgets by default
  • #23120: There should be indication that widget settings have been saved
  • #34115: oEmbed not working on author page without posts
  • #38017: Add widget instance to remaining widget argument filters
  • #39693: Fix missing assignment of widgets on theme switch
  • #40442: Widgets: Rename “Custom Menu” widget to “Menu”
  • #40854: Allow media to be embedded in Text widget
  • #41274: Improve discoverability of link URL in Image widget.
  • #41610: Widgets: Change “close” to “done?”
  • #41914: Widgets: Add gallery widget
  • #41969: Ensure Gallery widget is styled properly across widget areas in bundled themes
  • #42039: Widgets: Enable oEmbed support for Video widget
  • #42203: Ensure media & embeds in Text widget are styled properly across widget areas in bundled themes

See full list of tickets in the Widgets component with the 4.9 milestone.

#4-9, #dev-notes, #feature-oembed, #media, #media-widgets, #widgets

A New Themes Experience in the Customizer

WordPress 4.9 introduces a new experience for discovering, installing, and previewing themes in the customizer. Building on efforts during WordPress 4.7 development, this project prioritizes user flow, extensibility, and performance improvements.

A theme is the most fundamental aspect of customizing a site. This project seeks to unify the theme-browsing and theme-customization experiences by introducing a comprehensive theme browser and installer directly in the customizer.

The new flow seamlessly integrates theme management into the customization experience by bringing a new theme browsing framework into the customization interface along with the ability to install and live-preview a theme in a single click.

Screencast demonstrating the new themes experience in the customizer. Open the theme browser, search and browse installed and WordPress.org themes, and then install and preview in a single click.

The new theme browser is designed for extensibility. Third-party theme directories are encouraged to integrate with the core experience via plugins. Because the new browser is built on the core customize API, extending it is similar to extending any other part of the customization experience. As with every aspect of the customizer, this project approaches extensibiity modularly and in terms of both user and developer experience. The end of this post includes a technical overview of the new API.

Since WordPress 4.2, the customizer has loaded information about every installed theme every time the customizer loaded. In 4.9, theme data will only be loaded when a user visits the themes panel. The resulting performance improvement on every customizer load may be substantial on sites with a large number of installed themes, particularly on multisite networks.

For more information on the history and goals of this project, check out the original feature proposal from last year:

Feature Proposal: A New Experience for Discovering, Installing, and Previewing Themes in the Customizer

Theme Browsing Improvements

The changes since the previous merge proposal center around the experience of browsing themes. The customize sidebar now serves as the global index of theme sources (installed, WordPress.org, upload, and any additional sources added by plugins). In the customize preview area, a filter bar controls navigation within each of those sections.

Installed themes feature an instant search filter and a count of the results. WordPress.org themes also feature a search bar, in addition to the feature filter found in wp-admin and on WordPress.org. Rather than mimicking the existing WordPress.org and wp-admin theme browsers, the customizer features a simplified filter-oriented approach. The popular, favorites, and (randomized) featured sections are excluded in favor of a single, filter-driven section that defaults to showing the latest themes.

Over time, the customization team hopes to work with the theme review and meta teams to broadly evaluate the process of finding a theme. This future project will be driven by research into other product discovery experiences, as well as the experiences that third-party plugins build within the customizer for browsing themes from other sources. Ultimately, the goal is to bring an improved and unified theme browsing experience to WordPress.org, wp-admin, and the customizer, complete with new tags and other taxonomies. For now, the WordPress.org theme browser within the customizer is a starting point for a user-driven theme discovery experience.

Customize Themes API

The remainder of this post is dedicated to the technical implementation of the new themes experience, with three objectives: providing an example implementation of the customize API, documenting the feature to assist in future iterations, and introducing the API for extending the experience.

Customize Object Structure

The context for the themes experience is contained with a custom customize panel object, WP_Customize_Themes_Panel in PHP and wp.customize.ThemesPanel in JS. This panel is responsible for:

  • The overall theme browser UI layout
  • Installing themes (via wp.updates)
  • Loading theme previews
  • Updating installed themes from WordPress.org (via wp.updates)
  • Deleting installed themes (via wp.updates)

The custom themes panel object joins WP_Customize_Widgets_Panel and WP_Customize_Menus_Panel as core examples of the intended use for panels – as contexts for distinct features, rather than as generic containers for sections. It should generally not be necessary to modify the core panel object when extending the themes experience.

Theme browsing is done within custom customize section objects, which are instances of WP_Customize_Themes_Section in PHP and wp.customize.ThemesSection in JS. In 4.9, core provides two sections for browsing themes: Installed Themes and WordPress.org Themes. An additional section to Upload Themes will be added in a future release. Themes Sections handle the following:

  • Searching and filtering
  • Loading themes (from wp_prepare_themes_for_js() and WordPress.org), as theme control objects
  • Rendering screenshots for theme controls as they become visible (rather than loading all screenshots as soon as the theme data is loaded, for improved performance)
  • Opening and navigating the theme details modal

The themes section was initially introduced in WordPress 4.2. In 4.9, it has been completely reworked, most notably with the addition of built-in support for loading theme data from WordPress.org.

Each theme within the browser is represented with a customize control object, instances of WP_Customize_Theme_Control in PHP and wp.customize.ThemeControl in JS. Theme controls:

  • Display information about a single theme
  • Provide contextual buttons to install, preview, or install and preview themes depending on whether the theme is already installed
  • Contain an internal filter (and sorting) method in JS, which can be used for searching and filtering all theme controls within a section

While the theme control object was also initially introduced in WordPress 4.2, its 4.9 update completely refactors the control to use JS templates for rendering. This facilitates the updated themes section’s ability to quickly load data for large numbers of themes within a fully JS-driven experience. Hundreds of individual theme controls are dynamically created and deleted as users navigate the theme browsing interface, leveraging the customize API’s ability to scale by building on functionality initially introduced in WordPress 4.3 for the menus interface.

Extending the Core Experience

The modular structure of the customize API allows any aspect of the new themes experience to be modified or extended. In most cases, extensions will modify the themes section object, or create custom themes section instances or subclasses.

There are two types of WP_Customize_Themes_Sections: those that load all themes at once and search/filter theme locally (like the core installed section), and those that search and filter themes remotely, replacing every theme control object each time a search or filter changes. This distinction is managed with the filter_type parameter. When this set to local, all themes are assumed to be loaded from Ajax when the section is first loaded, and subsequent searching/filtering is applied to the loaded collection of themes within the section. This is how the core “Installed” section behaves – third-party sources with limited numbers of themes may consider leveraging this implementation. When filter_type is set to remote, searching and filtering always triggers a new remote query via Ajax. The core “WordPress.org” section uses this approach, as it has over 5000 themes to search.

With this parameter, it is theoretically possible to create a plugin that adds an instance of WP_Customize_Themes_Section that browses themes from a third-party source (using a custom action parameter). The customize_load_themes filter facilitates loading themes from third-party sources (or modifying the results of the core sections) within an Ajax call triggered by a themes section. In practice, it may be desirable to create a custom themes section object (subclassing WP_Customize_Themes_Section) to further customize the experience of browsing third-party themes within the customizer.

Additional Information & Next Steps

Most of the work for 4.9 was completed in #37661, with several follow up tickets to polish the feature. In addition to iterating on the WordPress.org theme browsing experience, there are a few improvements that are already planned for future releases:

  • #40278 – Introduce theme uploading in the customizer
  • #42046 – Clarify active and previewed themes
  • #42140 – Improve plurality of the themes count string

Here is the complete design flow for the new theme browser within the customizer, courtesy of @folletto:

Mockups of the user flow through the customize themes experience in 4.9, with additional elements for future releases

Please test the new themes experience in the 4.9 betas and share any feedback or bugs that you find on trac and in the comments.

#4-9, #customize, #dev-notes, #themes

Changes to the screen-reader-text CSS class in WordPress 4.9

The screen-reader-text CSS class is a small bit of CSS used in WordPress to visually hide text and make it still available to assistive technologies, screen readers, and any other software reading a page.

For a number of years, this CSS class has used an incorrect syntax for the clip property to deal with old Internet Explorer versions. WordPress 4.8 officially dropped support for Internet Explorer versions 8, 9, and 10. This is a good opportunity to update screen-reader-text to a modern, correct syntax and standardize it across the codebase. Furthermore, the clip property is deprecated: some browsers may still support it, but it is in the process of being dropped and it may cease to work at any time.

Worth noting this change applies only to the CSS class used in the WordPress admin pages.

Here’s how the old CSS class looks like:

.screen-reader-text {
	position: absolute;
	margin: -1px;
	padding: 0;
	height: 1px;
	width: 1px;
	overflow: hidden;
	clip: rect(0 0 0 0);
	border: 0;
	word-wrap: normal !important;
}

And here’s how the new CSS class looks like in WordPress 4.9:

.screen-reader-text {
	border: 0;
	clip: rect(1px, 1px, 1px, 1px);
	-webkit-clip-path: inset(50%);
	clip-path: inset(50%);
	height: 1px;
	margin: -1px;
	overflow: hidden;
	padding: 0;
	position: absolute;
	width: 1px;
	word-wrap: normal !important;
}

The only changes are the clip property value new syntax and the introduction of clip-path.

In the vast majority of cases this small change shouldn’t require any update to plugins and themes. There’s only one case to be aware of and that’s when the screen-reader-text CSS class is used to dynamically reveal some text. In a very few cases, WordPress itself reveals some visually hidden text. For example, when there’s no JavaScript support or on small screens, screen-reader-text gets reset to make the visually hidden text visible again:

.no-js .some-element .screen-reader-text {
	position: static;
	-webkit-clip-path: none;
	clip-path: none;
	width: auto;
	height: auto;
	margin: 0;
}

If you’re using a similar CSS technique in your plugin or theme admin pages, don’t forget to reset the new clip-path property too.

For more details, see the related changeset and Trac ticket.

#4-9, #dev-notes