Menú de navegaciónMenú
Categorías

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

Si position: sticky; no te funciona, quizá sea por esto...

La propiedad de CSS position, como su propio nombre indica, sirve para posicionar elementos HTML. Anteriormente ya echamos un vistazo general a sus propiedades con especial atención a position:absolute;, que es uno de sus valores más útiles.

En este post veremos otro interesante valor de esta propiedad: position:sticky;. No hace mucho me vi en la necesidad de usarlo en un banner, pero había un hándicap, y es que no me funcionaba (cuando todo parecía apuntar a que debería hacerlo) y no entendía por qué.

Si position:sticky; no te funciona, sigue leyendo, porque quizá estás pasando por alto alguno de los detalles que hay que tener en cuenta para usarlo. Y si no, también, porque te puede ahorrar tiempo en el futuro.

¿Qué hace position: sticky y para qué sirve?

Básicamente hace que el elemento se comporte como en position:relative hasta que, debido al scroll de la página, el elemento es alcanzado por la parte superior del viewport (no es exactamente así, pero es el uso más habitual). En ese momento se comporta como fixed, y para que funcione correctamente hay que especificar al menos un valor top, bottom, left o right, en función de si va a ser sticky en un scroll horizontal o vertical.

Los casos más comunes en los que se aplica esto suelen ser: fijar un menú en la parte superior de la página, resaltar banners, formularios u otras llamadas a la acción.

El caso es que no me funcionaba y no entendía por qué, así que hice lo que haría cualquiera: irme a ver qué dice la especificación.

Vale, seamos sinceros, antes de eso hice una pequeña parada técnica en Stack Overflow 😊, pero después me fui a ver qué decía la especificación, y en la especificación se indica que se desplazará dentro del primer ancestro que tenga un scroll box (que sea scrollable), y si no, tomará como referencia el viewport.

Vale, bien, pero no dice mucho más. ¿Qué quiere decir exactamente scrollable? ¿Que tenga ya scroll en su interior o basta con que pueda tenerlo? 

Por otro lado, había leído en Stack Overflow que no va a funcionar correctamente si el elemento padre (el ancestro inmediato) tiene overflow:hidden; (por favor, hidden se lee "jidden", que más de una vez he oído a algún desarrollador decir "jaiden" y me chirría mucho, manías que tiene uno).

Volviendo al tema. Dado que mi banner estaba rodeado por dos div anidados, prácticamente iguales y con la propiedad overflow sin definir; y que en uno funcionaba y en el otro no, deduje que debía intentar averiguar qué significaba exactamente scrollable. O, al menos, intentar acotarlo al máximo.

Para ello preparé un pequeño html de ejemplo, donde todo el contenido está dentro de un elemento main, en el que hay tres banner iguales y un poco de texto:

  • El primer banner consiste solo en una imagen dentro de un hipervínculo
  • El segundo es lo mismo que el primero, pero además rodeado por un div
  • Y el tercero es igual al segundo caso, pero el div tiene una altura definida superior a la altura de la imagen (y por tanto, del enlace)

En los tres casos definí el enlace como position: sticky y con un desplazamiento superior de 80px.

main a {
position: sticky;
top:80px;
border:10px solid #1B75CE;
display:inline-block;
}

Para que en el ejemplo se vean mejor, definí un borde azul para los enlaces y uno naranja para los div:

El resultado fue el siguiente:

  • Como el primer enlace es hijo directo de main, y este tiene suficiente contenido como para provocar un scroll en la ventana, en cuanto llega a 80px del borde superior se queda fijo hasta que finaliza el scroll.
  • En el segundo caso, el enlace es hijo directo del div que lo rodea, y no hay más contenido, así que el enlace nunca se queda en una posición fija.
  • En el tercer caso, como el div es más alto que el enlace, al hacer scroll el enlace se queda fijo a la vez que el del primer caso, pero se detiene en cuanto se topa con el final de su div padre. 

