Why Does My Overlay Not Cover the Whole Page?

Overlay not covering whole page bugs happen when an overlay is sized to a parent, placed under a header, trapped in a scroll area, or mounted in the wrong layer.

CSS Overlay Fix

Why Does My Overlay Not Cover the Whole Page?

An overlay not cover whole page bug usually means the overlay is not actually sized or layered against the full viewport. It may be positioned inside a parent, limited by a grid column, trapped under a sticky header, clipped by a scroll container, or using height:100% when the page needs viewport-based sizing.

This is one of those bugs that looks simple but can destroy the feel of a page. A backdrop that only covers half the screen makes the modal feel broken. A menu overlay that stops under the header feels unfinished. A loading overlay that covers only one section can confuse users about what is actually disabled.

  • overlay
  • fixed inset
  • viewport coverage
  • z-index layers

Test viewport ownership first

Temporarily change the overlay to position:fixed; inset:0; and move it near the end of the body or into a root overlay layer. If it suddenly covers the whole page, the original overlay was attached to the wrong parent or layer.

Related: Try this in the FrontFixer Live Inspector.

Open Live Inspector

What the bug looks like

The backdrop, loading screen, menu layer, or dimmed area covers only part of the page.

Why it happens

The overlay is filling a parent, section, grid column, or scroll container instead of the viewport.

What usually fixes it

Use a fixed root overlay with inset:0 and a clear z-index layer.

Why overlays fail to cover the full viewport

An overlay is supposed to communicate control. When a modal opens, a menu slides out, or a loading state appears, users expect the affected area to be obvious. If the overlay only covers the component, the main column, or the area below the header, the interface sends mixed signals.

The overlay not cover whole page problem usually comes from mixing local layout rules with global UI intent. A card overlay can be local. A full-page modal backdrop should not be local. A section loading shimmer can belong inside one section. A global loading lock should belong to the viewport.

The clean fix is to decide the overlay’s job first. If it should cover the whole page, mount it in a root layer and size it to the viewport. If it should cover only one card, keep it inside that card intentionally.

Local overlayGood for cards, sections, and small loading states.
Global overlayNeeded for modals, drawers, menus, and page locks.
Viewport sizingfixed plus inset:0 is the safe baseline.
Better mindsetCoverage is a layout decision, not decoration.
Error 1

The overlay uses height:100% inside a short parent

height:100% does not automatically mean the full page. It means the height of the containing block. If the parent is only a card, section, or wrapper, the overlay will only cover that parent.

Broken code

Parent-sized overlay
.section {
  position: relative;
}

.overlay {
  position: absolute;
  width: 100%;
  height: 100%;
}

Broken visual result

Only covers parent
Page header
Overlay only fills section
The overlay is doing exactly what the CSS says: it fills the parent, not the viewport.

Correct code

Viewport overlay
.overlay {
  position: fixed;
  inset: 0;
  width: auto;
  height: auto;
  z-index: 1000;
}

Fixed visual result

Covers viewport
Page still exists below
Overlay covers the whole viewport area
Use fixed inset when the overlay is supposed to cover the page.
Error 2

The header stays above the overlay

Sometimes the overlay covers most of the page but the sticky header remains visible. That usually means the header has a higher z-index or the overlay is mounted below a layer system that the header already owns.

Broken code

Overlay below header
.header {
  position: sticky;
  z-index: 100;
}

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

Broken visual result

Header leaks through
Overlay behind header layer
Sticky header still clickable
The overlay covers the viewport but loses the stacking battle to the header.

Correct code

Overlay above page chrome
:root {
  --z-header: 100;
  --z-overlay: 1000;
}

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

Fixed visual result

Overlay owns top layer
Header below overlay
Overlay is above header and page content
Give overlay layers a clear z-index token above normal page chrome.
Error 3

The overlay is trapped inside a scroll container

A scrollable parent can make an overlay cover only the visible panel or scroll with the content. This is common in dashboards, drawers, sidebars, tables, and app layouts with internal scrolling.

Broken code

Overlay inside scroll panel
.panel {
  max-height: 500px;
  overflow: auto;
  position: relative;
}

.panel .overlay {
  position: absolute;
  inset: 0;
}

Broken visual result

Panel-sized overlay
Overlay trapped in scroll panel
The overlay belongs to the scroll panel, so it cannot behave like a page overlay.

Correct code

Root overlay outside scroll
.panel {
  max-height: 500px;
  overflow: auto;
}

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

Fixed visual result

Root overlay ignores scroll
Overlay root covers full panel and page
The scroll panel can remain scrollable while the overlay sits outside it.
Error 4

The overlay is mounted inside the main grid column

In two-column layouts, the overlay may be placed inside the main content column instead of a page-level root. It then covers only the article area while the sidebar, header, or other page regions remain uncovered.

Broken code

Overlay inside main column
.layout {
  display: grid;
  grid-template-columns: 1fr 280px;
}

.main .overlay {
  position: absolute;
  inset: 0;
}

Broken visual result

Sidebar uncovered
Sidebar still exposed
Overlay only covers main column
The overlay is mounted in the main column, so the sidebar remains outside the covered area.

Correct code

Overlay outside layout grid
.layout {
  display: grid;
  grid-template-columns: 1fr 280px;
}

.page-overlay {
  position: fixed;
  inset: 0;
}

Fixed visual result

Whole layout covered
Sidebar below overlay
Overlay root covers the full page layout
Mount global overlays beside the layout grid, not inside one grid column.
Premium patterns

Three production-minded overlay coverage patterns

Premium overlay systems define coverage, scroll behavior, and layer order on purpose. Below are three different visual patterns so the overlay architecture does not become a repeated template.

Premium code example 1

Full-page overlay stack
:root {
  --z-header: 100;
  --z-backdrop: 900;
  --z-dialog: 1000;
}

.overlay-root {
  position: fixed;
  inset: 0;
  z-index: var(--z-backdrop);
}

.dialog {
  position: fixed;
  z-index: var(--z-dialog);
}

Premium visual result 1

Layer order blueprint
premium
Overlay stack above page chrome

The header stays in the app layer while backdrop and dialog own the overlay layer.

dialog backdrop header page
No exposed page zones
Pattern 1 is ideal for modal backdrops, confirmation dialogs, and blocking page states.

Premium code example 2

Mobile viewport overlay
.mobile-overlay {
  position: fixed;
  inset: 0;
  min-height: 100dvh;
  overflow: auto;
}

.mobile-overlay__panel {
  width: min(420px, 100%);
  min-height: 100dvh;
}

Premium visual result 2

Mobile coverage map
premium
Mobile overlay respects dynamic viewport

The overlay uses viewport units and internal scrolling instead of depending on page height.

100dvh overlay
fixed inset mobile viewport internal scroll safe coverage
Pattern 2 is ideal for mobile menus, drawers, checkout steps, and full-screen filters.

Premium code example 3

Local vs global overlay tokens
.card-overlay {
  position: absolute;
  inset: 0;
}

.page-overlay {
  position: fixed;
  inset: 0;
}

.is-page-locked {
  overflow: hidden;
}

Premium visual result 3

Coverage decision system
premium
Choose coverage before styling

The component can use a local overlay, while the app can use a global overlay root.

Card stateabsolute inset
Page statefixed inset
Locked statebody scroll off
Pattern 3 is ideal for design systems that need both section overlays and full-page overlays.

Fast practical rule

If the overlay should cover the whole page, use position:fixed, inset:0, and a root overlay layer. Do not rely on height:100%, main-column placement, or a local parent unless the overlay is intentionally local.

