Posición relativa de un elemento con position:fixed

En muchas webs se suele ver el uso de ‘position:fixed’ para mantener visible un elemento en todo momento aunque se haga scroll en la página. Por ejemplo, podemos ver este efecto en la web de Privalia, donde el menú de navegación permanece siempre a la vista. El problema de ’position:fixed’ es que la mayor parte de las veces necesita la ayuda de JavaScript para que podamos lograr el efecto que generalmente deseamos. En el ejemplo de Privalia, el elemento con ’position:fixed’ se mantiene fijado al viweport pero respecto a un elemento padre para no pisar la cabecera o el pie de la página, algo que hay que hacer mediante JavaScript.

Es por ello, que creo que sería interesante plantear un cambio en la especificación, de forma que ’position:fixed’ adquiera posición y dimensiones relativas al elemento parent inmediato con ‘position:relative’ manteniendo la posición dentro del área del viewport.

En el siguiente ejemplo, vemos el funcionamiento normal de ’position:fixed’ sin el apoyo de JavaScript, en el que el elemento con ‘position:fixed’ se muestra siempre en la misma posición respecto al viewport al mover los scrolls del ejemplo. En este ejemplo la parte relevante del código es únicamente el CSS del elemento fijado.

.fixed{
	position: fixed; 
	top:100px;
	width: 80px
}

Los dos problemas de este CSS, respecto al problema que se plantea, es que tanto la posición top como la dimensión width son relativas al viewport y no a un elemento parent, por lo que no podemos conseguir un efecto de un elemento fixed respecto al elemento parent. El elemento siempre están en la misma posición respecto al viewport y no podemos hacer más interacción al respecto sobre él.

Acceder a demo

En el siguiente ejemplo, hemos usado JavaScript para conseguir el efecto que deseaba sobre el elemento con ‘position:fixed’. El elemento se mantiene visible dentro del viewport pero dentro del área del elemento parent. De forma que si el elemento parent sale del viewport el elemento con ’position:fixed’ también sale con él. Podemos comparar el comportamiento de ambos ejemplos moviendo los scrolls vertical y horizontal. En muchos casos nos solemos olvidar del scroll horizontal, como en el caso de Privalia. Además de la posición, hay que tener en cuenta el ancho del elemento con ‘position:fixed’ cuando el parent tiene un ancho en porcentajes.

	$(document).ready(function(){
		var top,bottom, y, page;
		var left = $('.tofix').offset().left;
		tofixwidth();
		$(window).scroll(function (event) {
			// what the y position of the scroll is
			controlArticlePositions();			
			// whether that's below the form
			if (y >= top && y<=bottom && y > page) {
				$('.tofix').addClass('fixed');
				//control horizontal scroll
				tofixl =  left-x;
				$('.tofix').css('left', tofixl);
			} else {
				$('.tofix').removeClass('fixed');
			} 
		});
		$(window).resize(function() {
			tofixwidth();
		});
		function controlArticlePositions(){
			page = $('.page').offset().top;
			pageb = $('.tofix').height();
			top = $('.tofix').offset().top;
			bottom = page + $('.page').height() - pageb;
			y = $(window).scrollTop();
			x = $(window).scrollLeft();
		}
		function tofixwidth(){
			$('.tofix').css('width', '');			
			var sidebarW = $('.tofix').closest('.sidebar').css('width');
			$('.tofix').css('width', sidebarW);
		}
	});

Acceder a demo

Tags: ,

5 comentarios en “Posición relativa de un elemento con position:fixed”

  1. Buenos días.

    Me podeis ayudar con lo siguiente?

    Tengo una ul con unos cuantos li con titulos que tienen unos vinculos a cada descripcion en un listado, y me funciona bien, es decir cuando hago click en uno de los li, se desplaza el texto hasta donde está su correspondiente descipcion, pero necesito que no llegue hasta el top, sino que se quede unos 100 px más abajo, ya que tengo una barra de navegacion fija arriba de la pagina, y cuando el texto se coloca en el top, se queda detras de la barra que tengo fija. Hay alguna manera de que cuando le jaga click lleve el texto al top + una distancia?

    No se si me he explicado bien, espero que si.

    Gracias de antemano

  2. Juan dice:

    Hola! Estoy trabajando con un menú parecido a la de la web que pusiste de ejemplo, tipo fixed en el top de la página, el problema es que obviamente interrumpe el flujo de los elementos que le siguen, lo cual arreglé (Visualmente) poniéndole un padding de 80 px al elemento que sigue inmediatamente después de mi menú (Que mide de altura, 80 px naturalmente)… Como digo, es un arreglo visual, pues a la hora de funcionamiento sigue dañando el flujo normal, los anchors no funcionan correctamente, etc.. Pues todo aparece siempre corrido 80px.. Alguna idea de cómo hacer que los elementos fluyan de manera natural como si la posición del menú fuera relative? Un saludo!

  3. sonickseven dice:

    olle amigo se te olvido especificar que se tenia que hacer una clase en css que se llame .fixed!!! y por cierto solo funciona con paginas dimencionadas en porcentajes y no me sirve por que yo la tengo en pixeles :/ pero bueno gracias de todas maneras. la pudieras hacer en pixeles tegaradeceria

    • PoseLab dice:

      Hola sonickseven

      Creo que no has entendido el artículo. En la primero demo se muestra el funcionamiento actual de position:fixed y para mostrarlo se usa el class .fixed. Pero es en la segunda demo donde se utiliza la función javascript que emula el funcionamiento que me gustaría ver en CSS y que al poco de escribir este artículo lo implementó Google Chrome como position:sticky, aunque todavía no hay ninguna especificación al respecto. En cuanto al uso de porcentajes, los he usado para mostrar que una de las características que debe soportar este comportamiento es el redimensionamiento del ancho de la caja respecto al padre, así que si funciona con porcentajes tiene que funcionar con píxeles.

Deja un comentario