Resumen y consejos finales con position: sticky

Revisa bien estos puntos para asegurarte de que nada falle:

  • Aparte de la propiedad en sí misma, recuerda definir un valor para top (si lo vas a hacer en vertical, que probablemente será lo más habitual). Sea con lo que sea, hay que definir la posición para cuando se quede fixed, si no, no funcionará.
  • Asegúrate de que ningún ancestro de tu elemento sticky tiene overflow:hidden; u overflow:auto;. Aún diría más, yo pondría en la lista de sospechososos a cualquier ancestro al que se le haya definido un overflow explícitamente.
  • Revisa que el elemento padre sea lo suficientemente grande como para que tu elemento esté sticky hasta donde lo habías planeado.
  • Como complemento al punto anterior, ojo con los ancestros que usen flexbox, ya que por defecto provocan que sus elementos hijos crezcan hasta igualar sus alturas, así que ahí no hay scroll que valga a no ser que les modifiques el valor por defecto align-items:stretch;.

No te puedo garantizar que si no te funciona se deba exactamente a alguna de estas causas, pero creo que con estas pistas se pueden solucionar la gran mayoría de las incidencias. Al fin y al cabo, la especificación todavía es un borrador y no está tallado en piedra.

Eso sí, recuerda que a día de hoy su soporte es un poco irregular aunque razonablemente bueno. Tenlo en cuenta.

Por cierto, aquí puedes descargarte el ejemplo que he usado. Espero que te resulte útil, déjame en los comentarios tu opinión o cuéntanos si has tenido alguno de estos problemas con esta propiedad. A lo mejor conoces algún detalle que a mí se me haya podido escapar.

Pablo Iglesias Pablo Iglesias es diseñador Web. Cuenta la leyenda que, anidando listas HTML en busca de la página semánticamente perfecta, provocó un agujero espacio-temporal en IE tan grande, que en Redmond tuvieron que llamar al comando SG1 de Stargate para evitar una invasión alienígena. Puedes seguirlo en twitter ( @piglesias). Ver todos los posts de Pablo Iglesias
Archivado en: Desarrollo Web

Boletín campusMVP.es

Solo cosas útiles. Una vez al mes.

🚀 Únete a miles de desarrolladores

DATE DE ALTA

x No me interesa | x Ya soy suscriptor

La mejor formación online para desarrolladores como tú

Comentarios (25) -

Miguel Hernández
Miguel Hernández

Brooooo, eres un crack, he estado teniendo este problema varios días y gracias a ti ya tengo una dirección de que tengo que revisar, gracias por tu aporte

Responder

Gracias no entendia por que no me funcionaba per ocon tus ejemplos me quedo super claro, 100% sos un crack

Responder

capooooo ! me sirvió la explicación, yo lo que le hice al contenedor padre donde esta el elemento al que le aplico el sticky fue ponerle ::after { content=""; display:block; clear:both; overflow:hidden} y arrancó bien el sticky ? vaya a saber porque no tenía cuerpo el contenedor padre no se porque pasa eso a veces en algunas divs de mi css :(

Responder

Pablo Iglesias
Pablo Iglesias

Hola Julio,

Creo que en tu caso no funcionaba porque todos los contenidos del padre estaban flotados (fuera de flujo), así que no crece en altura porque es como si no contuviese nada.

Lo que le has aplicado es un hack para limpiar el flujo del documento, crear un nuevo contexto y que tome la altura como si sus hijos no estuviesen flotados.

En este post puedes ver algo más sobre el tema: www.campusmvp.es/.../...ra-limpiar-floats-css.aspx

Además, este post sobre z-index también te puede ayudar si además tienes problemas de superposiciones porque también le influye el concepto de "contexto":  www.campusmvp.es/.../...ento-en-mi-diseno-web.aspx

Responder

Hola, estoy intentado usar sticky para un scroll horizontal y no hay manera...

Responder

Pablo Iglesias
Pablo Iglesias

Hola Vanesa,
No lo he probado en horizontal, pero a priori deberían servir las mismas recomendaciones del post pero adaptadas.
Por ejemplo, en vez de redefinir "top", redefinir "left", asegurarse de que haya un ancestro "scrollable" etc...

Responder

Gracias a estos consejos pude poner a funcionar el sticky en mi sitio web. Gracias!

Responder

Pablo Iglesias
Pablo Iglesias

¡Genial! ¡De nada! 😄

Responder

Oscar Steven
Oscar Steven

gracias Pablo eres un master estaba teniendo problemas con eso :D

Responder

Pablo Iglesias
Pablo Iglesias

De nada, un placer. Me alegro mucho de haberte sido útil. :-)

