TechEarl

Remove the wp-block-library CSS in WordPress (Carefully)

How to dequeue the wp-block-library CSS in WordPress, and the one big caveat: do it only on a site whose front end uses no block markup, or you break your layout.

Ishan Karunaratne⏱️ 13 min readUpdated
Share thisCopied
How to remove the wp-block-library CSS in WordPress: a wp_enqueue_scripts snippet that dequeues the core block stylesheets, safe only on a site whose front end renders no block markup.

To dequeue the core block CSS that Gutenberg prints on the front end, hook wp_enqueue_scripts at a late priority and drop the relevant handles:

php
add_action( 'wp_enqueue_scripts', function () {
    wp_dequeue_style( 'wp-block-library' );
    wp_dequeue_style( 'wp-block-library-theme' );
    wp_dequeue_style( 'classic-theme-styles' );
    wp_dequeue_style( 'global-styles' );
}, 100 );

Read this part before you paste anything: most WordPress sites should not do this. The block editor has been the default since WordPress 5.0, so the typical site renders block markup on the front end, columns, buttons, galleries, cover blocks, and that markup depends on exactly the CSS this snippet removes. Strip it on such a site and your layout breaks. This is a narrow optimization for one specific kind of site, not a blanket "speed up WordPress" win. The whole article below is about figuring out whether you are that kind of site, and verifying it visually before you keep the change.

What wp-block-library is and when it loads

When WordPress 5.0 shipped the block editor (Gutenberg) in December 2018, it also started enqueueing the CSS those blocks need to render on the front end, not just in the editor. On a current install you will see these stylesheet handles printed in the page source:

  • wp-block-library: the core block styles. This is the big one, the rules that make core/columns, core/buttons, core/gallery, core/cover and the rest lay out correctly.
  • wp-block-library-theme: a smaller set of theme-facing block styles (things like the default look of a pull quote or a separator).
  • classic-theme-styles: a compatibility stylesheet WordPress added in 6.1 (late 2022) via wp_enqueue_classic_theme_styles(), enqueued for classic (non-block) themes so block content (notably Button and File blocks) keeps its back-compat styling inside them.

WordPress 5.9 (January 2022) added one more when it introduced theme.json and global styles: a global-styles handle, which prints the inline CSS your theme's theme.json generates (colors, spacing, typography presets). It is not a separate file request like the others; it is inline <style> output. I have included it in the snippet because if you are stripping block CSS you usually want the global-styles inline block gone too, but treat it as the modern addition it is, not core to the original problem.

One caveat on global-styles specifically: because it is generated inline by an action callback rather than enqueued as a plain file, wp_dequeue_style( 'global-styles' ) does not always clear it. If you still see the inline global CSS in the page source after dequeuing, remove the callback that prints it instead:

php
add_action( 'wp_enqueue_scripts', function () {
    remove_action( 'wp_enqueue_scripts', 'wp_enqueue_global_styles' );
    remove_action( 'wp_footer', 'wp_enqueue_global_styles', 1 );
}, 1 );

The remove_action() form is the robust one for global-styles; reach for it when the dequeue alone leaves the inline block behind.

All of these are enqueued by core during the normal asset pass, which is why you remove them on wp_enqueue_scripts rather than with a remove_action() like the emoji or shortlink cleanups.

The big caveat: only if your front end uses no blocks

This is the part that decides whether the snippet helps you or wrecks your site, so I am putting it before the "how much does it save" section on purpose.

The block editor has been the default editor since WordPress 5.0. That means unless you deliberately run the Classic Editor plugin, or build every page in a third-party page builder, your posts and pages are almost certainly made of blocks. A two-column layout, a styled button, an image gallery, a cover block with an overlay: every one of those renders correctly because wp-block-library is on the page. Remove it and the columns stack wrong, the button loses its padding and background, the gallery collapses, the cover overlay disappears.

So there are really only two situations where dequeuing this CSS is safe:

  • A classic-editor site: you run the Classic Editor plugin (or a classic-editor setup) and your content is plain TinyMCE HTML with no block markup at all.
  • A page-builder-only site: every front-end page is built in Elementor, Beaver Builder, Bricks, Divi, or similar, the builder ships its own CSS, and core blocks never appear in the rendered output.

If you are not clearly in one of those buckets, leave the CSS alone. And even if you think you are, you still have to verify visually (see the verification section), because one stray block in one old post is enough to break that one page after you strip the styles.

How much does this actually save?

Unlike the emoji or shortlink cleanups, this one can remove a real CSS request rather than a few bytes of inline head output. wp-block-library is a genuine render-blocking stylesheet the browser fetches and parses before it paints. On a current install its minified style.min.css is roughly 25 to 30 KB (the exact figure shifts release to release as core adds blocks). On a site that does not use it, dropping it removes that request and its round trip, plus the smaller wp-block-library-theme and classic-theme-styles files, and trims the inline global-styles block out of the HTML.

That sounds like a meaningful win, and on the right site it is a clean one. But I want to be honest about the shape of it:

  • This only helps the narrow slice of sites that genuinely render no blocks. For everyone else the "saving" is negative, because you are trading a CSS request for a broken layout.
  • Even where it is safe, it is one request. If the site is genuinely slow, this is not why. Caching, image sizing, and your slowest plugins and queries move the needle far more than a single stylesheet. On a store, the real WooCommerce speed levers are in the database, not the head.
  • Most readers who land here looking to "speed up WordPress" by removing block CSS should not apply this at all. The right answer for a block-based site is to keep the CSS and optimize elsewhere.

