JSFiddle - React, Tailwind, and code Playground
by mgibsonbr
HTML
<div class="contexto" id="A">
A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A
<div id="dentroDeA"></div>
</div>
<div class="contexto" id="B">
B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B
<div id="dentroDeB"></div>
</div>
<div id="semZ"></div>
CSS
.contexto { position: absolute; width: 100px; height: 100px; }
#A { background: red; z-index: 2; }
#B { left: 80px; top: 80px; background: green; z-index: 1; }
.contexto div { position: absolute; width: 40px; height: 40px; }
#A div { bottom: 0; right: 0; background: blue; z-index: 10; }
#B div { top: 0; left: 0; background: yellow; z-index: 20; }
#semZ {
position: absolute; width: 100px; height: 100px;
top: 0; left: 75px; background: lightgray;
}
JavaScript
var ctxA = document.getElementById('A');
var ctxB = document.getElementById('B');
var dentroDeA = document.getElementById('dentroDeA');
var dentroDeB = document.getElementById('dentroDeB');
var semZ = document.getElementById('semZ');
function naFrente(a, b) {
var pa = $(a).parents(), ia = pa.length;
var pb = $(b).parents(), ib = pb.length;
// Salta todos os ancestrais em comum
while ( ia > 0 && ib > 0 && pa[--ia] == pb[--ib] ) { }
var ctxA = (ia >= 0 ? pa[ia] : a), za = zIndex(ctxA);
var ctxB = (ib >= 0 ? pb[ib] : b), zb = zIndex(ctxB);
// Em último caso, olha as posições relativas
var relativo = ($(ctxA).index() - $(ctxB).index() < 0 ? a : b);
// Acha o primeiro com zIndex definido
while ( ctxA && za === undefined ) {
ctxA = ia < 0 ? null : --ia < 0 ? a : pa[ia];
za = zIndex(ctxA);
}
while ( ctxB && zb === undefined ) {
ctxB = ib < 0 ? null : --ib < 0 ? b : pb[ib];
zb = zIndex(ctxB);
}
if ( za !== undefined ) {
if ( zb !== undefined )
return za > zb ? a : za < zb ? b : relativo;
return za > 0 ? a : za < 0 ? b : relativo;
}
else if ( zb !== undefined )
return zb < 0 ? a : zb > 0 ? b : relativo;
else
return relativo;
}
function zIndex(ctx) {
if ( !ctx || ctx === document.body ) return;
// Verifica se o elemento está posicionado,
// e se tem z-index ou opacity
var posicionado = css(ctx, 'position') !== 'static';
var possuiZIndex = css(ctx, 'z-index') !== 'auto';
var naoOpaco = +css(ctx, 'opacity') < 1;
// Se ctx for um contexto, retorna
//if(posicionado && (possuiZIndex || naoOpaco)) {
if(posicionado && possuiZIndex) // Ignorando CSS3 por ora
return +css(ctx, 'z-index');
}
function css(el, prop) {
return window.getComputedStyle(el).getPropertyValue(prop);
}
//
// TESTE
//
console.log("A vs B: " + naFrente(ctxA,...