Responder

Muchas gracias amigo, me has solucionado un problema grave de manera muy rápida, te mando un saludo!

Responder

Pablo Iglesias
Pablo Iglesias

De nada, me alegro de que te haya sido útil. Saludos.

Responder

Que GENIOOOOO quedo clarísimo y me reí mucho con lo de hidden  porque, re si jajajaj.
Mil graciasss, a ver que más hay por campusmvp.es

Responder

Pablo Iglesias
Pablo Iglesias

Muchas gracias, Ezequiel 😅

Responder

Hola ya lo he usado varias veces en dispositivos de escritorio. Pero en dispositivos moviles no funciona. Por qué razón será?

Responder

Pablo Iglesias
Pablo Iglesias

Hola Walter, échale un vistazo en "Can I use" por si no tiene buen soporte en el navegador que estás usando: https://caniuse.com/?search=sticky  Hace unos años era necesario usar el prefijo -webkit- para Safari en iOS y Chrome.

De todas formas, cuando escribí el post el soporte era irregular pero ahora el soporte es muy bueno, así que probablemente alguna media query cambia alguna propiedad a un elemento de forma que se da alguno de los supuestos del post: Quizá la altura del elemento padre no es suficiente, obtiene un valor para overflow, o pasa a terner un display:flex...

Responder

Gracias!!!

Agradecido por muy buena explicación!!

Responder

Yo en mi css le tenia asignado a html y body un height del 100%, al eliminarlo position sticky funciono, si asignaba 100% a body o html individualmente funcionaba, pero al indicárselo a ambos dejo de funcionar .

Responder

Muchas Gracias :D , le agregaré solo un TOP como lo mencionas y listo, arreglado

Responder

David Rodríguez Cano
David Rodríguez Cano

Wow muchisimas gracias, no sabía por qué me estaba sucediendo pero gracias a tí ahora sí

Responder

Pablo Iglesias
Pablo Iglesias

De nada, David. Me alegro de que te haya sido útil.

Responder

Eres un GENIO, llevo 3 días investigando y como bien dices, no hay mucha información que solucione nada, todos hablan del overflow y yo tenia todos visible, hasta que entendí por tu post lo de "scrolleable", yo tenía el menú en el header, y al ser éste no scrolleable me era imposible poder hacer el menú sticky, lo he puesto en el main, como hijo directo, y ha funcionado. GENIO. Los de MDN creo que deberían revisar su explicación, porque para la gente que acabamos de empezar como yo, era incomprensible.

Un saludo,

Guillem.

Responder

Pablo Iglesias
Pablo Iglesias

Muchas gracias Guillem, me alegro de que te haya servido. Precisamente escribí el post porque es un tema muy lioso si no tienes algunos conceptos muy claros.

Responder

Muchas Gracias! si preciso había un overflow hidden  por ahí molestando  :)  lo pude solucionar gracias a ti :)

Responder

Muchas gracias!!! Lo guardo en mis recursos, porque seguramente se me presente otro día y no lo recuerde. Precisamente me estaba pasando lo del último punto de tus recomendaciones (ojo con los ancestros que usen flexbox), pero en mi caso usando un display grid, cambiando la propiedad align-items me funcionó 🙌🏼

Responder

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.