Menú de navegaciónMenú
Categorías

La mejor forma de Aprender Programación online y en español www.campusmvp.es

?id=adaf94b2-7a0f-4dfb-ab0d-2c874f001f2a

¿Por qué aunque pongo un z-index muy alto no consigo que se vea un elemento en mi diseño Web?

Antes de nada voy a empezar con un buen repaso de qué es la propiedad z-index, para qué vale y cómo trabaja. Aunque creas que conoces z-index, no dejes de leer esta parte introductoria, puesto que hay detalles que es muy probable que no tengas tan claros como creías.

El artículo es bastante largo porque entra a fondo en cómo se apilan los elementos de una página, algo que es crucial entender bien para poder evitar problemas a la hora de maquetar y mostrar los elementos adecuadamente. Además quiero ser exhaustivo. Incluyo también un vídeo explicativo al final, en el que se puede ver en la práctica lo explicado.

Este artículo está basado en material de mi curso HTML5 y CSS3 a fondo para desarrolladores de campusMVP. Si quieres aprender bien estas materias, más complicadas de lo que parece a primera vista, este es tu curso. Habla con tu responsable en tu empresa: puede saliros sin coste.

La propiedad z-index

La propiedad CSS z-index sirve para indicar la posición de los elementos en el eje perpendicular (eje "Z" de ahí su nombre) de una página.

Si vemos una página Web como un papel colocado sobre una mesa, los ejes X e Y serían los que siguen los bordes de la página, y el eje Z sería el perpendicular a la mesa (hacia "arriba"), algo así:

La imagen muestra un render 3D de una página Web impresa, encima de una mesa, con los ejes de referencia dibujados encima

Como vemos, todos los ejes parten de la esquina superior izquierda de la página. Los ejes horizontales, X e Y, que mueven los elementos sobre la superficie de la página, son los que establecemos con las propiedades top y left cuando un elemento está posicionado de manera diferente a la posición estática que tienen por defecto (por ejemplo: absolute, relative, fixed, sticky...). El eje Z es lo que establecemos con la propiedad z-index y se refiere a la posición de los elementos sobre el plano.

Con z-index podemos controlar cómo se posicionan unos elementos encima de los otros cuando coinciden al cambiar su posición.

En la página, este posicionamiento vertical se traduce en que unos elementos "tapan" a los otros porque se superponen, ya que, en la figura anterior, nosotros veríamos la página colocados de forma perpendicular a la mesa, o sea, desde arriba, por lo que no somos capaces de ver la "altura", y sólo veríamos unos encima de otros tapándose.

Lo básico que hay que saber de z-index es lo siguiente:

  1. Sus unidades son "niveles", no longitudes. Al contrario que el posicionamiento en los otros ejes, el valor de esta propiedad no se mide en píxeles u otras unidades de longitud, sino en "niveles". Es decir, es un número entero, positivo o negativo, que indica el "nivel" sobre el plano de la página en el que se colocará ese elemento.
  2. Sólo funciona en elementos posicionados. Es decir, en elementos con el valor por defecto de position (que es static), no tiene efecto alguno. Ya le puedes poner lo que quieras, que no te hará caso.

Cómo se colocan los elementos en una página: la importancia de z-index

Por defecto los elementos de una página tienen una posición estática, por lo que se colocan siguiendo el orden en el que están definidos en el código y, en principio, no se solapan nunca.

Nota: lo anterior no es del todo cierto ya que podemos jugar con márgenes negativos y cosas así para hacer que se solapen, pero no es lo habitual. En cualquier caso seguirían estando en el mismo plano, por lo que el término correcto sería "interfiriéndose", no solapándose. En caso de interferencia queda por encima el que se haya definido más tarde en el código.

Si cambiamos el modo de posicionamiento con la propiedad position y usamos alguno de los disponibles para poder colocarlos de manera relativa, absoluta, fija, etc... lo que ocurre es que estos elementos se salen del flujo normal de la página y se colocan en donde les corresponda, interfiriendo con cualquier otro elemento "normal" que hubiera en esa ubicación. Es decir, al posicionar un elemento éste interfiere con los demás elementos que ocupen su misma posición. Quedará por encima el que esté definido más tarde en el código, como en el caso comentado en la nota anterior.

Para poder controlar qué elemento se va a visualizar en caso de interferencia por posicionamiento existe la propiedad z-index. Gracias a ella podemos indicar en qué nivel queremos que esté cada elemento sobre el plano, decidiendo de esta manera cuál es el que se va a ver por encima de los demás.

Así, por ejemplo, consideremos este sencillo código HTML:

<div id="sc1" class="sc">
    <div class="caja roja">HOLA</div>
</div>
<div id="sc2" class="sc">
    <div class="caja verde">HOLA</div>
</div>
<div id="sc3" class="sc">
    <div class="caja azul">HOLA</div>
