Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more

A dropdown that disappears at the edge of its card is almost never a z-index problem. It is a clipping problem, and a larger z-index cannot move the edge of an ancestor’s clipping box. The modern way out is to render the open menu in the browser’s top layer, which an ancestor’s overflow cannot clip. Below is why the menu gets cut off, how to confirm the culprit in DevTools, and which fix fits which situation.

Clipping and stacking are separate rules

Most people debugging a hidden dropdown reach for z-index first. That instinct is reasonable, because z-index is the property that decides which overlapping boxes appear on top. But it answers a different question from the one overflow answers. Stacking decides which eligible painted content sits above other content. Overflow decides where painting is cut off at an element’s edge. A menu can be the topmost item in its own stacking context and still be invisible, because the ancestor that contains it clips everything beyond its padding edge.

Question Controlled by What a wrong value looks like
Which box paints above another? z-index inside a stacking context A menu sits behind a sibling card
Is painting cut off at an edge? overflow on an ancestor (hidden, clip, auto, scroll) The menu is cropped at the bottom of a panel regardless of z-index
Where is the box placed? position and the nearest containing block position: fixed lands relative to a transformed ancestor instead of the viewport

If the menu is cropped, not covered, raising z-index is the wrong lever. Each stacking context also keeps its contents ordered within itself, so a high value on the menu does not let it escape its ancestor’s clip.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Find the clipping ancestor

Before choosing a fix, identify which ancestor is doing the clipping. In Chrome, Edge, or Firefox DevTools:

  1. Open DevTools and select the dropdown element in the Elements panel. Confirm that it exists in the DOM and that the menu’s visible area is cut short.
  2. In the Computed pane, check the overflow-x and overflow-y values on the menu’s parent, then on each ancestor above it.
  3. Look for hidden, clip, auto, or scroll on any ancestor. The first one whose value is clipping is a candidate.
  4. In the Styles pane, temporarily change the candidate’s overflow to visible. If the menu appears in full, that ancestor is the source. Revert the change afterward; this is a diagnostic step, not a fix.
  5. While you are in the chain, note any ancestor with transform, perspective, or filter set. These matter if you plan to use position: fixed, covered below.

What each overflow value does to a menu

MDN defines visible as the only value that lets overflowing content show outside the padding box. The other values all clip. They differ in whether the element becomes a scroll container and whether scripts can scroll it, which changes how a menu behaves when it is trapped inside.

Value Clips at the padding box or clip edge Creates a scroll container Allows programmatic scrolling What it means for a menu
visible No No Not applicable Overflow shows outside the padding box. This value is never the clipping source.
hidden Yes, at the padding box Yes Yes The menu is cropped. Hidden focusable content can still receive keyboard focus without being scrolled into view, which is an accessibility problem.
clip Yes, at the overflow clip edge, optionally extended by overflow-clip-margin No No The menu is cropped with no scroll behavior. Use it for clipping on purpose, not on interactive menus.
auto Yes Yes Yes Scrollbars appear only when content overflows, so the menu is cut into a scrollable area.
scroll Yes Yes Yes Scrollbars always appear, whether or not content overflows.

Two details trip people up. First, a single overflow keyword sets both axes, while two keywords apply the first to the horizontal axis and the second to the vertical axis. Second, the axes are linked: when one axis is set to a value other than visible or clip, a visible value on the other axis computes to auto. So overflow-x: visible next to overflow-y: hidden does not neutralize the clip. Check the computed values rather than assuming.

Do not switch a deliberately scrolling panel to overflow: visible without asking why it was constrained. That can remove the intended scroll area, expose content that layout depends on, or shift the page. If the ancestor must stay a scroll container, the menu has to leave that subtree or enter the top layer.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Why the top layer escapes the clip

An open HTML popover is placed in the top layer. The CSS Positioned Layout Module Level 4 draft, published by the CSS Working Group, describes the rendering rule directly: “This special rendering behavior ensures that elements in the top layer cannot be clipped by anything in the document, or obscured by anything except elements later in the top layer.” MDN states the practical consequence: an open popover is not influenced by a parent’s position or overflow. That is why a popover can show a menu that a plain absolutely positioned child cannot.

Fix 1: Render the menu as a popover