Debug checklist

  • Check whether the overlay is absolute or fixed.
  • Replace width and height rules with inset:0 for full-page overlays.
  • Inspect whether the overlay is mounted inside a card, section, grid column, or scroll container.
  • Compare the overlay z-index against sticky headers, menus, drawers, and modals.
  • Look for parent overflow:hidden or overflow:auto.
  • Use a root overlay layer for modals, page locks, loading screens, and menus.
  • Use local overlays only for local card or section states.
  • Test mobile viewport height with address bars and long content.
Best first moveTry position:fixed; inset:0 and retest coverage.
Most common causeThe overlay is filling a parent instead of the viewport.
Most sneaky causeThe header has a higher z-index than the overlay.
Better mindsetChoose local or global coverage before styling the overlay.

When a partial overlay is correct

Partial overlays are not always wrong. A card loading state, image hover layer, table blocker, or local section skeleton can correctly cover only one component. The problem begins when the overlay is meant to block the page but is mounted like a local component.

Use local overlays for local states. Use global overlays for global states. That simple separation prevents most coverage bugs before they appear.

This also keeps the article intent clean: this fix is about coverage area, not a generic modal bug or a generic z-index bug. The main question is whether the overlay owns the viewport or only owns a component.

The authority move is not to make every overlay full-screen. The authority move is to make the coverage match the user’s expectation.

Why this bug feels so visible

Users do not need to understand CSS to feel when an overlay is wrong. They see uncovered areas, clickable headers, floating sidebars, or page content that should be disabled but still looks active. That visual mismatch creates distrust quickly.

A correct overlay makes the interface state obvious. It tells users whether the whole page is blocked, one section is loading, or a focused dialog needs attention.

Final takeaway

An overlay not cover whole page bug usually happens because the overlay is local while the design expects it to be global. The CSS may be filling a parent, grid column, scroll panel, or lower z-index layer instead of the viewport.

Use a root overlay layer, position:fixed, inset:0, and clear z-index tokens when the whole page must be covered. Keep partial overlays only when the component itself is the intended coverage area.

Want more fixes like this?

Browse more CSS overlay, z-index, fixed positioning, modal, dropdown, and responsive layout debugging guides in the FrontFixer library.

Why Does My Modal Stay Trapped Inside a Parent?

Modal trapped inside parent bugs happen when a dialog is mounted inside a clipped, transformed, scrolling, or locally positioned component.

CSS Overlay Fix

Why Does My Modal Stay Trapped Inside a Parent?

A modal trapped inside parent usually means the dialog is not living in a true page-level overlay layer. The modal may be nested inside a card, section, scroll container, tab panel, transformed wrapper, or component with overflow:hidden. When that happens, the modal can get clipped, appear too small, sit behind nearby UI, or fail to cover the page.

This is not the same as a normal modal z-index mistake. A bigger z-index may not fix it because the modal is still inside the wrong parent. The parent controls the visual boundary, stacking context, scroll area, or positioning context. The modal is trying to act global while the HTML structure says it is local.

  • modal
  • parent boundary
  • overflow hidden
  • overlay root

Test the parent boundary first

Temporarily move the modal markup outside the component in DevTools, or remove parent rules like overflow:hidden, transform, and position:relative. If the modal suddenly covers the page correctly, the parent was the trap.

Related: Try this in the FrontFixer Live Inspector.

Open Live Inspector

What the bug looks like

The modal opens, but it stays trapped inside a card, panel, section, sidebar, or scrollable component.

Why it happens

The modal is mounted inside a parent that controls clipping, positioning, scrolling, or stacking.

What usually fixes it

Move the modal to a root overlay layer and keep only the trigger inside the component.

Why a modal can be trapped by its own component

A modal looks like it should belong to the whole page, but the browser does not guess that intention. The browser follows the DOM and CSS. If the modal element is placed inside a product card, tab panel, sidebar widget, carousel slide, or article section, it still has to deal with that parent’s layout rules.

A modal trapped inside parent often starts as a convenience decision. The developer places the modal markup right beside the button that opens it. That feels organized, but it can make a global overlay depend on a local component. If the component has clipping, transform, scroll, or a local stacking context, the modal inherits that problem.