</div>

En él tenemos tres elementos con un <div> dentro cada uno de ellos. He establecido el CSS para que los divs interiores sean cuadrados y tengan un color diferente para verlos bien.

Nota: aunque los divs "padre" no son necesarios en general y, de hecho, en este caso se colapsan, quedando sin dimensiones, me interesa tenerlos para el ejemplo posterior, así que de momento no te preocupes por ellos.

Como sabemos, si no le cambiamos el posicionamiento quedarían unos debajo de otros, apilados en la vertical (posicionamiento estático):

Cajas apiladas

Si les ponemos un posicionamiento absoluto, sin indicar realmente posición alguna, estarán todos colocados en (0,0) y por lo tanto interferirán en el mismo plano y el que se verá es el último: el azul:

Todos los elementos interfiriendo, solo se ve el azul

Vamos, que es como si sólo tuviésemos uno a efectos de visualizarlos.

Ahora los voy a posicionar para que se muevan y se vean todos a la vez, pero interfiriendo unos con otros:

Los 3 elementos posicionados

Ahora los vemos todos, pero como se interfieren parcialmente, unos se tapan a otros, tapando el azul al verde y éste al rojo que está debajo de todo por ser el primero en el código.

Si queremos que uno de ellos prevalezca sobre los demás independientemente de dónde esté en el código, podemos ponerle un z-index superior a lo de los otros:

El verde ahora está por encima de los demás

¡Perfecto! Justo lo que queríamos. El CSS sería:

.caja {
    width: 200px;
    height:200px;
    position: absolute;
}

.roja {
    background-color: coral;
    top: 0;
    left: 0;
}

.verde {
    background-color: lightseagreen;
    top: 100px;
    left: 100px;
    z-index: 1;
}

.azul {
    background-color: skyblue;
    top: 200px;
    left: 200px;
}

Al ponerle un z-index:1; al segundo elemento (y tener todos ellos un posicionamiento absoluto), lo que estamos haciendo es colocarlo un nivel por encima del del documento "base", que es donde están los otros dos cuadrados, por eso se ve por encima.

Muy sencillo ¿no?

Cuando z-index no hace caso

Pues va a ser que no...

El problema de z-index es que parece muy sencillo (un número y listo), pero puede llegar a complicarse. Y es entonces cuando aparecen los problemas y nada parece funcionar. Vamos a verlo con un ejemplo sencillo.

Sigamos con la estructura anterior de cuadrados. Sólo voy a hacer un cambio muy pequeño: al div contenedor del tercer cuadrado le voy a aplicar una rotación con este estilo:

#sc3 {
    transform: rotate(360deg);
}	

Es una tontería, ya que lo deja tal cual estaba (girarlo 360 grados es dejarlo en la misma posición), pero me servirá para demostrar una cosa.

Nota: podría haber hecho otras muchas cosas con él, como cambiarle la opacidad un poco, aplicarle una máscara o aplicarle una ruta de recorte (propiedad clip-path), entre otras muchas cosas. Luego las veremos.

Ahora al cuadrado azul, el que está contenido en ese div que hemos rotado, le aplicamos un z-index:2;, es decir mayor que el del segundo cuadrado, el verde, por lo que en teoría debería quedar por encima, ya que está posicionado sobre él en el plazo Z:

El resultado: el cuadrado azul sigue por debajo a pesar de tener un z-index mayor que el verde

¡No funciona!

Este es uno de esos casos en los que, hagas lo que hagas con z-index no podrás ponerlo por encima.

Muchos desarrolladores Web, cuando se encuentran con un problema como este lo que hacen es ponerle un valor muy grande a la propiedad z-index, tratando de "ser el que más arriba está", en plan z-index:9999; y cosas así. Eso no vale para nada.

¿Cuál es el motivo de que es no funcione?

Contextos de apilamiento (stacking contexts)

Para entender por qué un determinado elemento "no hace caso" del z-index hay que entender qué es un contexto de apilamiento.

Por defecto, siempre existe al menos un contexto de apilamiento que es el que se crea en el elemento raíz de la página (<html>). Es en este en el que se apilan todos los demás elementos de la forma que hemos visto antes.

Pero, además de este, se pueden formar muchos otros contextos de apilamiento dentro de la página. En concreto, se forman contextos de apilamiento en elementos que cumplan alguna de estas condiciones:

  • Si están posicionados con absolute o relative y tienen un z-index aplicado (distinto de auto, el valor automático por defecto), como los tres cuadrados de nuestro ejemplo.
  • Si tiene posición fixed o sticky.
  • Si es hijo de un elemento Flexbox o Grid que tenga un z-index aplicado (nuevamente no auto).
  • Si se le aplica una opacidad parcial, es decir, si no es totalmente opaco (un valor tan grande como opacity:0.9999; sería suficiente).
  • Si se le ha aplicado alguna transformación (transform), filtro (filter), máscara (mask), perspectiva o ruta de recorte (como he comentado más arriba).
  • Si se han hecho mezclas fotográficas o de colores o se le ha aplicado aislamiento.
  • Si se ha cambiado su modo de contención de elementos.
  • Si se le indica al navegador que el elemento va a cambiar en el futuro, para resolver problemas de rendimiento.

