NEWVersion 1.0 is here.
OpenTailwindv1.0
BlocksTemplatesCollectionsGuidesPricing
Why Your Dropdown Is Hidden: CSS z-index and Overflow Fixes
BlogWhy Your Dropdown Is Hidden: CSS z-index and Overflow Fixes
TutorialOctober 14, 2026·4 min read

Why Your Dropdown Is Hidden: CSS z-index and Overflow Fixes

Diagnose clipped dropdowns, stacking contexts, and viewport collisions with an interactive example and a practical fix checklist.

By OpenTailwind, by lindo.ai

On this page

  1. Start with the visible symptom
  2. See why z-index cannot fix clipping
  3. Understand stacking contexts before choosing a number
  4. Keep menus inside the screen
  5. Test the awkward positions

When a dropdown appears behind another element, inspect its stacking context. When it is cut off, inspect ancestor overflow. When it opens beyond the screen, inspect placement and viewport collisions. Increasing z-index addresses only part of the first problem; it does not solve clipping or calculate a better position.

Start with the visible symptom

SymptomLikely area to inspectFirst useful change
Menu behind a neighboring sectionAncestor stacking contextsCompare the ancestors, not only the menu’s z-index
Menu cut off at a container boundaryoverflow: hidden, auto, or clipRemove unnecessary clipping or render outside the clipped ancestor
Menu extends beyond the viewportAlignment, width, and collision handlingClamp width and use a positioning system that flips or shifts
Menu moves away while scrollingCoordinate system and scroll listenersUse a positioning library or recompute placement

See why z-index cannot fix clipping

Example setup: Tailwind CSS 4.1.18, compiled locally, with plain HTML and vanilla JavaScript. These small educational examples are separate from the membership library. Adapt them to your application and test your final content and browser requirements.

Original OpenTailwind educational example. Open the full-width demo.
Complete HTML, CSS, and JavaScript

Use your compiled Tailwind stylesheet in place of /examples/tailwind.css. The example uses Tailwind CSS 4 utilities and vanilla JavaScript.

<!doctype html>
<html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><meta name="robots" content="noindex,follow"><title>An overflow clip cannot be fixed with z-index</title><link rel="stylesheet" href="/examples/tailwind.css"><style>body{font-family:system-ui,sans-serif;background:#faf9f6;color:#252824;padding:24px}button{cursor:pointer}button:disabled{cursor:wait;opacity:.6}:focus-visible{outline:3px solid #4f46e5;outline-offset:4px}</style></head><body><button id="fix" aria-pressed="false" class="mb-5 rounded-lg bg-stone-900 px-4 py-2 text-white">Fix the clipping</button>
<div id="boundary" class="relative h-32 overflow-hidden rounded-xl border border-stone-300 bg-white p-4">
  <p class="text-sm text-stone-600">This container clips its children.</p>
  <div class="absolute top-16 right-4 z-50 w-56 rounded-xl border border-orange-200 bg-orange-50 p-5 shadow-lg"><strong>My dropdown</strong><p class="mt-2">A high z-index still cannot escape overflow: hidden.</p></div>
</div>
<p id="result" role="status" class="mt-20 text-sm">The menu is clipped.</p><script>const fix = document.querySelector('#fix');
const boundary = document.querySelector('#boundary');
fix.addEventListener('click', () => {
  const enabled = fix.getAttribute('aria-pressed') !== 'true';
  fix.setAttribute('aria-pressed', String(enabled));
  boundary.style.overflow = enabled ? 'visible' : 'hidden';
  fix.textContent = enabled ? 'Show the clipping' : 'Fix the clipping';
  document.querySelector('#result').textContent = enabled ? 'The menu is visible. In a real clipped scroller, use a portal instead.' : 'The menu is clipped.';
});</script></body></html>

The dropdown already has a high stacking value. The parent still clips everything outside its rectangle. Changing overflow makes the issue visible immediately. In an actual scrolling panel, removing overflow may break the design; a portal can move the floating content outside that boundary instead.

Understand stacking contexts before choosing a number

A stacking context groups descendants into a separate stacking unit. A child cannot use a large local z-index to outrank an unrelated ancestor’s position in the outer context. Positioned elements with a non-auto z-index, transforms, and opacity below one are examples of conditions that can establish a context. Use browser developer tools to inspect the ancestor chain rather than escalating values to 999999.

MDN’s stacking-context reference documents the other triggers. After removing an accidental context, check the whole page: the transform or opacity may have been serving a deliberate purpose.

Keep menus inside the screen

OpenTailwind’s editor exposed another common case: a toolbar can wrap at smaller widths, leaving a menu aligned against the wrong edge. The useful controls are alignment, collision padding, available height, and maximum width. They solve a placement problem without changing the visual design of the trigger.

For a React project using Radix Popover, a portalled content panel can use these properties. This is a fragment to place inside your existing Popover root, alongside its trigger:

<Popover.Portal>
  <Popover.Content
    align="start"
    sideOffset={8}
    collisionPadding={12}
    style={{
      width: 288,
      maxWidth: 'calc(100vw - 24px)',
      maxHeight: 'var(--radix-popover-content-available-height)',
      overflowY: 'auto',
    }}
  >
    {/* Your controls */}
  </Popover.Content>
</Popover.Portal>

A portal alone does not supply collision handling; the positioning implementation does. Follow the Radix Popover documentation for the package version in your project. Choose a menu primitive for a true application menu and a disclosure or navigation pattern for ordinary site links.

Test the awkward positions

  1. Open the panel near each viewport edge.
  2. Resize until the toolbar wraps to a second row.
  3. Try browser zoom and the longest option label.
  4. Scroll both the document and any nested containers.
  5. Use the keyboard to open, navigate, dismiss, and return focus.

For a simple site menu, our responsive navbar example provides a smaller starting point. For visual direction, explore the capsule header design.

Library access: Tutorials and their educational demos are public. Copying library designs requires an account: 100 selected blocks and five templates per industry are free. Pro lifetime access unlocks the complete library.

Keep building

Responsive Tailwind CSS Navbar: Working Menu and 5 Layouts ↗

Try a keyboard-operable responsive navbar, copy its HTML and JavaScript, and adapt five navigation layouts with clear implementation notes.

Tailwind CSS Success Notifications: Inline Status or Toast? ↗

Create a working success notification example with accessible status updates, honest save feedback, and practical toast guidance.

Tailwind CSS Skeleton Loading: A Working Example ↗

Build a skeleton loading state with a working demo, stable layout, reduced motion, accessible status updates, and error-state guidance.

Browse 1,761 Tailwind CSS blocks

100 free blocks, five free templates per industry, and Pro lifetime access to the complete block and template library.

Browse BlocksTemplates
← Previous article

Tailwind CSS Skeleton Loading: A Working Example

Next article →

Carousel vs Slider: Differences and Accessible Examples

OpenTailwindv1.0

A little less starting from scratch.
A lot more making it yours.

Made with care by lindo.ai

The library

All blocksAll templatesHero sectionsPricing sections

Around here

Our storyGuides & ideasDesign examplesMembership & pricingQuestions?

Good design is a
good place to start.

FREE TO EXPLORE. YOURS TO BUILD.
© 2026 OpenTailwind · by lindo.ai
TermsPrivacyCookies All creativity welcome