Why Is My Tooltip Hidden Behind Other Elements?

Tooltip hidden behind elements problems usually happen when the tooltip is clipped by overflow, trapped in a stacking context, placed under a higher z-index element, or positioned relative to the wrong parent.

Tooltip Layer Fix

Why is my tooltip hidden behind other elements?

A tooltip can be coded correctly and still appear behind a card, header, image, dropdown, modal, or nearby section. The problem is rarely the text itself. It is usually a layout-layer problem: overflow:hidden, low z-index, stacking context, transformed parents, or a tooltip that is positioned inside the wrong container.

  • Tooltip z-index
  • Overflow clipping
  • Stacking context
  • Position absolute

What the bug looks like

The tooltip appears cut in half, shows under a card, disappears behind a header, or cannot escape its container.

Why it happens

Tooltips are floating UI, but they are often placed inside normal layout containers that clip or trap them.

What usually fixes it

Remove clipping from the parent, raise the tooltip layer, avoid stacking traps, or render the tooltip in a safer page-level layer.

Error 1

The tooltip is clipped by overflow:hidden

This is one of the most common tooltip bugs. The card needs rounded corners or image cropping, so it uses overflow:hidden. But the tooltip also lives inside that card, so the parent cuts it off.

Broken code

Parent clips tooltip
.card {
  position: relative;
  overflow: hidden;
}

.tooltip {
  position: absolute;
  bottom: 100%;
  z-index: 20;
}

Broken visual result

Tooltip gets cut off
Product card

The tooltip is inside a parent that clips anything outside the card.

Info This tooltip needs to escape the card, but overflow cuts it.
A higher z-index cannot fix clipping caused by parent overflow.

Correct code

Visible floating area
.card {
  position: relative;
  overflow: visible;
}

.tooltip {
  position: absolute;
  bottom: calc(100% + 8px);
  z-index: 20;
}

Fixed visual result

Tooltip can escape
Product card

The tooltip can float outside the card because the parent no longer clips it.

Info This tooltip can now appear above the card.
If the component must crop images, put the cropped image in its own wrapper instead of clipping the whole card.
Error 2

The tooltip has a lower z-index than nearby content

If the tooltip is not clipped but still appears behind another card, header, image, or panel, the problem is layer order. The tooltip needs to be above the nearby interactive content.

Broken code

Low tooltip layer
.tooltip {
  position: absolute;
  z-index: 2;
}

.feature-card {
  position: relative;
  z-index: 10;
}

Broken visual result

Another element paints above it
Pricing option

The tooltip is visible, but another content layer overlaps it.

Info Low z-index tooltip hidden by a card.
Feature card This layer is above the tooltip.
The tooltip is not clipped. It is simply behind a higher layer.

Correct code

Tooltip layer wins
.tooltip {
  position: absolute;
  z-index: 100;
}

.feature-card {
  position: relative;
  z-index: 1;
}

Fixed visual result

Tooltip above nearby content
Pricing option

The tooltip has a deliberate layer above nearby cards.

Info Tooltip layer is now above the card.
Feature card The card no longer covers the tooltip.
Use a controlled z-index scale instead of guessing random numbers.
Error 3

A transformed parent creates a stacking context trap

A tooltip can have z-index:9999 and still lose if it is inside a parent stacking context. Common triggers include transform, filter, opacity, isolation, and positioned parents with z-index.

Broken code

Tooltip trapped
.card {
  transform: translateZ(0);
  z-index: 1;
}

.card .tooltip {
  position: absolute;
  z-index: 9999;
}

Broken visual result

Huge z-index still loses
Transformed card

The tooltip is inside a lower stacking context.

Info Even z-index 9999 cannot escape this parent.
Page layer
z-index only competes inside the stacking context where the element lives.

Correct code

Move tooltip to safe layer
<body>
  <main class="page">...</main>
  <div class="tooltip-layer">...</div>
</body>

Fixed visual result

Tooltip escapes the trap
Transformed card

The component can stay transformed.

Info
Page layer
Tooltip is rendered in a safer page-level layer.
For complex UI, render floating elements in a dedicated layer outside transformed components.
Error 4

