
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 |
|---|---|---|
| Removes the style from the output queue in | The style is registered and enqueued, the standard case |
| 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 */ 5 function 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 } 14 add_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>:
1 add_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:
1 function 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 } 13 add_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 andonload="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 */ 4 function 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 } 12 add_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 */ 4 function 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 } 14 add_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 viawp_deregister_scriptof the parent script or find the hook the plugin uses to add inline styles.The plugin inserts CSS directly into
<head>viaecho. 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'sheader.php: if you see a directecho '<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_scriptshook do not affect the frontend and don't need to be disabled. Moreover, trying to deregister admin styles throughwp_enqueue_scriptswon'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
-csssuffix is added by the WordPress core in theWP_Dependencies::enqueue()method since version 2.6; this is an unchanging mechanism. But there's a nuance: if the plugin developer manually assigned a customidto the<link>tag, the suffix may not be present. In that case, the handle is the second argument of thewp_enqueue_style()call in the plugin's source code. The-cssrule 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_stylecall 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 itsid. 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
idattribute in the page source code. The rule of stripping-cssworks 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
9999covers any "stubborn" plugins, and thewp_enqueue_scriptshook 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.



