Skip to content

Everything for WordPress, web development — and beyond

How to disable WordPress plugin CSS styles via functions.php

How to disable WordPress plugin CSS styles via functions.php

You know the feeling: your WordPress site is ready, styled, plugins are all in place. You run PageSpeed Insights, and there it is, orange. Or red. The culprit is almost always the same: CSS. Dozens of style files from plugins and the theme line up in a queue and block rendering. The page is slow not because it's heavy, but because the browser is waiting.

The problem runs deeper than it seems. A plugin loads its style.css on every page of the site, even where its functionality isn't used. A contact form only appears on the contacts page, yet its styles load everywhere. A slider sits on the homepage, but its four CSS files hang on every URL without exception. That's dozens of unnecessary kilobytes and requests on every page view.

You can disable unnecessary styles without installing additional plugins, through functions.php. This isn't a hack; it's a built-in WordPress mechanism that has worked since version 2.6. Below is the complete guide: from finding the identifier to asynchronously loading a combined file.

💡 Quick overview:

  • How to find the identifier (handle) of any plugin CSS file through the id attribute in the page source code
  • How to disable styles using the wp_dequeue_style + wp_deregister_style combination with the correct priority
  • How to combine disabled styles into a single file and load it asynchronously via media print, without losing styling and without blocking rendering

How to find the CSS file identifier of a plugin

WordPress assigns a unique identifier, a handle, to every enqueued style file. This handle is what the functions wp_dequeue_style (documentation) and wp_deregister_style (codex) require. Without the correct handle, nothing gets disabled.

The most reliable method is to look at the page's HTML source code. Guessing based on the plugin name doesn't work; the plugin developer names the handle however they want, and the logic can be non-obvious.

Open the page source (Ctrl+U or view-source: before the URL) and find the <link> tag that loads the CSS of the plugin you need. For example, for Elementor it looks like this:

1<link href="/wp-content/plugins/elementor/assets/lib/animations/animations.min.css"
2 id="elementor-animations-css" media="all" rel="stylesheet" type="text/css">

Look at the id attribute. WordPress constructs it using the pattern: **plugin handle + the suffix **-css. In the example above, id="elementor-animations-css", which means the handle is elementor-animations. Strip -css from the end of the id value, and you get the exact handle for disabling. This works for any plugin or theme.

There are cases where the developer doesn't include an id on the <link> at all. In that case, find neighboring elements with an id or check the <script> tags of the same plugin: scripts use the -js suffix, and the handle often matches the style one. If you still can't find it, open the plugin's source code in /wp-content/plugins/... and find the wp_enqueue_style() call: the first argument is the handle.

Disabling styles: wp_dequeue_style and wp_deregister_style

WordPress provides two functions for managing styles. The difference is fundamental:

Function

What it does

When to use

wp_dequeue_style

Removes the style from the output queue in <head>

The style is registered and enqueued, the standard case

wp_deregister_style

Completely removes the style's registration from the system

You need to not just hide it, but replace it with your own version or exclude it permanently

In practice, both functions are used together: wp_dequeue_style removes it from the queue, and then wp_deregister_style in the codex ensures that no other code re-enqueues that handle through the dependency chain.

Basic code for functions.php

The code below disables styles from two plugins: full-screen-search and prettyPhoto. The high priority 9999 ensures the disabling runs AFTER the plugin has registered and enqueued its styles. Without the elevated priority, the function may execute before the plugin, leaving nothing to disable.

1/**
2 * Disable CSS files of specific plugins.
3 * Priority 9999 — runs last in the wp_enqueue_scripts chain.
4 */
5function sdstudio_dequeue_plugin_styles() {
6 // Dequeue
7 wp_dequeue_style( 'full-screen-search' );
8 wp_dequeue_style( 'prettyPhoto' );
9
10 // Deregister — so no one can re-enqueue
11 wp_deregister_style( 'full-screen-search' );
12 wp_deregister_style( 'prettyPhoto' );
13}
14add_action( 'wp_enqueue_scripts', 'sdstudio_dequeue_plugin_styles', 9999 );