The cleaner architecture is to keep the trigger local and the dialog global. The button can live inside the card. The modal root should usually live outside the card, near the end of the document or inside a dedicated overlay root.

Local trigger is fineThe button belongs inside the component.
Global dialog needs rootThe overlay should not depend on the card boundary.
Parent rules matterOverflow, transform, position, and scroll can all trap it.
Better mindsetKeep component UI local and page overlays global.
Error 1

The modal is inside a card with overflow hidden

Cards often use overflow:hidden to clip rounded corners, images, badges, or hover effects. If the modal is nested inside that card, the card can clip the modal even when the modal has a huge z-index.

Broken code

Modal inside clipped card
.product-card {
  position: relative;
  overflow: hidden;
}

.product-card .modal {
  position: absolute;
  inset: 0;
  z-index: 9999;
}

Broken visual result

Card clips modal
Modal stuck inside card
The modal is clipped by the same card that clips its image corners.
The modal is high, but the parent boundary is stronger than the child’s intent.

Correct code

Modal root outside card
.product-card {
  overflow: hidden;
}

.modal-root .modal {
  position: fixed;
  inset: 0;
  z-index: 1000;
}

Fixed visual result

Root modal covers page
Card stays clipped
Modal root owns the viewport
Leave card clipping on the card, but mount the modal outside the card.
Error 2

The modal is absolute inside a small section

A modal that uses position:absolute may use the nearest positioned parent as its reference. If that parent is a small section or tab panel, the modal covers only that local area instead of the full page.

Broken code

Absolute modal in section
.settings-panel {
  position: relative;
}

.settings-panel .modal {
  position: absolute;
  inset: 0;
}

Broken visual result

Only covers local panel
Settings panel parent
Page still visible
Modal only fills section
The modal is positioned against the section, not the viewport.

Correct code

Fixed modal in root
.settings-panel {
  position: relative;
}

.modal-root .modal {
  position: fixed;
  inset: 0;
  z-index: 1000;
}

Fixed visual result

Covers the viewport
Settings panel stays local
Page content
Fixed modal covers the whole browser area
Use a root fixed modal when the dialog should block the full page.
Error 3

The modal is inside a scroll container

Scroll containers are common in dashboards, sidebars, and app panels. If the modal lives inside one of those scroll areas, the overlay can scroll with the content or be limited to that container’s height.

Broken code

Modal inside scroll area
.panel-body {
  max-height: 420px;
  overflow: auto;
}

.panel-body .modal {
  position: absolute;
}

Broken visual result

Scroll area traps overlay
Modal scrolls inside panel
The dialog is limited by the same scroll container as the panel content.

Correct code

Panel scroll separated
.panel-body {
  max-height: 420px;
  overflow: auto;
}

.modal-root .modal {
  position: fixed;
  inset: 0;
}

Fixed visual result

Modal ignores panel scroll
Root modal sits above panel
Panel content can scroll, but the page-level modal should not be trapped inside it.
Error 4

The modal is owned by a reusable component

Reusable components often keep their markup self-contained. That can be convenient, but a modal that must cover the whole interface should not always be owned by the same component that opens it.

Broken code

Dialog inside component
<Card>
  <button>Open modal</button>
  <Modal />
</Card>

Broken visual result

Component owns dialog
Card component
Trigger Local state
Modal trapped
Neighbor UI
Still wins Local layers
The modal is packaged inside the component, so it inherits component boundaries.

Correct code

Trigger local, modal global
<Card onOpen={openModal} />

<ModalRoot>
  <Modal />
</ModalRoot>

Fixed visual result

Modal root owns dialog
Card component
Trigger only No overlay trap
Modal root
Backdrop Dialog
Global modal
The component opens the modal, but the root layer owns the modal’s layout.
Premium patterns

Two production-minded modal architecture patterns

Premium modal architecture separates trigger ownership from overlay ownership. Below are two different premium patterns: a layer-cake overlay map and a portal routing system.

