Load Gutenberg Component Styles on a WordPress Settings Page

When you build a WordPress plugin settings page with @wordpress/components and @wordpress/scripts, the buttons, toggles and panels often look unstyled. Outside the block editor, WordPress does not load the component stylesheet for you, even though your script depends on wp-components.

This snippet loads the core wp-components styles on your settings page, and only there, so the controls look the same as in the editor.

The snippet

<?php
/**
 * Load the WordPress component (Gutenberg) styles on your own plugin settings page.
 */

// ===== Config =====
function dpc_component_styles_config() {
	$config = array(
		// Hook suffix of each settings page, as returned by add_menu_page() / add_submenu_page(),
		// e.g. 'toplevel_page_my-plugin' or 'settings_page_my-plugin'.
		'screens' => array( 'settings_page_my-plugin' ),
		// Core style handles to load there. Add 'wp-block-editor' if the page renders block editor parts.
		'styles'  => array( 'wp-components' ),
	);
	// ===== End of config =====

	return (array) apply_filters( 'dpc_component_styles_config', $config );
}

add_action( 'admin_enqueue_scripts', 'dpc_component_styles' );

function dpc_component_styles( $hook_suffix ) {
	$config = dpc_component_styles_config();

	if ( ! in_array( $hook_suffix, (array) ( $config['screens'] ?? array() ), true ) ) {
		return;
	}

	foreach ( (array) ( $config['styles'] ?? array() ) as $handle ) {
		if ( wp_style_is( $handle, 'registered' ) ) {
			wp_enqueue_style( $handle );
		}
	}
}

Add it with Scripts Organizer

In Scripts Organizer go to Code Blocks → Add New and give the block a name. Set Trigger location to Admin only, tick PHP under Script location, paste the code into the PHP editor, edit the config and publish. Leave Action/Hook empty. Admin only fits: settings pages only exist in wp-admin, and the enqueue runs on admin_enqueue_scripts, the hook WordPress expects for admin styles.

The same code also works unchanged in a small plugin or an mu-plugin.

How it works

  • WordPress registers the wp-components style handle itself, pointing to wp-includes/css/dist/components/style.css. The snippet only enqueues that handle, so the version and the RTL file come from core and stay current after updates.
  • admin_enqueue_scripts passes the hook suffix of the current screen. The styles are added only when it is in your screens list, so other admin pages do not load an extra stylesheet.
  • Handles that are not registered are skipped, so a typo in styles cannot cause a notice.
  • The earlier version of this post called wp_enqueue_style() at the top level of the file. That runs before WordPress is ready for styles and logs “wp_enqueue_style was called incorrectly”. It also pointed a custom URL at the wp-editor handle name.

Find your hook suffix

add_menu_page() and add_submenu_page() return the hook suffix, for example toplevel_page_my-plugin for a top-level page or settings_page_my-plugin for a page under Settings. Not sure? Temporarily add error_log( $hook_suffix ); inside dpc_component_styles() and open your page.

Customise it

  • Several pages: add more hook suffixes to screens.
  • Block editor parts on the page (for example BlockEditorProvider): add 'wp-block-editor' to styles; for core block styles add 'wp-block-library'.
  • In your own plugin you can skip this snippet and list wp-components as a dependency of your stylesheet: wp_enqueue_style( 'my-plugin', $url, array( 'wp-components' ), $version );.

Gotchas

  • The styles are written for the editor. A few admin styles such as .wrap h1 or form inputs may still win over component styles on a classic settings page; scope your own CSS to the root element of your React app.
  • Since WordPress 6.x the component styles use CSS custom properties for the admin colour scheme, so they follow the user’s chosen colours.
  • For editor-only CSS, see CSS In Gutenberg editor.

In the Scripts Organizer library Import it with one click from Scripts Organizer.

// newsletter

Three tested WordPress snippets a week

Blocks, security, performance, Tailwind, PHP and React. Copy, paste, ship. You’ll also get DPlugins product updates. No spam, and you can unsubscribe anytime.

// newsletter

Three tested WordPress snippets a week

Blocks, security, performance, Tailwind, PHP and React. Copy, paste, ship. You'll also get DPlugins product updates. No spam, and you can unsubscribe anytime.