Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
debug z-index and stacking context
/*
Usage:
* Paste this into your dev tools console (or even better as a snippet)
* It will parse the page and find all the things that create a new stacking context
and dump some info about them to the console. It will also outline them on the page.
* This is pretty rough and probably misses heaps of bugs and edge cases.
*/
function run() {
function highlight(el) {
el.style.border = '3px solid #ff19bd';
}
function css(el, property) {
return window.getComputedStyle(el)[property];
}
function log(el, reason) {
console.group('New Stacking context');
console.log(el);
reason && console.log('Reason:', reason);
console.log('z-index: ', css(el, 'z-index'));
console.log('position: ', css(el, 'position'));
console.log('opacity:', css(el, 'opacity'));
console.log('transform:', css(el, 'transform'));
console.log('filter:', css(el, 'filter'));
console.log('perspective:', css(el, 'perspective'));
console.log('clip-path', css(el, 'clip-path'));
console.log('mask', css(el, 'mask'));
console.groupEnd();
}
Array.from(document.querySelectorAll('*')).forEach(function(el) {
var tagName = el.tagName;
var parentEl = el.parentElement;
var parentDisplay = parentEl ? css(parentEl, 'display') : null;
function p(property) {
return css(el, property);
}
// Tests
function mark(el, reason) {
highlight(el);
log(el, reason);
}
// Check the rules:
// https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context
// 1. Root element of document (HTML).
if (tagName === 'HTML') {
mark(el, 1);
}
// 2. Element with a position value "absolute" or "relative" and z-index value other than "auto".
if (
p('z-index') !== 'auto' &&
(p('position') === 'absolute' || p('position') === 'relative')
) {
mark(el, 2);
}
// 3. Element with a position value "fixed" or "sticky" (sticky for all mobile browsers, but not older desktop).
if (p('position') === 'fixed' || p('position') === 'sticky') {
mark(el, 3);
}
// 4. Element that is a child of a flex (flexbox) container, with z-index value other than "auto".
if (parentDisplay === 'flex' && p('z-index') !== 'auto') {
mark(el, 4);
}
// 5. Element with a opacity value less than 1.
if (parseFloat(p('opacity')) < 1) {
mark(el, 5);
}
// 6. Element with a mix-blend-mode value other than "normal".
if (p('mix-blend-mode') !== 'normal') {
mark(el, 6);
}
/*
7. Element with any of the following properties with value other than "none":
- transform
- filter
- perspective
- clip-path
- mask / mask-image / mask-border
*/
// TODO: account for vendor prefixes?
if (
p('transform') !== 'none' ||
p('filter') !== 'none' ||
p('perspective') !== 'none' ||
p('clip-path') !== 'none' ||
p('mask') !== 'none'
) {
mark(el, 7);
}
// 8. Element with a isolation value "isolate".
if (p('isolation') === 'isolate') {
mark(el, 8);
}
// 9. Element with a -webkit-overflow-scrolling value "touch".
if (p('-webkit-overflow-scrolling') === 'touch') {
mark(el, 9);
}
// 10. Element with a will-change value specifying any property that would create a stacking context on non-initial value
// TODO
});
}
run();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.