Premium code example 1

Root overlay layer
<main class="app">
  <ProductCard />
</main>

<div id="modal-root"></div>

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

.modal-dialog {
  position: fixed;
  z-index: var(--z-modal);
}

Premium visual result 1

Overlay layer cake
premium
Modal layer system

The app content stays below while backdrop and dialog live in the root overlay stack.

dialog layer backdrop layer component triggers base page
Root owns modal depth
Pattern 1 is ideal for product previews, account dialogs, checkout modals, and confirmation overlays.

Premium code example 2

Portal route from component to root
.card {
  overflow: hidden;
}

.card__button {
  position: relative;
}

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

Premium visual result 2

Portal routing system
premium
Component trigger, root dialog

The card keeps its clipped design. The portal sends the modal to a safe viewport layer.

Product card clipped image local button
Modal root backdrop dialog
Pattern 2 is ideal for component libraries, React portals, checkout drawers, and reusable card modals.

Premium code example 3

Mobile-safe dialog shell
.modal-root {
  position: fixed;
  inset: 0;
  display: grid;
  place-items: center;
}

.modal-dialog {
  width: min(520px, calc(100% - 32px));
  max-height: calc(100dvh - 32px);
  overflow: auto;
}

Premium visual result 3

Mobile-safe modal shell
premium
Viewport-safe dialog

The modal belongs to the root, but the dialog itself stays readable and scrollable on small screens.

dialog fits viewport
root fixed backdrop scrollable dialog
Pattern 3 is ideal when the modal can contain long forms, checkout steps, legal text, or settings panels.

Fast practical rule

If a modal is trapped inside a parent, stop increasing z-index and check where the modal is mounted. A page-level modal should usually be mounted in a page-level overlay root, not inside the card, section, or scroll container that opened it.

Debug checklist

  • Find the modal element in the DOM and identify its parent chain.
  • Check whether any parent has overflow:hidden or overflow:auto.
  • Check whether the modal uses position:absolute instead of viewport-level fixed positioning.
  • Look for local parents with position:relative.
  • Inspect transformed, filtered, or opacity-based parents that create local contexts.
  • Move the modal to a root overlay layer and keep the trigger inside the component.
  • Use separate z-index tokens for backdrop, dialog, header, drawer, and toast layers.
  • Test long modal content on mobile so the dialog scrolls internally instead of escaping the viewport.
Best first moveMove the modal markup outside the component and retest.
Most common causeThe modal is nested inside a card or panel with clipping.
Most sneaky causeThe trigger component owns the modal because it felt convenient.
Better mindsetTrigger local, dialog global.

When a local dialog is still okay

Not every pop-up needs to be a full page-level modal. A small tooltip, dropdown, inline editor, or component-only popover may correctly stay inside its parent. The key question is whether the UI is supposed to cover the page or only belong to the component.

If it must block the whole page, dim the background, or capture the user’s focus across the interface, treat it as a root overlay. If it only edits one card or shows one small hint, a local component layer may be fine.

The authority move is to choose the ownership level intentionally instead of letting markup convenience decide the modal architecture.

Why this bug hurts trust fast

A broken modal is not a subtle detail. Users immediately notice when a dialog opens inside the wrong box, gets cut off, hides behind the page, or refuses to cover the content. It makes the interface feel unfinished even if the rest of the layout is polished.

That is why modal architecture is a production concern, not just a visual tweak. The modal must be mounted where its job makes sense. A global modal needs a global layer.

Final takeaway

A modal trapped inside parent is usually an architecture problem, not just a z-index problem. The modal is mounted inside a parent that controls clipping, positioning, scrolling, or stacking.

Keep the trigger where it belongs, but move the modal to a root overlay layer when it needs to behave like a full-page dialog. That keeps cards, sections, and panels clean while the modal does its real job.

Want more fixes like this?

Browse more CSS overlay, modal, z-index, stacking context, dropdown, and responsive layout debugging guides in the FrontFixer library.