What public systems are optimizing for
The systems captured on October 3, 2026 use different z-index scales. That difference matters. Each vocabulary reflects a different ownership boundary, so copying the names without copying that boundary creates false clarity.
| Convention | Examples | Useful when | Main risk when borrowed | |
|---|---|---|---|---|
| Numeric scale | Numeric scale | USWDS; Duet token category | The system wants supported values and implementation helpers without naming every product layer. | A number shows where something sits but may not explain which relationship it protects. |
| Application-role ramp | Application-role ramp | Salt roles such as application header, modal, notification, and context menu | The design system governs recurring layers across an application. | A borrowed role may imply authority that the consuming project does not actually share. |
| Component-oriented ramp | Component-oriented ramp | Shoelace drawers, dialogs, dropdowns, toasts, and tooltips | A component library owns a known overlay family. | Product integrations can introduce relationships outside the library's vocabulary. |
| Broad framework vocabulary | Broad framework vocabulary | Chakra roles including sticky, banner, overlay, modal, popover, toast, and tooltip | A framework supplies common application roles out of the box. | The convenient list can encourage unused global layers or hide component-local relationships. |
Nord publishes named depth roles inside a versioned cross-foundation catalog. Panda treats z-index as a supported token category and makes the authoring, semantic-reference, generated-CSS, and consumption stages visible. Martin Fowler's token architecture adds another useful distinction: available options, application decisions, and component scope answer different questions.
Shoelace is historical evidence
The captured Shoelace page says the library is sunset with no active development. Its component-oriented naming still shows one possible ownership model, but use the current library's documentation for implementation decisions.
Don't average these ramps into a new one. Decide who owns each relationship first. The numeric values come later.
Route every relationship to one of four outcomes
Start with a sentence, not a number: "The notification must remain above an open dialog," or "The tooltip must remain above the control that owns it." Then classify the relationship by authority and change scope.
| Outcome | Use it when | Required record | Owner | |
|---|---|---|---|---|
| Shared semantic role | Shared semantic role | The relationship recurs across independently changing components or surfaces and should change as one policy. | Semantic purpose, ordering constraints, named consumers, context assumptions, and protected relationships. | Design-system or application-layer policy owner. |
| Component-local order | Component-local order | Parts move together with one component and have no independent application-level meaning. | Component contract, internal parts, allowed local range, and supported states. | Component owner. |
| Approved exception | Approved exception | A named integration or product surface cannot follow the shared relationship for a documented reason. | Scope, conflicting rule, replacement behavior, approver, expiry or retest trigger. | Product or integration owner plus the policy approver. |
| Unresolved rule | Unresolved rule | Authority, required order, affected consumers, or runtime conditions remain disputed or unknown. | Open question, evidence needed, decision owner, and blocking consequence. | Named decision owner; no token is created yet. |
A candidate earns shared status only if one authority can decide it and multiple named consumers need the relationship. Those consumers may change independently, but the relationship should remain stable. A controlled change must also show which consumers should move and which should not.
A name such as tooltip isn't enough. If a tooltip exists only inside one menu and its order changes only with that menu, the menu component probably owns the relationship. If tooltips from several component families must consistently outrank ordinary overlays, the relationship may belong to shared application policy.
Do not encode a disagreement as a token
If one team expects notifications above dialogs while another expects critical dialogs above every notification, the missing artifact is a policy decision. Adding --z-super-top only hides the disagreement.
Copy this versioned layer contract
The contract below is illustrative and unexecuted. Its identifiers and values don't come from Identity Forge or any observed design system. Replace every field with project evidence before treating it as accepted.
layerContract:
id: application-overlay-policy
authority:
source: ui-system/layers.yaml
version: 0.1.0-proposed
owner: design-system-team
role:
name: layer.notification
purpose: transient application notification
value: 500
orderingConstraints:
above:
- layer.dialog
below:
- approved-emergency-surface
allowedConsumers:
- global-notification-region
contextAssumptions:
- consumer host participates in the intended application stacking context
- no ancestor traps the consumer below the dialog host
componentLocalRelationships:
- notification close button remains local to Notification
- notification progress bar remains local to Notification
exceptions:
- id: embedded-support-widget
status: proposed
owner: integrations-team
rationale: third-party host relationship requires separate verification
evidence:
state: UNOBSERVED
references: []
correctionOwners:
sourcePolicy: design-system-team
generatedArtifact: build-platform-team
projectMapping: application-platform-team
componentContract: component-team
renderedConsumer: owning-product-team
retestTriggers:
- source version changes
- overlay host or portal target changes
- positioning, transform, opacity, isolation, or containment changes on an ancestor
- named consumer changes its mounting location
disposition: reviseThe contract keeps intent, implementation assumptions, evidence, and disposition separate. A proposed value can be internally coherent while the evidence remains UNOBSERVED. A correct rendered screenshot also doesn't prove that the source policy or mapping is correct if an accidental local override produced the result.
- The order of a dialog panel above its own backdrop belongs in the dialog contract unless another component depends on that internal relationship.
- The arrow, bubble, and dismiss control inside a tooltip remain component details.
- A third-party widget with a fixed host and separate lifecycle should remain an integration exception until its relationship is verified.
- A temporary debugging value belongs in a branch or diagnostic fixture, not in the accepted semantic scale.
- A relationship with no named consumer remains a proposal, not inventory.
Start from a complete upstream system
A design kit can supply the broader visual direction, semantic colors, typography, spacing, and implementation guidance. The consuming project still needs to define and verify its own layer policy.
Trace one role from source to rendered consumer
Consider an invented rule: the global notification region should appear above the standard dialog layer. This trace doesn't prove that the ordering is right for every product. It shows where a correct decision can diverge on its way to the screen.
- 1
Record the source decision
The proposed source declares
layer.dialog: 400andlayer.notification: 500. Authority is the versioned application layer policy. Evidence state: UNOBSERVED. - 2
Inspect the emitted artifact
Expected artifact: both identifiers appear with their intended values in the generated project asset. Observation: UNOBSERVED.
--app-layer-dialog: 400; --app-layer-notification: 500; - 3
Inspect the project mapping
Expected mapping: the project aliases its dialog and notification hosts to the emitted properties without swapping or duplicating the values. Observation: UNOBSERVED.
--layer-dialog: var(--app-layer-dialog); --layer-notification: var(--app-layer-notification); - 4
Check the component contract
Expected behavior: the notification region consumes the project notification alias. Internal notification parts use local ordering and don't create new global roles. Observation: UNOBSERVED.
.notification-region { z-index: var(--layer-notification); } - 5
Check the named consumer
Expected result: under the recorded mounting and ancestor conditions, the notification region appears above the standard dialog. Observation: UNOBSERVED. No acceptance decision is justified until this is executed and recorded.
Illustrative CSS is not a compatibility result
The snippets show a possible mapping shape. They weren't generated by a named tool, run in a browser, or tested against a framework. Keep the observation fields open until your project executes the cases.
Verify named consumers under real conditions
A single overlay demo is weak evidence. The same shared value can behave differently when consumers mount in different hosts, sit inside scrolling containers, or inherit new stacking contexts from ancestors. Record one row for each named consumer, including any conditions that could change the result.
verificationCases:
- consumer: primary-sticky-navigation
conditions: viewport scroll; navigation inside application shell
expectedOrder: above page content; below dialog and notification hosts
observedResult: UNOBSERVED
evidenceReference: null
firstDivergentLayer: UNOBSERVED
correctionOwner: UNASSIGNED_UNTIL_DIVERGENCE
retestTrigger: shell positioning or ancestor context changes
disposition: revise
- consumer: account-menu-dropdown
conditions: opened from sticky navigation; menu may mount locally or in an overlay host
expectedOrder: above navigation content; below dialog
observedResult: UNOBSERVED
evidenceReference: null
firstDivergentLayer: UNOBSERVED
correctionOwner: UNASSIGNED_UNTIL_DIVERGENCE
retestTrigger: portal target or navigation component changes
disposition: revise
- consumer: field-help-tooltip
conditions: control inside dropdown; tooltip open while dropdown remains open
expectedOrder: above its owning dropdown without redefining application policy
observedResult: UNOBSERVED
evidenceReference: null
firstDivergentLayer: UNOBSERVED
correctionOwner: UNASSIGNED_UNTIL_DIVERGENCE
retestTrigger: tooltip host or dropdown contract changes
disposition: revise
- consumer: confirmation-dialog
conditions: dialog open over scrolled page; standard overlay host
expectedOrder: above page, sticky navigation, and dropdown
observedResult: UNOBSERVED
evidenceReference: null
firstDivergentLayer: UNOBSERVED
correctionOwner: UNASSIGNED_UNTIL_DIVERGENCE
retestTrigger: dialog backdrop, panel, or host changes
disposition: revise
- consumer: global-notification-region
conditions: notification emitted while confirmation dialog is open
expectedOrder: follows the approved notification-versus-dialog policy
observedResult: UNOBSERVED
evidenceReference: null
firstDivergentLayer: UNOBSERVED
correctionOwner: UNASSIGNED_UNTIL_DIVERGENCE
retestTrigger: notification policy, host, or ancestor context changes
disposition: reviseThe tooltip case is especially revealing. A global tooltip token may be unnecessary if the tooltip only needs to outrank content inside its owning dropdown. If the tooltip mounts elsewhere, however, a local value may no longer describe the relevant relationship. The contract must name the mounting assumption instead of relying on the component name.
Debug the first divergence, not the largest number
When the rendered order is wrong, compare the expected chain with the actual chain from authority to screen. Stop at the first mismatch. That layer owns the first correction attempt.
- 1
Check the source contract
Is the intended relationship explicit, current, approved, and assigned to the right authority? If the contract itself is ambiguous, changing CSS is premature.
- 2
Check the generated artifact
Did the expected source version emit both identifiers and values? A stale or incomplete artifact is a generation or distribution failure.
- 3
Check the project mapping
Does the consuming project map each semantic role to the intended emitted value? Look for swapped aliases, copied literals, stale imports, and mode-specific overrides.
- 4
Check the component contract
Does the component consume the project role at the correct host? Separate its application-level host from the internal ordering of the backdrop, panel, arrow, or control.
- 5
Check approved exceptions
Is a documented integration or surface exception intentionally replacing the shared policy? Confirm its scope, owner, and retest trigger.
- 6
Inspect the rendered consumer
Record the mounting target, relevant ancestors, scroll container, positioned elements, and stacking contexts. If two elements are in different contexts, compare the contexts rather than their descendant values.
- 7
Change one hypothesis and retest
Raise or lower a value only when the evidence shows that the numeric relationship inside the relevant context is wrong. Otherwise, correct the mapping, host, component contract, exception, or context boundary.
A z-index token can govern an intended relationship, but it cannot guarantee that two rendered elements participate in a relationship where their values can compete.
Value escalation should remain a hypothesis. If a tooltip is trapped inside a lower stacking context, changing it from 100 to 100000 only changes its position among peers in that context. The higher context still wins. The useful finding is the first divergent boundary, not the biggest value in the stylesheet.
Migrate arbitrary values without a global renumbering
Don't begin a migration by sorting every integer and assigning a token name. That approach preserves accidental relationships and promotes component internals into global policy. Inventory the relationships first, then migrate one accepted relationship at a time.
- 1
Inventory consumers and relationships
For each literal z-index, record the named consumer, what it must appear above and below, its mounting location, and the owner who can confirm the rule.
- 2
Mark context boundaries
Group values that actually compare within the same stacking context. Don't infer a global order from integers found in unrelated contexts.
- 3
Preserve intentional local ordering
Keep backdrop-to-panel, trigger-to-popup, and similar internal relationships in their component contracts when no external consumer depends on them.
- 4
Classify each candidate
Choose shared semantic role, component-local order, approved exception, or unresolved rule. Reject unused placeholder layers.
- 5
Map one named relationship
Introduce the source role, emitted value, project alias, and component consumption path for one relationship. Don't renumber unrelated values to make the scale look tidy.
- 6
Run the affected verification cases
Record the expected order before executing. Capture observations, the first divergent layer, correction owner, retest trigger, and accept, revise, or block disposition.
- 7
Remove a literal only after its consumer moves
The existence of a new token doesn't prove that the old value is unused. Trace references and retain a visible migration state until the named consumer is verified.
Leave room without giving it meaning
Numeric gaps can make later value changes convenient, but gaps aren't semantic roles. Add a role only when a current relationship and named consumer justify it.
Where Identity Forge stops
This topic is adjacent to Identity Forge's shipped design-token and implementation-ready design-system coverage. Identity Forge can supply upstream design-kit artifacts such as semantic color tokens, typography, spacing, layout guidance, DESIGN.md, and supported exports. The frozen evidence for this article doesn't establish a shipped Identity Forge z-index token or z-index export.
The consuming project owns its layer policy, numeric mappings, component behavior, exceptions, stacking assumptions, runtime tests, and acceptance decision. Don't attribute the illustrative identifiers, values, or unexecuted results in this guide to Identity Forge.
Make one relationship verifiable today
Choose the overlay relationship your product reuses most often. Name its authority, two real consumers, expected order, mounting assumptions, and retest trigger. Then execute one consumer case and trace the first divergence before adding another shared layer token.
Sources
- Z-index - U.S. Web Design System (USWDS): USWDS documents a primarily numeric z-index token scale, special top and bottom values, and supported implementation routes.
- Z-Index - Salt Design System: Salt documents named application layers intended to make stacking order predictable across its system.
- Design Tokens - Nord Design System: Nord publishes a versioned token catalog with documented depth roles and intended uses.
- Design Tokens - Duet Design System: Duet includes z-index among the categories in its broad design-token catalog.
- Z-Index Tokens - Shoelace: Shoelace documents component-oriented z-index values for overlays and states that the library is sunset with no active development.
- The Value of z-index | CSS-Tricks: CSS-Tricks explains magic-number escalation, global versus component-local layering, and why a larger value cannot cross a higher stacking context.
- Tokens - Panda CSS: Panda CSS separates token authoring, semantic references, generated CSS, and token consumption in styles.
- Z-Index - Chakra UI: Chakra UI publishes a broad framework-owned z-index vocabulary including sticky, modal, popover, toast, and tooltip roles.
- Design Token-Based UI Architecture - Martin Fowler: The article separates available options, application decisions, and component-scoped tokens as distinct architectural layers.
- First-party product source: Identity Forge publicly describes design kits and agent-ready artifacts, but the frozen product evidence does not establish a shipped z-index token capability.