What matters here: the hook wp_enqueue_scripts is the correct place for this operation. Not wp_head, not init, not wp_loaded. It is on wp_enqueue_scripts that WordPress assembles the style queue, and this is where you should disable them, just later than the plugins do.

Why priority 9999, not 11 or 99

Plugins register styles with the default priority of 10. But some set 20, 50, or even 100 when they have complex dependency chains. A priority of 9999 covers virtually any real-world scenario. The only downside: if two of your own snippets share the same priority of 9999, their execution order is undefined. In practice this is rare, while using 11 regularly fails with "stubborn" plugins.

Additionally, you can register the disabling on the wp_head hook with the same priority as a safety net for styles that a plugin enqueues by bypassing wp_enqueue_scripts and outputting directly into <head>:

1add_action( 'wp_head', 'sdstudio_dequeue_plugin_styles', 9999 );

But this is a fallback. Normally, a single wp_enqueue_scripts is enough.

How to disable ALL styles of a specific plugin

Many plugins have not one CSS file, but several. Contact Form 7, WooCommerce, Elementor, each drags in 3-5 style files. Disabling them one by one is tedious. Scan the page source and collect all handles with the same prefix: they are usually grouped together.

Example for Elementor, a typical set of handles: elementor-frontend, elementor-animations, elementor-icons, and elementor-pro. All four in a single call:

1function sdstudio_dequeue_elementor_styles() {
2 $handles = [
3 'elementor-frontend',
4 'elementor-animations',
5 'elementor-icons',
6 'elementor-pro',
7 ];
8 foreach ( $handles as $handle ) {
9 wp_dequeue_style( $handle );
10 wp_deregister_style( $handle );
11 }
12}
13add_action( 'wp_enqueue_scripts', 'sdstudio_dequeue_elementor_styles', 9999 );

What to do with disabled styles

Disabling is only half the job. If you simply remove a plugin's CSS, everything on the page breaks: forms get misaligned, sliders fall apart, icons disappear. The styles are needed, just not at the cost of blocking rendering.

The right approach: combine the disabled styles into ONE compact file and load it without blocking. The algorithm:

  • Disabled plugin styles via wp_dequeue_style + wp_deregister_style.
  • Copied the contents of EVERY disabled CSS file. Take them from the plugin folder, not from the browser inspector, which shows a minified build that's inconvenient to work with.
  • Combined them into a single file, for example /wp-content/themes/your-theme/css/dequeued-plugins.css.
  • Loaded it with the media="print" attribute and onload="this.media='all'". The browser downloads the file asynchronously without blocking rendering and applies the styles after loading.

Combined file loading code

1/**
2 * Load the combined CSS file of disabled styles asynchronously.
3 */
4function sdstudio_enqueue_dequeued_styles() {
5 wp_enqueue_style(
6 'sdstudio-dequeued',
7 get_stylesheet_directory_uri() . '/css/dequeued-plugins.css',
8 [],
9 filemtime( get_stylesheet_directory() . '/css/dequeued-plugins.css' )
10 );
11}
12add_action( 'wp_enqueue_scripts', 'sdstudio_enqueue_dequeued_styles', 1 );

The priority of 1 here is intentional: the combined file must be enqueued BEFORE the disabling functions with priority 9999 execute. Otherwise, WordPress may fail to recognize the dependency and drop the styles from the queue entirely.

Asynchronous loading without a plugin

To prevent the browser from waiting on the CSS file before rendering the page, add media="print" and onload attributes via the style_loader_tag filter:

1/**
2 * Change media="print" to onload-switch for asynchronous CSS loading.
3 */
4function sdstudio_async_css( $html, $handle ) {
5 if ( 'sdstudio-dequeued' !== $handle ) {
6 return $html;
7 }
8 return str_replace(
9 "media='all'",
10 "media='print' onload=\"this.media='all'; this.onload=null;\"",
11 $html
12 );
13}
14add_filter( 'style_loader_tag', 'sdstudio_async_css', 10, 2 );

The mechanism is straightforward: the browser sees media="print" and does not block rendering, since the print media type does not affect the screen. After the file loads, onload fires, switches media to all, and the styles are applied instantly. The user sees a fully styled page with no delay on initial load.

When you should not disable styles via functions.php

The wp_dequeue_style method is powerful, but not universal. Here are three cases where it is either useless or harmful:

  • Styles are embedded inline via wp_add_inline_style. Such styles live inside a <style> tag and have no separate handle. You'll need to disable them via wp_deregister_script of the parent script or find the hook the plugin uses to add inline styles.

  • The plugin inserts CSS directly into <head> via echo. This is a workaround used by some older plugins. Only finding the specific hook or, as a last resort, output buffering will help here.

  • You're working with a third-party theme that manages dependencies on its own. Some themes, especially premium ones, use their own asset loader that bypasses WP_Styles. Before writing code, check the theme's header.php: if you see a direct echo '<link...', the deregister system won't work.

In these cases, it's better to use specialized plugins like Asset CleanUp or Perfmatters, which work at the URL level and disable assets on a per-page basis without digging into hooks.

Watch the video guide on disabling styles: the entire process from finding the handle to verifying the result in 8 minutes.

⁉️🤔 Frequently asked questions

Do I need to disable CSS styles in the admin panel (*/wp-admin/*)?

No. Styles loaded via the admin_enqueue_scripts hook do not affect the frontend and don't need to be disabled. Moreover, trying to deregister admin styles through wp_enqueue_scripts won't do anything, as they are registered separately. If the admin panel is slow, the problem is usually elsewhere: heavy analytics scripts in the dashboard, external Google Fonts, or the Heartbeat API.

Is it safe* to remove -css from the id attribute to get the handle? Does this rule always work?*

Yes, the -css suffix is added by the WordPress core in the WP_Dependencies::enqueue() method since version 2.6; this is an unchanging mechanism. But there's a nuance: if the plugin developer manually assigned a custom id to the <link> tag, the suffix may not be present. In that case, the handle is the second argument of the wp_enqueue_style() call in the plugin's source code. The -css rule covers the vast majority of cases.

Can I disable styles only on specific pages?

Yes, and this is the proper production approach. Wrap the wp_dequeue_style call in a WordPress conditional tag: is_front_page() for the homepage, is_single() for posts, is_page() for pages, is_archive() for archives. To exclude by post ID, use ! is_single(123). Conditional dequeuing on specific URLs reduces load across the entire site, not just where the plugin isn't needed.

What happens if I call wp_dequeue_style for a handle that isn't registered?

Nothing. The function silently completes without errors, PHP notices, or warnings. This is safe. But don't rely on it as a strategy: collect handles only from real pages, otherwise your code accumulates "dead" lines that do nothing and only clutter functions.php.

How do I verify that a style was actually disabled, and not just stopped applying because of cache?

Open the page source (Ctrl+U), not the developer panel. Look for a <link> with the plugin's handle or its id. If the tag is gone, the style is disabled. Browser cache does not affect the source code, unlike the Network tab in DevTools. Additionally, you can clear the WordPress cache: any caching plugin, then Purge All.

Key takeaways on disabling CSS in WordPress

Three main conclusions from this entire guide:

  • The handle is the key to everything. Without the correct identifier, no function will work. Always find the handle through the id attribute in the page source code. The rule of stripping -css works nearly every time; for exceptions, check the plugin's source code.

  • Dequeue + Deregister is the standard combination. The first function removes the style from the queue, the second ensures it doesn't resurface through the dependency chain. Priority 9999 covers any "stubborn" plugins, and the wp_enqueue_scripts hook is the only correct place for this operation.

  • Disabled styles should not disappear. Combine them into a single file and load it asynchronously via media="print" + onload. The user gets a fully styled page, and the browser doesn't wait for CSS before rendering.

Try it on one or two plugins today. A couple of minutes in functions.php, and the result is immediately visible in PageSpeed Insights. Start with the "heaviest" plugin, the one with the most CSS files: disable, combine, measure speed. Most likely, that alone will be enough to move from the orange zone to the green.