The tooltip is positioned relative to the wrong parent

position:absolute uses the nearest positioned ancestor. If the trigger is inside one element but the tooltip is positioned relative to another, the tooltip can appear in the wrong place and hide behind unrelated content.

Broken code

No local anchor
.tooltip-wrap {
  /* missing position: relative */
}

.tooltip {
  position: absolute;
  bottom: 100%;
  left: 0;
}

Broken visual result

Tooltip floats from wrong place
Tooltip anchored to the wrong ancestor.
Settings row

The trigger is here, but the tooltip is not anchored locally.

Info
Other content The tooltip can collide with this.
The tooltip may look hidden because it is not positioned where you think it is.

Correct code

Local tooltip anchor
.tooltip-wrap {
  position: relative;
  display: inline-flex;
}

.tooltip {
  position: absolute;
  bottom: calc(100% + 8px);
  left: 0;
  z-index: 100;
}

Fixed visual result

Tooltip anchored correctly
Settings row

The tooltip is positioned relative to the trigger area.

Info Tooltip is anchored to the right local parent.
Other content No longer fighting the tooltip.
Use a local wrapper for simple tooltips and a page-level layer for complex floating UI.
Premium pattern

A production-minded tooltip layer pattern

A stronger tooltip system separates normal layout from floating UI. Simple tooltips can use a local relative wrapper, but complex tooltips should use a dedicated high-level layer so cards, grids, overflow, and transforms do not trap them.

Premium code

Safe tooltip system
:root {
  --layer-tooltip: 1000;
}

.tooltip-anchor {
  position: relative;
  display: inline-flex;
}

.tooltip {
  position: absolute;
  left: 50%;
  bottom: calc(100% + 10px);
  z-index: var(--layer-tooltip);
  transform: translateX(-50%);
  max-width: min(260px, calc(100vw - 32px));
}

.card-media {
  overflow: hidden;
}

.card-body {
  overflow: visible;
}
/* For complex apps */
.tooltip-layer {
  position: fixed;
  inset: 0;
  z-index: var(--layer-tooltip);
  pointer-events: none;
}

.tooltip-layer .tooltip {
  position: absolute;
  pointer-events: auto;
}

Premium visual result

Floating layer, predictable result
Premium card

The card layout stays clean, and the tooltip has a predictable layer.

Info
Clean tooltip It floats above cards, grids, headers, and nearby sections.
Premium tooltip CSS does not depend on luck. It uses a clear anchor, safe overflow, and a controlled layer.

Fast practical rule

If a tooltip is hidden behind other elements, do not only increase z-index. First check whether the parent is clipping the tooltip with overflow:hidden. Then check stacking context, positioned ancestors, and whether the tooltip should live in a higher page-level layer.

Debug checklist

  • Inspect the tooltip and confirm it has a real position, usually position:absolute or position:fixed.
  • Check the parent container for overflow:hidden, overflow:auto, or overflow:clip.
  • Temporarily set the parent to overflow:visible to see if clipping is the cause.
  • Compare the tooltip z-index with nearby cards, headers, overlays, and dropdowns.
  • Look for stacking context creators like transform, filter, opacity, isolation, and positioned parents.
  • Make sure the tooltip is positioned relative to the intended wrapper.
  • Avoid placing app-level floating UI inside cards, sliders, or overflow-heavy layout wrappers.
  • Use a simple layer scale for tooltip, dropdown, header, modal, and overlay values.
Best first move Toggle parent overflow in DevTools. If the tooltip appears, you found the clipping parent.
Most common cause A card uses overflow:hidden for rounded corners and accidentally clips the tooltip.
Most sneaky cause A transformed parent traps the tooltip in a lower stacking context.
Better mindset Tooltips are floating UI. They should not be trapped by normal content layout.

Final takeaway

A tooltip hidden behind other elements is usually a layer and containment problem, not a text problem. The tooltip may be clipped by overflow, trapped in a stacking context, placed under another z-index layer, or positioned relative to the wrong parent.

Start with overflow, then inspect stacking context, then fix the tooltip’s layer strategy. For simple UI, a local relative wrapper can work. For complex UI, a dedicated tooltip layer is safer and easier to debug.

