I was setting up a rebuild for a client site built on Elementor, and step one was routine: clone production to local. I used Studio by WordPress.com, the local environment that runs PHP through WASM with SQLite as the database. The production DB import finished, I opened the home page, and the entire site rendered unstyled. Broken nav, broken hero, every section collapsed into a stack of left-aligned text. The HTML was all there. The styling was not.
First reflex: open DevTools and hunt for 404s in the Network tab. And here is the first trap. Studio runs an Express layer in front of its PHP, and that layer redirects requests for missing static files to /?ver=.... That request returns the home page HTML with a text/html mime type. So the browser silently loads HTML where a stylesheet should be, CSS parsing fails without a sound, and the Network tab shows no obvious 404. Everything looks like a success. It took me a while to notice that the "CSS" response was actually the home page.
Stop trusting the Network tab, check the disk
Once I checked the filesystem directly, the picture was clear: Elementor's per-post CSS files at /wp-content/uploads/elementor/css/post-{ID}.css were missing. Elementor writes one CSS file per document, and in this clone those files were gone for nearly every page.
I tried the classic move: hit the page in the browser and hope Elementor regenerates the file on its own. Nothing happened. In Elementor 4.x, a page hit alone does not rewrite the per-post CSS file. So this was not going to heal itself; the files had to be recreated explicitly.
Root cause: RUCSS state that hitched a ride from prod
The production site runs WP Rocket with Remove Unused CSS (RUCSS) enabled. RUCSS works by processing Elementor's per-post CSS files into optimized inline rows in the wp_wpr_rucss_used_css table, then removing or replacing the originals. That processing runs through async background jobs. In production, the cycle completes normally. Inside Studio's container, those jobs never complete reliably.
And because I imported the production DB wholesale, all of that RUCSS state came along for the ride. The RUCSS table held 783 leftover rows from prod. Even after I deactivated WP Rocket, the symptom persisted, because the artifacts were everywhere: cache directories like used-css/, min/, wp-rocket/, critical-css/, background-css/, and busting/, wp_rocket_* rows and their transients in wp_options, and the post-{ID}.css files that RUCSS had already deleted back on prod. Deactivating a plugin does not bring back files that no longer exist.
The fix: clean up, then regenerate in code
First, deactivate WP Rocket on the Studio clone only. It stays active on prod and needs no changes there; this whole problem is about a local environment that cannot run the RUCSS cycle.
Second, delete the leftover cache directories:
wp-content/cache/used-css/
wp-content/cache/min/
wp-content/cache/wp-rocket/
wp-content/cache/critical-css/
wp-content/cache/background-css/
wp-content/cache/busting/Third, clear the leftover rows in wp_options:
DELETE FROM wp_options
WHERE option_name LIKE '%rocket%'
OR option_name LIKE '%wp_rocket%'
OR option_name LIKE '%wpr_%';Fourth, and this is the key step: regenerate the CSS per document, programmatically. Bootstrap WordPress, collect every Elementor document (the kit, header, footer, templates, and every page carrying _elementor_data meta), then call the CSS file API for each one:
require __DIR__ . '/wp-load.php';
// kit, header, footer, templates, and every post with _elementor_data
$ids = get_posts( [
'post_type' => 'any',
'post_status' => 'any',
'posts_per_page' => -1,
'fields' => 'ids',
'meta_key' => '_elementor_data',
] );
foreach ( $ids as $pid ) {
\Elementor\Core\Files\CSS\Post::create( $pid )->update();
}One gotcha worth underlining: do not call \Elementor\Plugin::$instance->files_manager->clear_cache() afterwards. It sounds like a sensible tidy-up step, but it wipes the very files you just generated.
Once WP Rocket was off and the regen had run, rendering came straight back. The nav was a nav again, the hero was a hero again.
The ongoing risk: kit-level cascades
There is one behavior to keep watching after this. Calling update() on a single page can trigger a kit-level cascade that wipes the per-post CSS files of OTHER documents, including the header and footer. The symptom is distinctive: the header and footer render unstyled, with the logo and menu items stacking vertically as plain text. So after any Elementor data edit, re-run the regen for the full list of known documents, not just the page you touched.
The takeaway
- Importing a production DB into a local environment imports your optimization plugin's state too. RUCSS with no working background jobs means per-post CSS disappears with nothing to replace it.
- If the local environment redirects missing static files to HTML, the Network tab will lie to you. Check the disk, and check what the stylesheet response actually contains.
- In Elementor 4.x, a page hit does not write the CSS file. Regeneration must be explicit via
Post::create( $pid )->update(). - Never
clear_cache()after a regen, and re-run the full-list regen after every Elementor data edit so a kit cascade does not take down your header and footer.
