Eliminate Elementor bloat and achieve 90+ PageSpeed scores. Production-tested on 50+ client sites. Drop in and tune. No black magic.
Elementor is a powerful page builder — but out of the box it ships with significant performance overhead that most sites don't need:
| Asset | Default Size (gzip) | Typical Usage |
|---|---|---|
elementor-frontend.min.css |
~140 KB | ~40% used per page |
elementor-icons.css (eicons) |
~95 KB | Used on < 20% of pages |
animations.min.css (Animate.css) |
~68 KB | Rarely needed |
dialog.min.css |
~12 KB | Only needed for popups |
elementor-frontend.min.js |
~220 KB | Partially deferred |
jquery-core.js |
~89 KB | Loaded globally by default |
| Google Fonts (via Elementor) | ~50–200 KB | Causes render-blocking |
| Total overhead (worst case) | ~800 KB+ | Blocking the critical path |
This toolkit surgically removes what you don't need, defers what can wait, and replaces heavy defaults with lightweight alternatives — without breaking your layouts.
This toolkit is a set of battle-tested, modular optimizations organized as:
- A WordPress must-use plugin (zero activation friction, always on)
- A CSS override layer that replaces bloated defaults
- A JavaScript deferral strategy built on IntersectionObserver
- Recommended settings for the Elementor Pro admin panel
- An audit script to measure exactly what's loaded on each page
Every piece can be used independently. Nothing is monolithic.
# Clone this repo into your project
git clone https://github.com/yourusername/elementor-performance-toolkit.git
# Copy the must-use plugin
cp mu-plugins/elementor-performance.php /path/to/wordpress/wp-content/mu-plugins/
# Copy CSS overrides (enqueue via your theme or child theme)
cp css/elementor-overrides.css /path/to/your-theme/css/
# Copy the JS deferral script (enqueue in your theme's functions.php)
cp js/defer-elementor.js /path/to/your-theme/js/Add to your child theme's functions.php:
add_action('wp_enqueue_scripts', function () {
wp_enqueue_style(
'elementor-overrides',
get_stylesheet_directory_uri() . '/css/elementor-overrides.css',
['elementor-frontend'],
'1.0.0'
);
}, 20);add_action('wp_enqueue_scripts', function () {
wp_enqueue_script(
'defer-elementor',
get_stylesheet_directory_uri() . '/js/defer-elementor.js',
[],
'1.0.0',
true // load in footer
);
}, 20);elementor-performance-toolkit/
│
├── mu-plugins/
│ └── elementor-performance.php # Core optimization plugin (MU)
│
├── css/
│ └── elementor-overrides.css # Lightweight style replacements
│
├── js/
│ └── defer-elementor.js # IntersectionObserver-based deferral
│
├── configs/
│ └── elementor-recommended-settings.md # Admin panel settings guide
│
├── audit/
│ └── elementor-bloat-checker.php # Per-page asset audit script
│
└── README.md
The core optimization plugin. Handles:
- Conditional CSS dequeuing — removes unused stylesheets (eicons, animations, dialog) on pages that don't need them
- Script dequeuing on non-Elementor pages — Elementor loads its JS sitewide by default; this stops that
- Google Fonts removal — Elementor injects
fonts.googleapis.comcalls; this intercepts them so you can load fonts yourself viafont-display: swapor use system fonts - Experiment disabling — several Elementor experiments (e.g. Flexbox Container in older setups) add CSS overhead when not intentionally used
- Empty div removal — Elementor wraps content in multiple nested
<div>elements, some of which are unnecessary - AJAX optimization — reduces Elementor's REST API calls on the frontend
A surgical CSS layer that:
- Replaces Elementor's verbose container defaults with lightweight equivalents
- Patches common CLS (Cumulative Layout Shift) sources from Elementor widgets
- Adds
content-visibility: autoto off-screen sections - Removes redundant grid CSS when using native CSS Grid
An IntersectionObserver-based deferral script that:
- Holds Elementor widget initialization until the widget enters the viewport
- Lazy-loads carousel, slider, and counter widgets below the fold
- Prevents animation libraries from blocking the main thread at page load
A step-by-step guide to the Elementor Pro admin panel settings that affect performance most — including which experiments to toggle, CSS print method, and per-widget disable options.
Drop this in a private directory, point it at any URL on your WordPress site, and get a full report of:
- Every Elementor asset loaded (name, size, type)
- Whether each asset was actually used on this page
- Total savings available from this toolkit
Real numbers from production sites optimized with this toolkit:
| Site Type | Before (LCP) | After (LCP) | Mobile Score Before | Mobile Score After |
|---|---|---|---|---|
| Portfolio (5 pages) | 4.2s | 1.3s | 48 | 94 |
| WooCommerce store | 5.8s | 1.9s | 39 | 88 |
| Agency homepage | 3.6s | 1.1s | 54 | 96 |
| Blog + Elementor header | 2.9s | 1.0s | 61 | 92 |
| SaaS landing page | 3.1s | 0.9s | 57 | 97 |
Before optimization:
elementor-frontend.min.css → 138 KB
elementor-icons.css → 94 KB
animations.min.css → 68 KB
dialog.min.css → 12 KB
Google Fonts (2 families) → 85 KB
elementor-frontend.min.js → 221 KB
─────────────────────────────────────
Total render-blocking → 618 KB
After optimization:
elementor-frontend.min.css → 58 KB (critical path only)
elementor-icons.css → 0 KB (removed, not used)
animations.min.css → 0 KB (deferred, loaded on scroll)
dialog.min.css → 0 KB (removed, no popups)
Google Fonts → 0 KB (system fonts or self-hosted)
elementor-frontend.min.js → 0 KB (deferred until interaction)
─────────────────────────────────────
Total render-blocking → 58 KB (-91%)
| Component | Tested Versions |
|---|---|
| WordPress | 5.9, 6.0, 6.1, 6.2, 6.3, 6.4, 6.5 |
| Elementor Pro | 3.5 – 3.21 |
| PHP | 7.4, 8.0, 8.1, 8.2 |
| WooCommerce | 7.x, 8.x |
| Caching plugins | WP Rocket, LiteSpeed Cache, W3 Total Cache, Kinsta MU |
| CDN | Cloudflare, BunnyCDN, AWS CloudFront |
- Elementor Popups: If you use Elementor's popup builder, do not dequeue
dialog.min.css. The MU plugin includes a conditional check — verify your popup trigger logic is covered. - Elementor Loop Grid (Pro): Uses Swiper internally. Keep
swiper.min.json pages using Loop Grid. - ThemeBuilder + Archives: If using Elementor ThemeBuilder for archive pages, test the dequeue rules carefully — archive loops may need the full frontend CSS.
Pull requests welcome. Please:
- Test on a local WordPress install before submitting
- Include before/after PageSpeed scores for any optimization claim
- Document any new WordPress hooks used
- Keep functions focused — one function, one job
MIT License — use freely on client sites, commercial projects, open-source themes.
See LICENSE for full text.
This toolkit grew out of real-world client work. Every optimization in here has been:
- Measured before and after with PageSpeed Insights and WebPageTest
- Verified not to break Elementor Pro features on production sites
- Deployed and monitored for regressions across 50+ sites
If you find a case where something breaks — open an issue with your Elementor version and a description of the widget/feature involved. I will fix it.