Want more fixes like this?

Browse more z-index, tooltip, overlay, and CSS debugging guides in the FrontFixer library.

Why Is My Modal Behind the Overlay?

Modal behind overlay problems usually happen when the overlay has a higher z-index than the modal, the modal is trapped inside a stacking context, or the modal and overlay are placed in the wrong HTML structure.

Modal z-index Fix

Why is my modal behind the overlay?

A modal behind overlay bug is one of the most confusing CSS problems because the modal exists, the overlay exists, and the code looks almost right. But visually, the dark overlay sits above the modal, the popup looks faded, or the modal cannot be clicked. The real issue is usually layer order: z-index, stacking context, position, transform, or where the modal is placed in the HTML.

  • Modal z-index
  • Overlay layer
  • Stacking context
  • Click blocking

What the bug looks like

The modal appears dim, sits under the dark background, cannot be clicked, or looks like it opens behind the page.

Why it happens

The overlay and modal are not in the right stacking order, or the modal is trapped inside a lower stacking context.

What usually fixes it

Put the overlay and modal in one predictable layer system, then make the modal layer higher than the overlay.

Error 1

The overlay has a higher z-index than the modal

This is the simplest version of the bug. The overlay is placed above the page, but the modal is not placed above the overlay. The result is a popup that looks hidden, darkened, or unclickable.

Broken code

Overlay wins
.overlay {
  position: fixed;
  inset: 0;
  z-index: 1000;
}

.modal {
  position: fixed;
  z-index: 50;
}

Broken visual result

Modal is under overlay
Page content
behind Modal

The popup is lower than the overlay layer.

The modal exists, but the overlay paints above it and steals the visual focus.

Correct code

Modal wins
.overlay {
  position: fixed;
  inset: 0;
  z-index: 1000;
}

.modal {
  position: fixed;
  z-index: 1001;
}

Fixed visual result

Modal above overlay
Page content
above Modal

The popup is now above the overlay layer.

The modal layer must be higher than the overlay layer.
Error 2

The modal is trapped inside a stacking context

A modal can have a huge z-index and still lose if it is inside a parent stacking context. A transformed parent, filtered parent, or positioned parent with its own z-index can trap the modal below the page overlay.

Broken code

Trapped modal
.card {
  transform: translateZ(0);
  z-index: 1;
}

.card .modal {
  position: fixed;
  z-index: 9999;
}

Broken visual result

Huge z-index still loses
Transformed parent
trapped Modal

The modal is inside a lower parent context.

A huge z-index cannot escape a parent stacking context.

Correct code

Page-level modal
<body>
  <main class="page">...</main>

  <div class="overlay"></div>
  <div class="modal">...</div>
</body>

Fixed visual result

Modal escaped the trap
Page card
page level Modal

The modal is a sibling of the overlay at page level.

Place app-level overlays and modals near the end of the body or in a portal/root layer.
Error 3

The modal has z-index, but no useful positioning

Developers often add z-index to a modal and expect it to jump above everything. But if the element is not positioned or not participating in a stacking order that accepts z-index, the value may not solve the layer problem.

Broken code

z-index without position
.overlay {
  position: fixed;
  inset: 0;
  z-index: 20;
}

.modal {
  z-index: 100;
}

Broken visual result

Layer rule incomplete
Page content
incomplete Modal

The modal layer is not defined clearly.

z-index alone is not a complete modal positioning system.

Correct code

Positioned modal layer
.overlay {
  position: fixed;
  inset: 0;
  z-index: 20;
}

.modal {
  position: fixed;
  inset: auto;
  z-index: 30;
}

Fixed visual result

Position and layer agree
Page content
defined Modal

The modal is positioned and layered above the overlay.

For modals, define both placement and layer order explicitly.
Error 4

The HTML order makes the overlay cover the modal

When two positioned elements are in the same stacking level, later elements can paint above earlier elements. If the overlay is inserted after the modal and both use similar z-index values, the overlay may cover the modal.

Broken code

Overlay after modal
<div class="modal">...</div>
<div class="overlay"></div>

