Why Your HTML Dropdown Menu Is Not Opening Properly (Causes & Fixes)

A dropdown that won’t open — or opens incorrectly — is almost always caused by a CSS conflict, a missing JavaScript event, or an overflow issue hiding the menu. This guide covers every real cause with working fixes.

If your HTML dropdown menu is not opening properly, you are dealing with one of the most common UI bugs in web development.

HTML dropdown menu is not opening properly

The dropdown might not open at all, it might flash briefly and disappear, it might open but get cut off by a parent element, or it might work on desktop but refuse to work on mobile. Each symptom points to a different cause — and each cause has a clear fix.

This guide covers every real reason an HTML dropdown menu fails to open, from simple CSS mistakes to JavaScript event issues to overflow clipping problems that confuse even experienced developers.

The :hover rule is missing or written incorrectly

CSS Issue

If you’re building a pure CSS dropdown, the most common reason it doesn’t open is a missing or incorrectly written :hover selector. The dropdown menu exists in the HTML but stays hidden because the CSS rule to reveal it is either absent, misspelled, or targets the wrong element.

A pure CSS dropdown works by hiding the menu by default and showing it when the parent is hovered. This requires exact selector structure:

Wrong — hover targets the menu itself, not the parent

Correct — hover the parent, show the child menu

And the matching HTML structure:

✓ Quick diagnostic
Right-click the dropdown button in your browser, choose Inspect, and look for the .dropdown-menu element in the HTML panel. In the Styles panel, check whether display: none is applied and whether hovering the parent toggles it. If the rule shows as crossed out, something is overriding it.

CSS Issue

A parent element has overflow: hidden or overflow: auto

This is one of the trickiest dropdown bugs because everything looks correct in your code — the CSS hover rule works, the JavaScript fires, the menu technically opens — but you can’t see it because a parent container is clipping it.

overflow: hidden on any ancestor will clip absolutely-positioned children, even when they sit outside the container’s visible bounds.

The dropdown menu appears to not open at all, when in reality it’s opening but being immediately cropped to zero height.

Causes clipping

Fixed

To diagnose this, open DevTools, select the dropdown menu element, and check the Computed styles for overflow. Then go up through each parent element in the HTML tree checking their overflow values. The culprit is usually a wrapper div you didn’t write yourself — like one added by a CSS framework.

⚠ overflow: auto causes the same problem

Both overflow: hidden and overflow: auto clip absolutely-positioned children. overflow: auto adds a scrollbar inside the container rather than clipping, but the dropdown menu still can’t escape the container’s bounds. overflow: scroll has the same effect.

CSS Issue

The dropdown opens but appears behind other elements

A z-index conflict is what happens when the dropdown opens correctly — it’s there, it has the right display value — but another element on the page is rendered on top of it, making it invisible or partially hidden. This commonly happens with sticky headers, modals, image sliders, or any positioned element with a higher z-index.

Dropdown hidden behind a sticky header

Give the dropdown a higher z-index

ℹ z-index only works on positioned elements
z-index has no effect unless the element also has a position value of relative, absolute, fixed, or sticky. Setting z-index: 9999 on an element with position: static does nothing — add position: relative to the dropdown menu first.

JavaScript Issue

JavaScript click handler is not attached to the button

If your dropdown relies on JavaScript to toggle open and close (which it should, for better accessibility and mobile support), a missing or incorrectly attached event listener means clicking the button does nothing at all.

Wrong — selector typo, listener never attaches

Correct — with null check to prevent errors

⚠ Script placement matters
If your <script> tag is in the <head> without a defer attribute, the JavaScript runs before the HTML elements exist in the DOM — so querySelector returns null and the event listener never attaches. Either move the script just before </body>, or add defer to the script tag: <script src="app.js" defer>.

JavaScript Issue

A JavaScript error is preventing the dropdown from working

If there’s a JavaScript error anywhere on your page — even in a completely unrelated script — it can stop the rest of your JavaScript from executing. This means your dropdown’s event listeners might never get attached, even if the dropdown code itself is perfectly correct.

Open the browser console (F12 → Console tab). If you see any red errors, those need to be fixed first. Common errors that silently kill dropdown functionality:

  • Uncaught TypeError: Cannot read properties of null — a querySelector returned null and the code tried to use it
  • Uncaught ReferenceError: X is not defined — a variable or function is used before it’s defined
  • Uncaught SyntaxError — a typo in JavaScript syntax stops the entire script from parsing

✓ Debugging step
Open DevTools → Console. Reload the page. Any red errors that appear on load are candidates for breaking your dropdown. Fix them top-to-bottom — often one root error causes a cascade of others, and fixing the first one clears everything.

CSS Issue

The dropdown container is missing position: relative

When a dropdown menu uses position: absolute to appear below the trigger button, it positions itself relative to the nearest positioned ancestor — an ancestor with position set to anything other than static. If no positioned ancestor exists, the menu positions itself relative to the whole page and appears in a completely unexpected location.

Menu flies to a random position on the page

Add position: relative to the parent

Mobile Issue

CSS :hover dropdowns don’t work on touchscreens

A dropdown that works perfectly on desktop but refuses to open on a phone or tablet almost always means the menu is triggered by CSS :hover alone. Touchscreens don’t have a hover state — a tap either fires a click event or triggers a brief hover that immediately closes when the finger lifts.