So: a real request you can remove on the right site, nothing you should reach for reflexively. The decision is entirely about whether your front end uses blocks, which is the previous section, not this one.

If your site does use blocks: load block CSS on demand

Most readers who land here do use blocks, and the honest advice above is "leave wp-block-library alone." But there is a middle path that trims the same bloat without the breakage: tell core to split the one monolithic stylesheet into per-block stylesheets and load only the blocks actually present on the page.

Core has supported this since WordPress 5.8 (July 2021) behind a single filter:

php
add_filter( 'should_load_separate_core_block_assets', '__return_true' );

Flip that on and instead of shipping the whole wp-block-library file on every request, WordPress enqueues a small stylesheet per block type and prints only the ones that block appears on the page. A post with a paragraph and an image no longer carries the CSS for galleries, columns, and cover blocks it never uses. Nothing breaks, because every block still gets exactly the styles it needs.

This is the right lever for a block-based site: you keep the blocks, you keep correct rendering, and you cut the dead CSS that the dequeue approach can only remove by also removing the styles you depend on. It pairs well with inlining the critical CSS for the blocks above the fold, so the first paint does not wait on any block stylesheet at all.

Two notes worth knowing before you ship it. The filter is a global toggle, so test the front end the same way you would for the dequeue (look at multi-column layouts, buttons, galleries) to confirm a theme or plugin is not relying on the combined file being present. And block themes (full site editing) already behave closer to this model, so the win is largest on classic themes that opt in explicitly.

Put it in a plugin, not the theme

As with every asset cleanup, keep this out of functions.php so it survives a theme switch. The block CSS coming back silently the day someone changes themes is exactly the kind of "why is there a stylesheet I removed?" mystery that wastes an afternoon later. Drop it into wp-content/mu-plugins/te-remove-block-css.php:

php
<?php
/**
 * Plugin Name: TE Remove Block Library CSS
 * Plugin URI:  https://techearl.com/remove-wp-block-library-css
 * Description: Dequeues the core block stylesheets on the front end. Only for sites that render no block markup.
 * Version:     1.0.0
 * Author:      Ishan Karunaratne
 * Author URI:  https://techearl.com
 * License:     GPL-2.0-or-later
 * Text Domain: te-remove-block-css
 */

add_action( 'wp_enqueue_scripts', function () {
    wp_dequeue_style( 'wp-block-library' );
    wp_dequeue_style( 'wp-block-library-theme' );
    wp_dequeue_style( 'classic-theme-styles' );
    wp_dequeue_style( 'global-styles' );
}, 100 );

The late priority (100) is the implementation detail that matters. Hooks fire in priority order, and core enqueues these styles during the normal wp_enqueue_scripts pass at the default priority 10. If your dequeue ran at 10 too, it might fire before the style was queued, and there would be nothing to remove yet. Running at 100 puts you after the enqueuers, so the handles are in the queue by the time you take them out. This is the same reason the Dashicons dequeue uses a late priority.

Files in wp-content/mu-plugins/ (must-use plugins) load automatically, before regular plugins, cannot be deactivated by accident from the dashboard, and survive theme changes, which is exactly the behaviour you want for infrastructure-level tweaks like this.

Verify it worked

A visual check is mandatory here, not optional. This is the cleanup most likely to break something, so verifying is the actual work, not an afterthought.

First confirm the stylesheet is gone from the source. Logged out, in a private window:

text
$ curl -s https://example.com/ | grep -i block-library
(no output)

No output means wp-block-library is no longer printed. But that only tells you the CSS is gone, not that the page is fine without it. So the real test is the eyes:

  • Open the front end and click through every page template you have: the home page, a post, a page, the archive, the front page if it is custom.
  • Look specifically for the things block CSS controls: multi-column layouts (do they stack or sit side by side?), buttons (do they have padding and a background, or are they bare links?), galleries (grid or a vertical pile?), cover blocks (overlay present or gone?), separators and pull quotes.
  • Check an old post too, not just recent ones. A single legacy post built with a block when you were briefly on the default editor is enough to break that one page.

If everything renders the way it did before, you are clear: your front end genuinely uses no blocks and you have removed a real request. If anything looks wrong, your site uses block markup after all. Pull the snippet, put the CSS back, and accept that this optimization is not for your site. There is no middle ground where you keep a half-broken layout to save one request.

The usual reasons the stylesheet survives after you add the snippet are the familiar three: a page cache serving old HTML (purge it), a priority that runs too early (it is set to 100 above for this reason), or a plugin re-enqueueing block CSS after your callback runs.

See also

Sources

Authoritative references this article was fact-checked against.

TagsWordPressPerformancePHPGutenbergwp_enqueue_scriptsPage Speed

Found this useful? Pass it on.

Copied

Ishan Karunaratne

Tech Architect · Software Engineer · AI/DevOps

Tech architect and software engineer with 20+ years building software, Linux systems, and DevOps infrastructure, and lately working AI into the stack. Currently Chief Technology Officer at a healthcare tech startup, which is where most of these field notes come from.

Keep reading

Related posts

Add a Custom WP-CLI Command in WordPress

How to register a custom WP-CLI command: guard it with defined('WP_CLI'), wire it up with WP_CLI::add_command(), turn class methods into subcommands, document args with @synopsis, and show progress with make_progress_bar().