Divi 5 Dropdown Menu Not Showing? It Is Not Broken, It Is Behind the Page.

I upgraded sitezinc.com to Divi 5 and my header lost its dropdowns. Hover over Services, nothing. Hover over Products, nothing. If your Divi 5 dropdown menu not showing problem started right after an upgrade, I can save you the two afternoons I spent on mine, because the menu was never actually broken. It was rendering on time, at the right coordinates, fully opaque. It was just painting behind the page.

That is what made this hard. Every instinct says a missing dropdown is a CSS problem. Something did not compile, a rule got dropped, a plugin is overriding a display value. I chased all of those. They were all wrong.

This is my own site, so I can name it and show the real evidence instead of sanding the details off. sitezinc.com runs Divi 5 on WordPress 7.0 and PHP 8.2, and the header is a Divi 5 Theme Builder header, not the legacy child theme header. That one detail turns out to matter more than anything else in this post. I have written about the rest of that upgrade in my Divi 4 to Divi 5 migration notes, but this bug earned its own writeup.

What follows is the catalogue of wrong theories in the order I had them, then the one console command that ended the guessing, then the fix. The fix took about fifteen seconds. Finding it did not.

Five Theories I Chased Before the Right One

Here is the thing about a bug like this: the wrong theories are not stupid. Each one was a reasonable read of the evidence in front of me, and each one cost real time to disprove. Listing them is the honest part of the story. If you are searching right now for why your Divi 5 dropdown menu not showing on the front end, this table alone may spare you a few hours.

TheoryWhy it looked rightWhy it was wrong
The backward compatibility noticeDivi was flagging backward compatibility mode on the site, right when the menus brokeThe notice is informational. It reports legacy module usage and does not change how the header renders.
A corrupted transition ruleReading the submenu transition property in the console returned a string that looked mangled and truncatedThe CSSOM was truncating a long value for display. The actual rule was intact.
Leftover third-party custom CSSA Divi add-on vendor had left a rule in the custom CSS box forcing .nav li ul { display:flex }I removed it. No change. It was clutter, not the cause.
A responsive helper pluginIt injects its own menu configuration attributes into the header markupDisabling it changed nothing, and its configuration is mobile focused anyway.
An opacity or hover-state compile bug in Divi 5Divi 5 was new, and a reveal that does not reveal smells like a compile failureThe console proved the reveal was working. See the next section.

I want to be careful with the third-party plugin names, so I have left them generic. None of them turned out to be at fault, and a post that blames a vendor for a bug they did not cause is worse than no post at all.

The Console Said the Menu Was Working Perfectly

The theory that took longest to kill was the compile bug, and killing it is what turned the whole investigation around. On a real mouse hover, the submenu computed opacity 1 and visibility visible. The li:hover selector matched. The gap between the bottom of the menu link and the top of the submenu was minus one pixel, meaning the submenu was tucked exactly where it belonged.

So it was not opacity. It was not visibility. It was not position. The browser was doing everything Divi asked it to do. Something was sitting on top of the result.

One honest detail that cost me real time: synthetic hover events were unreliable here. Dispatching a mouseover from the console did not reproduce the hover state the way a physical pointer did, so every diagnostic had to run on a timer while I actually hovered the menu with my hand on the mouse. That is not elegant and it does not automate, but it was the only way to read true values.

Click to see the JavaScript code: the hit test that found the culprit (14 lines)
// Run this, then hover the menu with a real mouse.
// Synthetic mouseover events did not reproduce the hover state.
setTimeout(function () {
  var sub = document.querySelector('.et-menu li:hover > ul');
  if (!sub) { console.log('no open submenu'); return; }

  var r = sub.getBoundingClientRect();
  var hit = document.elementFromPoint(r.left + 10, r.top + 10);
  var cs = getComputedStyle(sub);

  console.log('opacity', cs.opacity, 'visibility', cs.visibility);
  console.log('z-index', cs.zIndex);
  console.log('top painted element', hit.tagName, hit.className);
}, 4000);

One Hit Test Ended the Guessing

The last three lines are the ones that mattered. document.elementFromPoint() takes a pair of viewport coordinates and hands back the topmost element painted there. According to MDN, it returns the topmost element at the specified coordinates, ignoring anything with pointer events disabled. Point it at a spot inside an open submenu and it will tell you, with no interpretation required, whether the submenu is the thing your cursor would actually hit.

It was not. The top painted element at the submenu's own coordinates was DIV.et_pb_section_1, the hero section of the page underneath the header.

The submenu had a computed z-index of 9999. The hero section it was losing to did not. That is the moment the bug stopped being a CSS mystery and became a layout architecture problem.

Why a z-index of 9999 Loses to a Section With No z-index at All

Most people treat z-index as a global ranking. Bigger number wins, so when something is hidden you type more nines. That model is wrong, and a Divi 5 dropdown menu not showing above the page body is exactly what happens when the wrong model meets reality.

A z-index value is only compared against its siblings inside the same stacking context. MDN puts it plainly: "Stacking contexts are treated atomically as a single unit in the parent stacking context." Once the header forms its own stacking context, everything inside it is flattened into one card in the deck. Shuffling the pages inside that card does not move the card.

What Actually Creates a Stacking Context