Broken visual result

DOM order fights layer order
Page content
covered Modal

The overlay is inserted after this layer.

When layers are not explicit, DOM order can make the overlay paint above the modal.

Correct code

Explicit layer order
<div class="overlay"></div>
<div class="modal">...</div>

Fixed visual result

Overlay below modal
Page content
top layer Modal

The modal is inserted and layered above the overlay.

Use clear z-index values and sensible HTML order for overlay systems.
Premium pattern

A production-minded modal layer pattern

A reliable modal system uses named layer values, keeps modal and overlay close together in the DOM, and avoids placing modals inside transformed cards, sliders, headers, or small layout wrappers.

Premium code

Predictable modal stack
<div class="modal-root">
  <div class="modal-overlay"></div>

  <section class="modal-dialog" role="dialog" aria-modal="true">
    ...
  </section>
</div>
:root {
  --layer-overlay: 1000;
  --layer-modal: 1010;
}

.modal-overlay {
  position: fixed;
  inset: 0;
  z-index: var(--layer-overlay);
  background: rgba(15, 23, 42, .64);
}

.modal-dialog {
  position: fixed;
  left: 50%;
  top: 50%;
  z-index: var(--layer-modal);
  transform: translate(-50%, -50%);
  width: min(100% - 32px, 480px);
}

Premium visual result

Modal system, not z-index guessing
Page content
clean layer Modal dialog

The overlay and dialog have predictable, named layers.

Premium modal CSS avoids random z-index numbers and makes the layer order obvious.

Fast practical rule

If your modal is behind the overlay, compare the overlay layer and the modal layer first. Then inspect the modal’s parents for stacking context traps like transform, opacity, filter, isolation, and positioned wrappers.

Debug checklist

  • Inspect the overlay and modal in DevTools and compare their computed z-index values.
  • Make sure both overlay and modal have a real position, usually position:fixed.
  • Keep the modal z-index higher than the overlay z-index.
  • Check whether the modal is inside a transformed, filtered, or positioned parent.
  • Move app-level modals near the end of the document or into a dedicated modal root.
  • Avoid random values like z-index:999999; use a small layer scale instead.
  • Check whether the overlay is stealing clicks with pointer-events.
  • Verify that the modal is not inside a header, slider, card, or overflow-hidden wrapper.
Best first move Temporarily lower the overlay z-index. If the modal appears, the issue is layer order.
Most common cause The overlay has a higher z-index than the modal.
Most sneaky cause A parent with transform traps the modal inside a lower stacking context.
Better mindset A modal should be a page-level layer, not a child of whatever section opened it.

Final takeaway

A modal behind overlay problem is usually not fixed by throwing a bigger z-index at the modal. The real fix is to understand which stacking context the modal belongs to and whether the overlay is above it.

Place the overlay and modal in a predictable page-level layer, give the overlay a lower layer than the modal, and avoid trapping the modal inside transformed or overflow-heavy parents.

Want more fixes like this?

Browse more z-index, overlay, and CSS debugging guides in the FrontFixer library.

Fix z-index not working

z-index usually stops working when the element is not being compared in the layer system you think it is. The fix is rarely a bigger number. The real fix is checking positioning, stacking context, overflow clipping, and parent structure.

CSS Layering Fix

Why Is My z-index Not Working?

z-index can feel broken when a dropdown hides behind a section, a modal appears under a header, or a tooltip disappears even with a huge value. But the browser is usually following CSS stacking rules correctly. The problem is almost always the context around the element, not the number itself.

  • CSS stacking context
  • Dropdown and modal bugs
  • Overflow and parent layer issues

What the bug looks like

A dropdown hides under another section, a modal appears behind a header, a tooltip gets cut off, or a sticky element refuses to sit above the page.

Why it happens

z-index only compares elements within stacking rules. A parent can trap the child inside a lower layer, so a huge number does not always win.

What fixes it

Add the right positioning, inspect parent stacking contexts, remove accidental clipping, and move important overlays to a safer layer when needed.

The simple rule behind z-index bugs

z-index is not one global ladder where the biggest number always wins. It works inside stacking contexts. A stacking context is like a small private layer system inside the page.