Trigger method Desktop mouse Touchscreen Keyboard
CSS :hover only ✓ Works ✗ Doesn’t work ✗ Doesn’t work
JS click event ✓ Works ✓ Works ✗ Needs extra work
JS click + focus ✓ Works ✓ Works ✓ Works

The fix is to switch from CSS-only hover to a JavaScript click-toggled approach, which works on all devices. The click handler example in section 4 covers this exactly. If you need to keep hover for desktop, you can combine both approaches:

CSS Issue

The CSS class toggle works but display: none is overridden

Your JavaScript correctly adds and removes an is-open class on the dropdown menu. You can see the class appearing in DevTools when you click the button. But the menu still doesn’t show. The likely cause: a more specific CSS rule is keeping display: none active even when the class is present.

Specificity conflict — .is-open rule loses

Match specificity or use !important on the open state

HTML / Accessibility

Keyboard focus and accessibility issues

If your dropdown opens with mouse hover or click but is inaccessible via keyboard — Tab key, Enter, Escape — it’s not technically broken, but it’s effectively broken for a significant portion of users. Proper ARIA attributes and keyboard handling are what separate a working dropdown from a good dropdown.

Quick cause-and-fix reference

Symptom Most Likely Cause Fix Difficulty
Nothing happens on hover Wrong :hover selector or missing CSS rule Easy
Nothing happens on click JS event listener not attached or selector typo Easy
Menu opens but is cut off overflow: hidden on a parent element Medium
Menu opens but hides behind content z-index too low or missing Easy
Menu appears in wrong location Parent missing position: relative Easy
Works on desktop, broken on mobile CSS :hover only — no touch support Medium
Class toggles but menu stays hidden CSS specificity conflict overriding open state Medium
Everything broken after adding script JS error earlier in page blocking execution Debug

Troubleshooting checklist

Work through this when your HTML dropdown menu is not opening properly:

  • Open DevTools → Console. Any red errors? Fix those first — a JS error anywhere on the page can stop your dropdown’s event listeners from attaching.
  • Inspect the dropdown menu element. Is display: none applied? When you hover or click, does it toggle to display: block? If not, the CSS hover rule or JS toggle isn’t working.
  • Check your CSS hover selector — it should be .dropdown:hover .dropdown-menu, not .dropdown-menu:hover.
  • Inspect all parent elements for overflow: hidden or overflow: auto — either will clip an absolutely-positioned dropdown menu.
  • Check z-index — is the dropdown menu getting a high enough value? Does the parent have position: relative?
  • Test on a real mobile device or browser DevTools mobile emulation. If it fails on touch, switch from CSS :hover to a JavaScript click toggle.
  • Check your <script> tag placement — if it’s in <head>, add defer or move it before </body>.
  • If JS toggles the class but the menu stays hidden, open DevTools Styles panel and look for a crossed-out rule — a more specific selector is overriding your open state.

Frequently Asked Questions

Why is my HTML dropdown menu not opening properly?

The most common causes are a missing or incorrect CSS :hover selector, a JavaScript event listener that isn’t attached to the button, a parent element with overflow: hidden clipping the menu, or a z-index conflict hiding it behind other elements. Open the browser console first — any red errors need to be fixed before diagnosing dropdown-specific issues.

My dropdown works on desktop but not on mobile. Why?

This almost always means the dropdown is triggered by CSS :hover only. Touchscreens don’t generate hover events — a tap either fires a click or triggers a brief hover that disappears immediately. Switch to a JavaScript click event handler to support all devices, or use the @media (hover: hover) media query to keep CSS hover for desktop while adding JS click handling for touch.

My dropdown opens but is cut off or hidden. What’s wrong?

A parent element has overflow: hidden or overflow: auto, which clips absolutely-positioned children. Open DevTools, inspect the dropdown menu element, then walk up through each parent checking for overflow values. Change the culprit to overflow: visible. If you added overflow to prevent content spillage, use padding instead.

My dropdown opens behind other elements. How do I fix z-index?

Set a high z-index on the dropdown menu — something like z-index: 9999 — and make sure the menu has a position value other than static (z-index only works on positioned elements). Also ensure the parent container has position: relative so the absolutely-positioned menu is anchored to it correctly.

My JavaScript class toggle works but the dropdown still doesn’t show. Why?

A CSS specificity conflict is probably overriding your open state. Open DevTools, click the dropdown menu element, and look at the Styles panel. If the display: block rule from your .is-open class appears crossed out, a more specific rule is winning. Either increase the specificity of your open-state selector, or switch from display to visibility and opacity for the toggle.

What is the correct HTML structure for a dropdown menu?

A reliable dropdown needs: a wrapper element with position: relative; a button (not a div) as the trigger with aria-expanded and aria-haspopup attributes; and a menu element with position: absolute and a high z-index. Use a <button> for the trigger, not a <div> or <span> — buttons are focusable by default, receive click events from keyboard Enter, and are properly announced by screen readers.

The bottom line

An HTML dropdown menu that isn’t opening properly is almost always a layering problem — either a CSS rule isn’t reaching the element, JavaScript isn’t wired up to the right element, or a parent container is visually blocking the menu from appearing where it should. The browser DevTools are your fastest diagnostic tool: check the console for JS errors first, then inspect the menu element’s computed styles to see exactly which CSS rules are winning.

The other important shift is moving away from CSS-only :hover dropdowns if you need mobile support. A JavaScript click toggle takes about ten extra lines of code and makes your navigation work correctly on every device, every input method, and every browser.

Leave 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.