intive Argentina Blog

La traición de position:fixed

Existen pocas cosas seguras en la vida. Los polos norte-sur, de qué lado va a caer la tostada con mermelada, o si Lost después de la segunda temporada fue una estafa.

Aquellos que trabajamos en front-end, particularmente con CSS, si bien estamos acostumbrados a que las cosas se pisen entre sí, lo hacemos porque contamos con la seguridad de que cada cosa hará lo que siempre hace.

Por eso, si quiero que algo tenga un comportamiento o apariencia, simplemente debo definir ese comportamiento o apariencia. Y si luego quiero cambiar eso, simplemente definiendo la propiedad nuevamente, se pisara. Ese es el efecto de la cascada. Lo último se impone a lo primero.

Pero en determinadas ocasiones, esto no es así. Y nuestro mundo tal como lo conocemos se desmorona.

Recientemente en uno de nuestros proyectos, implementamos un paquete de terceros que nos permite mostrar un menú contextual. Seguimos los pasos recomendados para la implementación, pero no funcionaba. Y sin embargo no teníamos errores de ningún tipo.

Al inspeccionar el DOM de nuestra aplicación, vimos que el menú contextual estaba, pero no se mostraba.Y una de las propiedades del CSS de dicho menú era position: fixed. Recordemos que esta propiedad nos asegura que un elemento se mostrará en determinado lugar del viewport o pantalla (por decirlo de modo más fácil). O sea, que aquello que posea position:fixed se verá en un lugar y nada más importa.

Y ustedes pensaran: «Oiga, un position:fixed no se esconde así como así»

Y tienen razón. Pero acá empieza el misterio.

En un elemento padre, para desplazar un elemento en una animación, mediante JS modificábamos la propiedad translate3d para desplazar dicho elemento.

Buscando, encontramos otras pobres víctimas de esta anomalía, igual que nosotros:

Pregunta en StackOverflow

Y leyendo la especificación nos enteramos que cualquier elemento que utilice translate o translate3d, convierte a los position: fixed; de sus elementos hijos en position:relative. Vamos, que de pronto el norte es el sur y cosas así.

Transform rendering

Como buenos apasionados, decidimos probarlo. Aquí tienen un fiddle: https://jsfiddle.net/a2dtsgag/5/

Como verán, si el position:fixed del segundo elemento funcionara como estamos acostumbrados, sólo veríamos un cuadrado naranja, ya que ambos estarían superpuestos y sin embargo vemos dos. Todo por culpa de ese condenado translate. Hagan la prueba. Pueden borrar la propiedad de su elemento padre y verán como inmediatamente ambos cuadrados naranjas se superponen.

La propiedad translate3d, que era la que estábamos usando, acepta 3 parámetros:

Uno referido al desplazamiento horizontal, otro al vertical y el último produce un efecto de aumento o disminución del elemento. Es como si lo hiciéramos salir de la pantalla o lo hundiésemos.

Por suerte para nosotros, estábamos sólo usando translate para un desplazamiento horizontal, así que lo que pudimos hacer fue reemplazar translate(value, 0, 0) por left: value o right: -value, y pista.

Si hubiéramos usado translate para un desplazamiento vertical, podríamos haber usado top:value; o bottom: value;.

Pero si hubiéramos tenido que usar la tercera propiedad…

Bueno, mejor no pensemos en esos oscuros escenarios.

Pablo Hiyano

Pablo Hiyano es líder general de las brigadas de intive-FDV. Estudiante de Biología en Universidad de Buenos Aires (UBA), desde joven su gran interés por la programación lo convirtió en un desarrollador autodidacta apasionado por el mundo Javascript. En su tiempo libre, disfruta jugar con su hijo, ver series británicas y leer sobre filosofía, especialmente obras de Michel Foucault.

Sebastián Bogado

Es desarrollador de full stack en intive – FDV. Ha trabajado con el stack de Javascript en varias plataformas (Televisores Smart & relojes Smart, NodeJS, aplicaciones híbridas móviles y – por supuesto – el navegador). En la actualidad estudia ingeniería informática en la Universidad de Buenos Aires (UBA), y está trabajando en su tesis de graduación.

2 comentarios