Last active
January 26, 2026 16:04
-
-
Save jeferson-sb/4bebc6f421e6c50090118f7006a2a854 to your computer and use it in GitHub Desktop.
Find stacking context on the page
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * Will return all elements that create a stacking context in the parent tree. | |
| * @param {HTMLElement} root - The root element to start the search from. | |
| * @example const stackingContexts = listStackingContexts(document.body) | |
| */ | |
| function listStackingContexts(root) { | |
| const walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT) | |
| const stackingContexts = new Map() | |
| const contextStack = [] | |
| if (root instanceof HTMLElement && isStackingContext(root)) { | |
| const rootChildren = new Map() | |
| stackingContexts.set(root, rootChildren) | |
| contextStack.push({ node: root, children: rootChildren }) | |
| } | |
| let currentNode = null | |
| while ((currentNode = walker.nextNode())) { | |
| while ( | |
| contextStack.length > 0 && | |
| !contextStack[contextStack.length - 1].node.contains(currentNode) | |
| ) { | |
| contextStack.pop() | |
| } | |
| if (!isStackingContext(currentNode)) continue | |
| const childrenMap = new Map() | |
| if (contextStack.length > 0) { | |
| contextStack[contextStack.length - 1].children.set(currentNode, childrenMap) | |
| } else { | |
| stackingContexts.set(currentNode, childrenMap) | |
| } | |
| contextStack.push({ node: currentNode, children: childrenMap }) | |
| } | |
| return stackingContexts | |
| } | |
| function isStackingContext(elementNode) { | |
| const styles = elementNode.computedStyleMap() | |
| const zIndex = styles.get('z-index').value | |
| const opacity = styles.get('opacity').value | |
| const position = styles.get('position').value | |
| const blendMode = styles.get('mix-blend-mode').value | |
| const isolation = styles.get('isolation').value | |
| const containerType = styles.get('container-type').value | |
| const willChange = styles.get('will-change').value | |
| const scenarios = { | |
| zIndex: zIndex !== 'auto', | |
| opacity: opacity < 1 && position !== 'static', | |
| blendMode: blendMode !== 'normal', | |
| isolation: isolation === 'isolate', | |
| containerType: containerType === 'size' || containerType === 'inline-size', | |
| willChange: willChange !== 'auto' | |
| } | |
| const createsStackingContext = Object.values(scenarios).some(Boolean) | |
| return createsStackingContext | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment