Why z-index: 9999 Is an Anti-Pattern

Understanding why using arbitrarily high z-index values like 9999 or 999999 creates maintenance problems and how to replace them with a proper scale.

Debugging

Detailed Explanation

The z-index: 9999 Problem

Using arbitrarily high z-index values is one of the most common CSS anti-patterns. It seems like a quick fix but creates cascading problems as a project grows.

How It Starts

/* Developer A: "I need this above the header" */
.modal { z-index: 999; }

/* Developer B: "My modal needs to be above that one" */
.important-modal { z-index: 9999; }

/* Developer C: "The tooltip needs to be on top of everything" */
.tooltip { z-index: 99999; }

/* Developer D: "I need this REALLY on top" */
.critical-alert { z-index: 999999; }

/* The codebase 6 months later... */
.the-thing-that-must-not-be-named { z-index: 2147483647; }
/* (That's the max 32-bit integer) */

Why It Fails

  1. No ceiling: There is always a higher number. When two developers independently add high values, conflicts are inevitable.

  2. No semantic meaning: z-index: 9999 communicates nothing about what the layer is or where it should sit in the hierarchy.

  3. Stacking contexts nullify it: Even z-index: 2147483647 is trapped inside its stacking context. If the parent has z-index: 1, it cannot exceed another element with z-index: 2.

  4. Hard to debug: Finding all z-index values scattered across a codebase and understanding their relationships is extremely difficult.

The Fix: Define a Scale System

/* Before: arbitrary values */
.dropdown { z-index: 100; }
.header { z-index: 500; }
.modal-bg { z-index: 999; }
.modal { z-index: 9999; }
.tooltip { z-index: 99999; }

/* After: deliberate scale */
:root {
  --z-dropdown: 1000;
  --z-sticky: 1020;
  --z-overlay: 1040;
  --z-modal: 1050;
  --z-toast: 1080;
  --z-tooltip: 1090;
}

.dropdown { z-index: var(--z-dropdown); }
.header { z-index: var(--z-sticky); }
.modal-bg { z-index: var(--z-overlay); }
.modal { z-index: var(--z-modal); }
.tooltip { z-index: var(--z-tooltip); }

Migration Strategy

  1. Audit: Search your codebase for all z-index declarations
  2. Categorize: Group them by purpose (dropdown, modal, tooltip, etc.)
  3. Design scale: Use this tool to create a proper z-index scale
  4. Replace: Swap hardcoded numbers for CSS variables
  5. Lint: Add a CSS linter rule to prevent hardcoded z-index values

ESLint / Stylelint Rule

// stylelint-plugin-no-hardcoded-zindex (conceptual)
"declaration-property-value-disallowed-list": {
  "z-index": ["/^[0-9]+$/"]
}

Use this tool to design your z-index scale before writing a single line of CSS.

Use Case

When inheriting a codebase with scattered z-index values and need to refactor to a consistent, maintainable scale system, or when setting up CSS guidelines for a new project.

Try It — z-index Manager

Open full tool