More things than you would guess, which is the real trap. Per MDN's stacking context reference, a new context is formed by the root element, by a positioned element with a z-index other than auto, by any element with position: fixed or sticky, by an opacity below 1, by a transform, a filter, a mix-blend-mode other than normal, isolation: isolate, and by contain: layout or paint.

Read that list again and notice how many of those a page builder applies without asking you. A fade-in animation sets opacity. A sticky header sets position. A subtle scale on hover sets transform. Any one of them silently seals a whole branch of the page into its own layer, and every z-index inside that branch is now a local argument.

Why This Bites Page Builders Specifically

In a hand-built theme, the header and the body live in one template and you can see the whole tree at once. In Divi 5 they do not. The Theme Builder header is its own template and the page body is another, assembled into separate wrappers at render time. You edit them on different screens, on different days, and nothing in either editor shows you how the two wrappers stack against each other.

So you end up with a dropdown carrying a z-index of 9999 inside a header wrapper that sits below the body wrapper. The submenu wins every argument in its own room and still loses the building. Elementor, Bricks and Divi all share this shape, which is why "my dropdown is behind my hero" is a page builder question far more often than a hand-coded theme question.

The Fix Was a Builder Setting, Not a Line of CSS

I did not want a custom CSS band-aid on this. A rule like .et-l--header { z-index: 100000 !important; } would have worked, and it would have been the wrong answer, because six months from now nobody remembers why that rule exists or which bug it was holding shut.

The native fix: open the Theme Builder header template, select the header section, and raise its Z Index setting under Advanced. That lifts the header's stacking context above the body's, and the dropdowns paint over the hero immediately. No snippet, no stylesheet, nothing to document in a file that a future me will never open.

Worth knowing: the first time I hit this, the header section had a Z Index hard-coded to 0, which is what put it level with the body content in the first place. Clearing that value let it fall back to Divi's own default of 10, and that was enough. The setting is on the section, not the row and not the Menu module. I lost time poking at the wrong element.

The Second Bug Hiding Behind the First

Fixing the stacking order revealed a smaller problem that had been invisible while the menus were, well, invisible. The dropdowns now painted on top, but the first-level dropdown background was transparent on hover, so the hero headline underneath bled straight through the submenu text. Readable if you squinted. Unusable if you were a visitor.

That one traced to the Menu module's dropdown hover state background being set to transparent. Divi 5 keeps separate values for the normal and hover states of a module, and it is easy to set one and assume you set both. Setting a solid background on the hover state finished it.

Two bugs, one symptom, and the second one only became visible after the first was fixed. That is a pattern worth expecting rather than being surprised by. If you want a sanity check on your own upgrade before you go hunting, my Divi 5 upgrade assessment tool covers the common breakage points.

What I Gave Up by Fixing It Natively

I still think the builder setting was the right call, but it is not free, and pretending otherwise would make this a brochure instead of a case study.

The biggest cost is invisibility. A CSS snippet lives in a file I can grep, diff and version. A Z Index value lives inside a Theme Builder template in the database. It does not show up in a code search, it does not appear in a git history, and no teammate reviewing the site's CSS will ever know it is load-bearing. That is not a hypothetical downside for me. It is the exact reason the first fix disappeared without anyone noticing until visitors could not use the menu.

The second cost is that I have now declared the header the winner against the entire page body, permanently. That is correct for a header. It also means that the day I want a full-screen body overlay or a modal that covers the header, I will be fighting my own fix. I would rather have that argument later than have broken menus now, but I am aware I moved the problem rather than eliminating it.

The third cost is process. The diagnostic that cracked this needed a physical mouse on a real machine, which means it cannot run in a headless check or a monitoring script. There is no automated test I can write that would have caught this before a visitor did.

This Is the Second Time I Have Fixed the Same Bug

Here is the part I would rather leave out. I fixed this once on June 27, by clearing that hard-coded z-index of 0 on the header section and confirming the dropdowns painted correctly over the hero. Four days later, on July 1, they were behind the hero again.

I never established why it reverted. The plausible candidates are a Divi or plugin update recompiling the Theme Builder template, or a Theme Builder save resetting the section value. I did not prove either one, and I am not going to dress up a guess as a root cause. What I know is that the setting was cleared on June 27 and was back in a losing state on July 1, and that raising it explicitly rather than relying on Divi's default has held since.

That is the difference between a fix and a fix you trust. If your Divi 5 dropdown menu not showing problem returns after a clean fix, treat the recurrence as its own bug rather than reapplying the same setting on autopilot. Clearing the value to inherit a default depends on the default surviving every future save. Setting an explicit high value is louder, uglier, and does not quietly evaporate. If yours comes back a third time, I would stop treating it as a settings bug and start looking at what writes to that template.

The broader lesson is the one I keep relearning, most recently while chasing an intermittent WooCommerce checkout failure: stop theorizing and get the browser to tell you a fact. Five theories cost me two afternoons. One hit test cost me four seconds and answered the question completely. The question "is my CSS wrong" has a hundred possible answers. The question "what is actually painted at this exact pixel" has one.

Sources

0 Comments

Submit a Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Post Search

Follow Us

Feel free to follow us on social media for the latest news and more inspiration.

Related Content