This means a child with z-index:9999 can still appear behind another element if the child is trapped inside a parent stacking context that sits lower than a different parent.

The fastest fix is usually not z-index:999999. The fastest fix is finding which parent is controlling the layer battle.

Error 1

The element has z-index but no positioning

This is the first thing to check. In many real layouts, z-index is expected to work on an element that has no positioning context. Add positioning intentionally before assuming the layer value is broken.

Broken code

No positioning
.overlay {
  z-index: 9999;
}

Broken visual result

Number exists, layer does not win
Page section This section still appears above the overlay.
Overlay z-index alone is not a reliable setup.

Correct code

Positioned layer
.overlay {
  position: relative;
  z-index: 20;
}

Fixed visual result

Element can now layer correctly
Page section This section is now behind the overlay.
Overlay Positioning gives the z-index a useful layer role.
Error 2

The dropdown is behind another section

Dropdowns often fail because the dropdown layer is lower than a nearby section, header, or card. The fix is not always a giant value. It is making the parent and dropdown layering intentional.

Broken code

Wrong layer order
.nav {
  position: relative;
  z-index: 1;
}

.dropdown {
  position: absolute;
  z-index: 1;
}

.hero {
  position: relative;
  z-index: 5;
}

Broken visual result

Dropdown loses the layer battle
Navigation
Products
Pricing
Docs
Next section covers it

Correct code

Intentional layer
.nav {
  position: relative;
  z-index: 30;
}

.dropdown {
  position: absolute;
  z-index: 40;
}

.hero {
  position: relative;
  z-index: 1;
}

Fixed visual result

Dropdown is above the content
Navigation
Next section stays behind
Products
Pricing
Docs
Error 3

A parent stacking context traps the child

This is the bug that makes developers angry. A child has z-index:9999, but it still appears behind another element because its parent is inside a lower stacking context.

Broken code

Trapped child
.parent-a {
  position: relative;
  z-index: 1;
}

.child {
  position: absolute;
  z-index: 9999;
}

.parent-b {
  position: relative;
  z-index: 2;
}

Broken visual result

9999 is trapped inside parent A
Parent A z-index:1
Child z-index:9999
Parent B z-index:2

Correct code

Fix parent order
.parent-a {
  position: relative;
  z-index: 5;
}

.child {
  position: absolute;
  z-index: 10;
}

.parent-b {
  position: relative;
  z-index: 2;
}

Fixed visual result

The parent layer now wins
Parent B z-index:2
Parent A z-index:5
Child z-index:10
Error 4

The element is clipped by overflow, not hidden by z-index

Sometimes the element is not behind anything. It is being cut off by a parent with overflow:hidden, overflow:auto, or another clipping behavior. That is a different bug.

Broken code

Clipped overlay
.card {
  position: relative;
  overflow: hidden;
}

.tooltip {
  position: absolute;
  top: 100%;
  left: 0;
  z-index: 9999;
}

Broken visual result

Tooltip is cut off

Card with overflow hidden

The tooltip exists, but the parent clips it.

Tooltip z-index:9999, still clipped.

Correct code

Visible overlay
.card {
  position: relative;
  overflow: visible;
}

.tooltip {
  position: absolute;
  top: calc(100% + 8px);
  left: 0;
  z-index: 20;
}

Fixed visual result

Tooltip can escape

Card with visible overflow

The overlay is allowed to appear outside.

Tooltip is visible now.
Error 5

A transform creates a new stacking context

A parent with transform can create a new stacking context. This often happens when people add transform:translateZ(0), animation helpers, GPU tricks, or subtle transform effects.

Broken code

Transform trap
.wrapper {
  position: relative;
  transform: translateZ(0);
  z-index: 1;
}

.menu {
  position: absolute;
  z-index: 9999;
}

.panel {
  position: relative;
  z-index: 2;
}

Broken visual result

Transform created a layer trap
Transformed parent z-index:1
Menu z-index:9999
Neighbor layer z-index:2

Correct code

Avoid accidental context
.wrapper {
  position: relative;
}