This is the central modern fix. The popover is an element with the popover attribute, and a button with popovertarget opens it without custom script.

  1. Mark up the trigger and the menu. Keep the menu in the same place in the DOM as before; the top layer handles the rendering.
    <button popovertarget='site-menu' id='menu-trigger'>Account</button>
    <div id='site-menu' popover='auto'>
      <ul>
        <li><a href='/profile'>Profile</a></li>
        <li><a href='/sign-out'>Sign out</a></li>
      </ul>
    </div>
  2. Override the browser’s default popover styling. By default an open popover is centered in the viewport and has its own border and padding, so reset what you do not want:
    #site-menu {
      margin: 0;
      padding: 0.5rem;
      border: 1px solid #ccc;
      background: #fff;
    }
  3. Test inside the clipping container. Open the menu while the panel is scrolled and while the container is at its narrowest width.

With popover='auto', the browser also closes the popover on Escape and on clicks outside it. A popover solves the layering problem, but it does not supply menu semantics, arrow-key navigation, or focus management. Those remain your responsibility.

Placing the popover against its trigger with CSS anchor positioning

A popover placed in the top layer still needs coordinates. The Popover API guide shows how to make the invoker the anchor, and CSS anchor positioning then places the popover relative to that trigger. Anchor positioning support is narrower than popover support, so confirm the browsers you must serve before relying on it.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
#menu-trigger {
  anchor-name: --menu-anchor;
}
#site-menu {
  position-anchor: --menu-anchor;
  position-area: bottom span-right;
  margin: 0;
  position-try-fallbacks: flip-block;
}

The flip-block fallback moves the menu above the trigger when there is no room below. If anchor positioning is unavailable in a target browser, the popover still escapes the clip, but its placement falls back to default positioning or to a small script that measures the trigger.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Fix 2: Move the menu out of the clipped subtree

When a popover is not an option, the common alternative is to render the menu at the document level, outside the clipped component, and position it with script. This works in every browser that supports the code you write, but it moves the cost into your application. You must recalculate position on scroll, resize, and layout changes, return the menu to the correct stacking order, and route clicks and keyboard events back to the trigger’s component. Framework portals are one way to do this. The standards sources behind the clipping rules do not prescribe a portal pattern, so treat it as an architectural trade-off to weigh against the top-layer option rather than a universal remedy.

Why position: fixed is not a guaranteed escape

Many articles suggest switching the menu to position: fixed. That works only under specific conditions:

  • An ancestor with transform, perspective, or filter becomes the containing block for fixed descendants, so the menu is positioned relative to that ancestor, not the viewport.
  • Clipping is still a separate issue. A fixed menu inside a clipping ancestor with no transform, perspective, or filter may be placed correctly yet still be cut off.
  • Top-layer elements have their own containing-block behavior, so a popover does not depend on this rule.

Trace the full ancestor chain before you rely on fixed positioning, and test scroll behavior with the panel scrolled.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Choosing a fix

Option Escapes a clipping ancestor Keeps the scroll container intact How the menu is positioned Browser baseline Who handles focus and keyboard behavior
Raise z-index only No Yes Unchanged Any browser Unchanged
Set the container to overflow: visible Yes No, the scroll area is removed Unchanged Any browser Unchanged
position: fixed on the menu Only without a transform, perspective, or filter ancestor Yes Viewport, or the transformed ancestor if one exists Any browser Your code
Open popover, default placement Yes Yes Default top-layer placement, centered until styled Check current MDN compatibility data for your target browsers Your code, with light dismiss and Escape from popover=’auto’
Open popover with CSS anchor positioning Yes Yes Relative to the trigger, with optional fallback placement Narrower than popover support; check current MDN compatibility data Your code
Render outside the clipped subtree Yes Yes Script-measured and synchronized Any modern browser Your code, plus event routing back to the trigger

For most new menus built on a trigger, start with an open popover and CSS anchor positioning if your browser set allows it. Reach for script-based rendering outside the subtree when you must support browsers without the top layer or when the menu’s logic depends on the component tree.

Accessibility and verification checklist

  • Choose the HTML control that matches the pattern. A popover container does not turn a list of links into a menu with arrow-key navigation.
  • If the pattern needs focus to move into the menu on open, move it in code, and return focus to the trigger on close.
  • Confirm that Escape closes the menu and that clicking outside it behaves as intended.
  • Avoid overflow: hidden around focusable menu items unless you also manage focus inside it, since hidden content can take focus without scrolling into view.
  • Test with the containing panel scrolled, at narrow widths, at high zoom, and in the browsers you support, since placement and support differ across them.

The sources behind these rules settle the clipping and top-layer behavior, but they do not define an accessibility pattern for your application. Check the menu against your own interaction requirements before publishing it as a reusable component.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.