En general se puede decir que se forma un nuevo contexto de apilamiento cuando sacamos un elemento del flujo normal de la página, sea con el método que sea (todos los de la lista anterior lo hacen de un modo u otro).

Cuando se forma un nuevo contexto de apilamiento lo que ocurre es que todos los elementos hijos del que lo ha formado pasan a gestionarse con él, en grupo, y su propiedad z-index ya no tiene efecto sobre los demás elementos fuera de este contexto.

Esto es la clave: la posición en Z de sus hijos sólo tendrá influencia sobre otros elementos del mismo contexto de apilamiento.

Interferencia de los contextos de apilamiento

Sólo nos falta un detalle más: conocer cómo se relacionan entre sí los contextos de apilamiento.

Si hay más de un elemento que forma su propio contexto de apilamiento en una página (algo que pasa constantemente), en caso de que estos elementos interfieran entre sí, el orden de visualización es el siguiente, idéntico al de los elementos individuales que hemos visto antes:

  1. Abajo de todo de la pila, en el nivel 0, se visualiza el elemento raíz, que forma su propio contexto de apilamiento, el global. Lo que se ven son los bordes y el fondo del elemento raíz de la página (el elemento <html>). Es importante señalar que, aunque le pongas a algún elemento hijo del raíz un z-index negativo, no podrá estar nunca por debajo del elemento raíz.
  2. Justo encima se visualizan los elementos posicionados con un z-index negativo. Estos no pueden estar por debajo del raíz, pero sí por debajo de otros elementos.
  3. A continuación se ponen los elementos no posicionados, es decir, los que tienen position:static, que es el valor por defecto, en el orden de aparición en el código fuente (los que están definidos más tarde, se ven por encima en caso de interferencia).
  4. Luego se colocan los elementos posicionados de diversas formas (absoluta, relativa...) que no tienen un z-index especificado (lo tienen en auto).
  5. Finalmente se colocan los elementos posicionados que además tienen un z-index positivo.

Sabiendo esto es fácil ver por que en nuestro ejemplo el cuadrado azul no se ve a pesar de que le hayamos puesto un z-index altísimo... ¿Sería capaz de ver el motivo?

Te lo voy a mostrar en un vídeo en el que te lo explico de manera visual:

En resumen

En más ocasiones de las que nos gustaría, las cosas en HTML y CSS parecen mucho más sencillas de lo que son en realidad. Una de estas cuestiones aparentemente fáciles, pero que tiene mucho más fondo del que parece, es el posicionamiento vertical de elementos, controlado por la propiedad z-index, que influye en qué elementos se ven cuando se solapan varios.

Existen dos conceptos clave para entender el posicionamiento vertical: los contextos de apilamiento y la prioridad cuando se produce una interferencia entre elementos.

En este artículo, basado en material de mi curso HTML5 y CSS3 a fondo para desarrolladores de campusMVP, te explico con detalle esos conceptos para ir más allá de lo que sabe el desarrollador medio sobre el tema, y ayudarte a evitar cualquier problema que te pueda surgir a la hora de aplicar la visibilidad vertical de elementos.

Además vemos un ejemplo práctico del problema, con un vídeo explicativo que te ayuda a entender qué pasa y cómo solucionarlo. Puedes descargar el ejemplo desde aquí (ZIP, 0,6Kb).

¡Espero que te resulte útil!

José Manuel Alarcón Fundador de campusMVP, es ingeniero industrial y especialista en consultoría de empresa. Ha escrito diversos libros, habiendo publicado hasta la fecha cientos de artículos sobre informática e ingeniería en publicaciones especializadas. Microsoft lo ha reconocido como MVP (Most Valuable Professional) en desarrollo web desde el año 2004 hasta la actualidad. Puedes seguirlo en Twitter en @jm_alarcon o leer sus blog técnico o personal. Ver todos los posts de José Manuel Alarcón
Archivado en: Desarrollo Web

¿Te ha gustado este post?
Pues espera a ver nuestro boletín mensual...

Suscríbete a la newsletter

La mejor formación online para desarrolladores como tú

Agregar comentario

Los datos anteriores se utilizarán exclusivamente para permitirte hacer el comentario y, si lo seleccionas, notificarte de nuevos comentarios en este artículo, pero no se procesarán ni se utilizarán para ningún otro propósito. Lee nuestra política de privacidad.