.menu {
  position: absolute;
  z-index: 30;
}

.panel {
  position: relative;
  z-index: 1;
}

Fixed visual result

The overlay layer is free
Wrapper no longer traps the menu
Neighbor stays behind
Menu layer works predictably

Fast practical rule

If z-index is not working, stop increasing the number and inspect the parent chain. The bug is usually positioning, stacking context, overflow clipping, or a parent with a property that created a new layer system.

Recommended baseline

Layering foundation

Use small, intentional z-index values and create a clear layer scale instead of throwing giant numbers at every bug.

:root {
  --layer-base: 1;
  --layer-dropdown: 20;
  --layer-sticky: 30;
  --layer-modal: 40;
  --layer-toast: 50;
}

.nav {
  position: relative;
  z-index: var(--layer-sticky);
}

.dropdown {
  position: absolute;
  z-index: var(--layer-dropdown);
}

.modal {
  position: fixed;
  inset: 0;
  z-index: var(--layer-modal);
}

.toast {
  position: fixed;
  right: 16px;
  bottom: 16px;
  z-index: var(--layer-toast);
}

Why this baseline helps

It avoids number chaos You do not need 999999 everywhere when the layer system is planned.
It makes intent obvious A dropdown, modal, sticky bar, and toast each get a predictable role.
It exposes real bugs faster When the scale is clear, a broken layer usually points to parent context or overflow.
It is easier to maintain Future changes become safer because the site has a known layering order.

Debug checklist

  • Check whether the element has position:relative, absolute, fixed, or sticky.
  • Inspect the parent chain for transform, opacity, filter, perspective, isolation, contain, or will-change.
  • Check whether a parent has overflow:hidden, overflow:auto, or another clipping rule.
  • Confirm whether the issue is true layering or visual clipping.
  • Compare parent stacking contexts, not only child z-index values.
  • Avoid escalating from z-index:10 to 999999 without checking structure.
  • For modals and app-wide overlays, consider placing them near the end of the document or inside a dedicated layer root.
  • Use a simple layer scale for dropdowns, sticky elements, modals, and toasts.
Best first move Add positioning intentionally and inspect the parent chain before changing the z-index number again.
Most common false fix Using z-index:999999 while the element is trapped inside a lower parent context.
Most overlooked cause overflow:hidden makes many people think z-index is failing when the element is actually clipped.
Better mindset z-index is not a power contest. It is a relationship between positioned elements, parent contexts, and layer order.

When absolute positioning is the real problem

If an element is not only behind something but also appears in the wrong place, the issue may be absolute positioning. The element may be anchored to the wrong parent.

In that case, read Why is my absolute positioned element in the wrong place?.

When a dropdown is being cut off

If a menu or dropdown disappears at the edge of a card, section, slider, or container, the issue may be clipping rather than layer order.

In that case, read Why is my dropdown getting cut off?.

When fixed headers cover content

A fixed header can create another layer problem when it sits above content, anchors, modals, or dropdowns in unexpected ways.

If your sticky or fixed header is involved, read Why is my fixed header covering content?.

When overflow creates side effects

Overflow bugs can look like z-index bugs because they change what is visible on screen. But the solution is usually different.

If you are fighting overflow too, read Fix overflow causing horizontal scroll.

FrontFixer Live Inspector

Test the layer stack before raising the z-index again.

When a dropdown, tooltip, overlay, or modal sits behind another element, the problem is not always the number itself. Paste a simplified layer example into the FrontFixer Live Inspector and check whether positioning, stacking context, overflow clipping, or a transformed parent is controlling the result.

The Live Inspector helps you test the visible behavior first, then move the safer CSS pattern into your real project only after you understand why the layer failed.

Final takeaway

When z-index is not working, the browser is usually not ignoring you. It is following stacking context rules that are easy to miss.

Start with positioning. Then inspect parent stacking contexts, overflow clipping, transformed wrappers, and the order of parent layers. Once the real layer system is clear, z-index becomes predictable again.

A clean parent structure beats a giant z-index number almost every time.

Need more CSS fixes?

Browse the CSS cluster or jump back to the full FrontFixer library to keep debugging faster.