A very common scenario: you switch on Remove Unused CSS (RUCSS) in WP Rocket to chase a PageSpeed score, the pages get faster, everything looks fine — until someone reports that the mobile menu won't open, the dropdown doesn't appear, or a modal shows up unstyled. On desktop everything's normal, but the interactive components are broken.
I hit this while optimizing an editorial site for a client. And what made it even more confusing: in my admin account everything was fine. The problem only showed up once I opened the site in incognito.
Why RUCSS strips the CSS you need
RUCSS works by scanning the initial HTML of the page, then keeping only the CSS selectors it finds there. The rest gets dropped to save weight.
The problem: many UI states don't exist in the initial HTML yet. They only get set by JavaScript after the user interacts:
[data-open="1"]— appears when the drawer opens.is-active/.is-open— added on click[aria-expanded="true"]— toggled when a dropdown opens
Because these selectors aren't present when RUCSS scans, they're treated as "unused" and removed. So the moment the drawer/dropdown/modal opens, its CSS is already gone → the component renders broken.
Trap #1: a logged-in admin sees a different version
This is what cost me the most time. WP Rocket doesn't serve the RUCSS output to logged-in admins — you see the full CSS, so everything looks normal. Anonymous visitors get the stripped-down version.
The rule: always verify through incognito or an anonymous curl, never trust what you see in your admin tab.
# Check the HTML visitors actually see
curl -s "https://situs-anda.com/" | grep -i "wpr-usedcss"The fastest diagnostic: append ?nowprocket to the URL to bypass WP Rocket's entire process. If the component works normally with ?nowprocket, RUCSS is your culprit.
The fix: safelist the toggle selectors
Add the interactive-state selectors to the "CSS Safelist" in WP Rocket (File Optimization → Remove Unused CSS). But there's one important limitation:
The safelist only accepts plain classes (
.class) and ids (#id) — not attribute selectors like[data-open]or[aria-expanded].
So for components controlled by attributes, you have to work around it. Three options, from cleanest down:
-
Add a toggle class, not just an attribute. When your JS opens the drawer, set
.is-openand[data-open], then safelist.is-open. Simple and fully supported. -
Set the critical styles directly from JS (a safety belt). Even if the CSS gets stripped, the JS still forces the styles:
drawer.style.setProperty("display", "block", "important"); drawer.style.setProperty("transform", "translateX(0)", "important"); -
Use "Load CSS Asynchronously" instead of RUCSS for pages with complex interactive CSS — fewer savings, but it doesn't throw away your toggle states.
Trap #2: turning RUCSS off doesn't auto-clear the old cache
This one matters. When you disable RUCSS, WP Rocket does not automatically discard the cached wpr-usedcss blocks stored per-URL. Old pages keep serving the stripped CSS.
After changing any RUCSS setting, you have to click Tools → "Clear Used CSS" specifically — a regular "Clear Cache" isn't enough.
Checklist for "components broke after WP Rocket"
- Open in incognito (or
?nowprocket) — confirm this only happens for anonymous visitors. - Identify the missing state — a drawer/dropdown/modal toggled by JS.
- Safelist its toggle class (
.is-open,.is-active) — remember, attribute selectors aren't supported. - For attribute-driven components: add a toggle class, or force the critical styles from JS.
- After changing settings, "Clear Used CSS" — not just a regular clear cache.
RUCSS is a great performance tool, but it's blind to anything that only appears after interaction. Once you understand that, the fix is quick — and your mobile menu comes back to life without sacrificing your PageSpeed score.
