Problema con el posicionamiento absoluto de capas

  • Por
A veces el posicionamiento absoluto de capas es demasiado rígido, pues si la definición de pantalla cambia de un usuario a otro las capas pueden quedar colocadas en lugares donde no deseamos. He aquí una solución.

He recibido una consulta en mi correo sobre colocación de capas de manera absoluta, pero en la que no nos importe la definición de la pantalla del usuario y otros ir y venir de los elementos HTML. Nuestro compañero expresó su duda de la siguiente manera:

Si trabajamos con position:absolute dando un left y un top funciona si tienes tu página alineada a la izquierda. Mi página está alineada en el centro, entonces lo que sucede es que dependiendo de la resolución de pantalla que tengas (ancho de 800px,1024px,etc) me baila toda la página y no cuadra nada.

Primero que todo, debemos saber que si trabajamos con el position relative las capas se colocan en el lugar donde aparecen dentro del código HTML. De este modo, si colocamos una capa con position relative dentro de una celda de una tabla, dicha capa aparecería dentro de la celda donde la estamos colocando, independientemente del lugar donde se sitúe la celda al cambiar la definición de la pantalla.

El problema de esta solución es que la capa haría crecer la celda de la tabla donde queremos colocarla (al igual que cualquier otro elemento HTML que colocásemos dentro de la tabla) y es muy probable que nuestro diseño no nos permita este hecho. Seguramente ya habrías notado este problema y si no es así te invito a que crees la capa que intentas colocar con el atributo position a relative para ver si con eso tu problema ya está resuelto.

En casi todos los casos, la capa que intentamos colocar va a tener que tener el position absolute, porque con relative no arreglamos totalmente el problema. Entonces volvemos a el problema inicial, que era situar la capa con position absolute en el lugar exacto, independientemente de la definición de pantalla.

La solución final que propongo pasa por aplicar algún truquillo. De hecho, estuve hace unos días preguntándome sobre esa cuestión y al final encontré la solución, aunque no se me ocurrió a mi, sino que la extraje de las librerías X-Library.

La idea es un poco compleja y para su puesta en marcha debemos realizar una serie de acciones que, sinceramente, considero excesivas para un problema inicialmente sencillo. Así pues, que no asuste lo que voy a soltar a continuación, que luego trataré de explicarlo un poco mejor.

Nuestro esquema de trabajo consistirá en una capa con posición relativa, que nos servirá de "ancla" y otra con la posición absoluta, donde colocaremos el contenido final a mostrar en la capa.

La capa relativa la colocaremos en el lugar aproximado donde queramos que aparezca la capa absoluta. La capa absoluta la posicionaremos, una vez cargada la página, en un lugar próximo a la capa relativa. Por supuesto, estas acciones las vamos a tener que realizar con Javascript, que es el lenguaje que nos permite actualizar las posiciones de las capas dinámicamente.

Detenidamente

Decíamos que habría que colocar una capa relativa cercana al lugar donde tiene que aparecer la capa con position absolute. Insisto en que las capas relativas se colocan en el lugar donde las metemos dentro del código HTML, por lo que será fácil colocar la capa relativa en el lugar exacto y que este lugar sea válido para cualquier definición.

La segunda capa, la que tiene el contenido final, la pondremos inicialmente en una posición cualquiera y escondida, de manera que no se vea que está mal colocada. Una vez terminada de cargar la página, podremos acceder a la posición de la capa relativa, extrayendo sus valores top y left y colocándolos en los correspondientes top y left de la capa con posición absoluta. Una vez marcada la posición de la capa absoluta podemos volverla visible.

A la vista de la imagen siguiente, la capa con posición relativa la hemos colocado en el enlace. En realidad habría tres capas con posición relativa para poder posicionar otras tantas capas con posición absoluta. La parte que vemos sombreada de verde corresponde al espacio que abarcaría la capa relativa.

Su posición sería la que está marcada por el aspa roja que aparece en su esquina superior izquierda. Dicha posición depende del lugar donde aparezcan los enlaces en la página.

Luego, con Javascript deberíamos asignar la posición de la capa absoluta de una manera parecida a esta.

left de la capa absoluta = left de la capa relativa

top de la capa absoluta = top de la capa relativa + altura de la capa relativa

Podemos sumarle algún píxel más a la posición de la capa, si es que queremos moverla un poco abajo y a la derecha, tal como hemos visto en la imagen.

No pretendo en este artículo, muy a mi pesar y por falta de espacio y tiempo, explicar cómo se hacen esas operaciones de Javascript. Advierto que si no se conoce nada de Javascript va a ser imposible ponerse con una tarea tan tediosa como el manejo de capas. Si por el contrario, ya hemos tenido contacto con Javascript y DHTML anteriormente, no debería ser un problema realizar esas acciones.

Referencias Javascript

En DesarrolloWeb tenemos un par de manuales de Javascript, que sería necesario estudiar para empezar a introducirse en el lenguaje.

En el Taller de Javascript tenemos algún artículo sobre tratamiento dinámico de capas.

Pero sin duda, lo que mejor os va a venir para tratar con capas y su posicionamiento dinámico es utilizar algún framework Javascript, los cuales os ayudarán fácilmente a realizar cualquier tipo de operación DHTML con la certeza de que funcione bien en todos los navegadores. Os recomiendo las siguientes lecturas:

Autor

Miguel Angel Alvarez

Miguel es fundador de DesarrolloWeb.com y la plataforma de formación online EscuelaIT. Comenzó en el mundo del desarrollo web en el año 1997, transformando su hobby en su trabajo.

Compartir

Comentarios

eyagos

10/8/2002
Bueno, eso del javascript está muy bien, pero si lo que queremos es simplemente una capa con posición absoluta que se centre en la ventana del navegador, lo podemos hacer de una manera mucho más simple (y bastante curiosa por cierto):

Se trata de poner una capa con posiciones absolutas, pero sin especificarle ni la posición izquierda ni la posición superior. Estas las "heredará" automáticamente de una tabla que pondremos justo después de la capa (que estará fuera de la capa y que no tiene porque tener ningun contenido), a la que le daremos el mismo ancho que a la capa, y que centraremos en la página con el atributo align="center".

Como veis parece un poco estraño, pero funciona con IE6 y NS6. Si quereis ver como funciona, aquí teneis un ejemplo que he hecho yo (mirar el código fuente): http://users.servicios.retecal.es/decodingtv/center_absolut_layer.htm

Dr_Fasiko

09/4/2003
Creo que una manera más sencilla de centrar el contenido de una capa (como eyagos hace referencia) es centrar el contenido y fijar el ancho al 100%, me explico:

Si lo que deseamos es centrar un contenido y ponerlo a cualquier altura, podemos realizar un proceso muy sencillo.

1.- Establecemos el ancho al 100% así a cualquier resolución siempre se adaptaría al ancho de pantalla.

2.- Le indicamos que centre el contenido, así, sea cual sea la resolución, siempre lo centrará.

3.- Establecemos el alto, ya que el alto es completamente independiente de la resolución que utilicemos.



Os pongo un ejemplo:

<div style="width: 100%; top: 220px; position: absolute; visibility: visible; z-index:10" align="center">

Espero que mi explicación os sirva de ayuda.

Dr. Fásiko - webmaster de www.empanao.com

Javivi

22/4/2003
Hola gente, la mezcla de la solución que ha dado Dr_Fasiko y eyagos me ha solucionado el problema que tenía de que no se centraba ni tomaba el tamaño exacto que yo deseaba la capa, con esto me ha funcionado a la primera, era algo que lo había dejado casi por imposible por que no conozco tampoco mucho este entorno de programación, lo que he hecho ha sido introducir dentro de la capa una tabla con lo que quiero mostrar (con un ancho fijo la tabla), y la capa con un ancho del 100% y centrada en la página, así da igual el tamaño de la ventana o la configuración de la pantalla.

Un saludo y muchas gracias a todos.

Kueik

04/12/2003
GENIAL!, TREMENDAMENTE GENIAL. OS FELICITO! Porque creo sinceramente que éste era un problema que muchíssima gente tenía, entre ellos yo, por lo que os felicito de todas todas! hacia tiempo que no continuaba haciendo mi pagina web por motivos del trabajo, y hoy que ya he acabado los examenes, dios! me encuentro la solución al problema con la que la dejé. Simplemente genial!

Roberto

14/1/2004
A mí me parece realmente sencillo con JavaScript:
.-Creamos la capa con posición absoluta pero sin coordenadas.
.-Obtenemos el tamaño de la ventana, la dividimos entre dos y le restamos la mitad del ancho y/o alto de la capa.
.-Con onresize la podemos reescribir a cambiar el tamaño de la ventana.

//capa: 760*400
var x= Math.floor(document.body.clientWidth / 2) -380;
if(x<0){x=0;}
var y= Math.floor(document.body.clientHeight / 2) -200;
if(y<0){y=0;}

document.write('<div id="capa" style="left: '+x+'px; top: '+y+'px">');

Con esto lo hago yo y ningún problema.
Espero haber sido de ayuda ;-)
Saludos
Roberto

Danilo

01/11/2004
Para centralizar una pagina basta con meter todo el contenido dentro de un div con estas caracteristas (solo cerrar la equtiqueta al final de la pagina) : body { margin:0; padding:0; background:#cccccc; text-align:center; /* hack para el IE */ } #tudo { width: 760px; margin-left:auto; margin-right:auto; padding: 10px; text-align:left; /* "remedio" para el hack de IE */

Guillermo

25/4/2005
He encontrado la solución al problema. Más adelante copio unos scripts que te devuelven la posición exacta de un elemento, a partir de ahí se puede jugar con las capas.

SOLUCIÓN DE LA WEB http://www.quirksmode.org/js/findpos.html

function findPosX(obj)
{
var curleft = 0;
if (obj.offsetParent)
{
while (obj.offsetParent)
{
curleft += obj.offsetLeft
obj = obj.offsetParent;
}
}
else if (obj.x)
curleft += obj.x;
return curleft;
}

function findPosY(obj)
{
var curtop = 0;
if (obj.offsetParent)
{
while (obj.offsetParent)
{
curtop += obj.offsetTop
obj = obj.offsetParent;
}
}
else if (obj.y)
curtop += obj.y;
return curtop;
}

Oscar

21/12/2006
Yo tenía el problema de la web centrada y querer poner una capa en un punto concreto, y he conseguido ubicar la capa en donde quería y es válido para todas las resoluciones y todos los navegadores. <b>Sin javascript.</b> Ubico una capa "layer1" con posición absoluta anidada en una tabla (de esta forma "layer1" siempre aparecerá en el mismo punto, independientemente de la resolución). Después coloco la capa "layer2" (la que me interesa) anidada en "layer1" y le doy un "margin-left" en CSS para que se me separe de "layer 1" tanto como quiero. El top es independiente de la resolución... y ya está! Igual esto está mal, no soy un gran programador, pero me pareció interesante postearlo porque a mí me ha servido perfectamente. Saludos!!

theblabla

07/2/2007
Buenas tardes, me encontré con el mismo problema y la solución que le di fue la siguiente:

Pongamos el ejemplo de un formulario que consta de dos capas y que éstas están dentro de <div id="contenedor"></div>

El html seria algo asi:



<style type="text/css">
#capa1{
background-color:#CC6633;
position:relative;
left:10px;
top:10px;
height:250px;
z-index:1;
}

#capa2{
background-color:#3399CC;
position:relative;
top:-240px;/*<----Esta es toda la trama!!! */
left:10px;
height:250px;
z-index:2;
}
</style>
<div id="contenedor">
<div id="capa1">hola mundo</div>
<div id="capa2">adios mundo</div>
</div>


El tema de mostrar-ocultar es cosa del señor JS. Entonces le pedi que hiciese el trabajo sucio por mi (gracias señor JS :p ). Esto lo soporta Ie 6, FF 2.0, NS 8 (opera no lo tengo por aqui).

function showLayer(layerToShow, layerToHide){ document.getElementById(layerToShow).style.visibility="visible"; document.getElementById(layerToHide).style.visibility="hidden";
}

05/3/2007
He estado viendo el tema del JS, pero claro, ni idea de cómo aplicarlo para que se pillen esos datos que muestra el js.

Si alguien pusiera un ejemplo <html> hasta </html> nos ayudaría bastante.

Gracias

Mario

18/5/2007
Efectivamente, como ya lo han mencionado, me parece que la forma más sencilla de fijar las capas en una determinada posición es a través de una estructura de tablas. Despues de darle formato al sitio con tablas es posible ubicar una capa dentro de alguna celda con su propiedad position=relative, luego de esto es posible anidar otras capas (dentro de la capa relativa) como absolutas, el margen izquierdo y superior de las capas anidadas estara referenciado al punto superior izquierdo de la capa relativa o principal o madre (como gusten llamarle).
Una última observación es poner en cero los argumentos top y left de la capa relativa para que no se desplace de su posición original.

Este es el script que ilustra lo anterior:
<td width="570" bgcolor="#E7E6E9">

<div style="position: elative; width: 570px; height: 165px; z-index: 1; left: 0px; top: 0px" id="capa1">

<div style="position: absolute; width: 100px; height: 100px; z-index: 1; left: 10px; top: 10px" id="capa2">

xyz</div>
<p>x

</div>
</td>

Jorge Padilla

29/8/2007
Lo que tenemos que hacer es "anclar" la capa absoluta que queremos tener. Y para anclarla necesitamos una capa relativa. Me explico:

La capa relativa es la capa PADRE, que nos dará las coordenadas que necesitamos para posicionar la capa absoluta HIJO.

El concepto es que la capa HIJO es absoluta, pero no es absoluta a la página (es decir, no comienza en X=0;Y=0), si no que es absoluta a la capa en la que está anidada, a la capa PADRE (con coordenadas X=a;Y=b)

Ej:
<!--Esta es la capa PADRE, que nos va a dar las coordenadas-->
<div style="position: relative; width:150; height:165;; left:0; top:0" id="PADRE">
<a href="itinerarios.html" onmouseover="muestracapa('PADRE','HIJO')">Itinerarios de Viaje</a>


<!--Esta es la capa HIJO, que será absoluta y que colocaremos a continuación de nuestra capa PADRE por medio de JavaScript-->
<div style="position: absolute; width:auto;height:auto;background:red;visibility:hidden" id="HIJO">
NEW YORK<BR>MADRID<BR>LONDRES
</div>

</div>

Después de esto, hay que conseguir las coordenadas en las que queremos posicionar nuestra capa absoluta. Yo lo he hecho a la misma altura que la relativa y justo a la derecha donde termina menos un par de pixels, para que esté dentro de la celda.

<script>
function muestracapa(capa1,capa2)
{
var posicionX = parseInt(document.getElementById(capa1).style.left) + parseInt(document.getElementById(capa1).style.width) - 2;

var posicionY = parseInt(document.getElementById(capa1).style.top);

document.getElementById(capa2).style.top = posicionY;

document.getElementById(capa2).style.left = posicionX ;

document.getElementById(capa2).style.visibility = "visible";
}
</script>

Victoria Plaza

12/9/2007
Hola, me ha servido mucho este articulo, y para practicar he hecho una mini pagina con las dos posibilidades comentadas (usar una capa anclaje que contenga la capa dependiente, o usar cualquier otro objeto web como punto de referencia y calcular su posicion)

No se si resultara muy largo el codigo pero ahi va, listo para copiar y pegar.

<html >
<head>
<script>
/*Este script es un poco mas complicado pero sirve para cualquier capa
declarada dentro del body (no dentro de la capa anclaje!!)
Ademas con este script no necesitariamos una capa anclaje,
podriamos poner como punto de referencia cualquier imagen, celda, u objeto de
nuestra web */

function findPos(obj) { /*calcula la posicion de un objeto dentro de la web*/
var curleft = curtop = 0;
if (obj.offsetParent) {
curleft = obj.offsetLeft
curtop = obj.offsetTop
while (obj = obj.offsetParent) {
curleft += obj.offsetLeft
curtop += obj.offsetTop
}
}
return [curleft,curtop];
}

function start1() /*posiciona la capa dependiente*/
{
limpiar();
posicion= new Array();
var anclaje=document.getElementById("celda");
/* Para poner este punto de anclaje no necesitamos la capa relativa
yo he utilizado el objeto "celda" */
var submenu=document.getElementById("capaSubmenu1");
posicion=findPos(anclaje);
submenu.style.left=posicion[0] + 10 ;
submenu.style.top=posicion[1] + 40 ;
submenu.style.visibility="visible";
}
</script>

<script>
/*Este script es el mas sencillo, pero necesita que la capa dependiente
sea HIJO de la capa anclaje, es decir, que su codigo se encuentre interno a la capa anclaje */
function start2() /*posiciona la capa dependiente*/
{
limpiar();
var anclaje=document.getElementById("capaAnclaje");
var submenu=document.getElementById("capaSubmenu2");
submenu.style.left=anclaje.style.left +10 ;
submenu.style.top=anclaje.style.top +20 ;
submenu.style.visibility="visible";
}
</script>

<script>
/* oculta la capa */
function limpiar()
{
var submenu2=document.getElementById("capaSubmenu2");
var submenu1=document.getElementById("capaSubmenu1");
submenu1.style.visibility="hidden";
submenu2.style.visibility="hidden";

}
</script>
</head>

<body >
<table width=100% border="1"> <tr>
<td><a onClick="limpiar()">Quitar capa</a></td>
<td> <a id=celda>celda A </a>
<div id="capaAnclaje" style="position:relative"> Capa anclaje
<div id="capaSubmenu2" style="position:absolute; visibility:hidden">Capa2 bajo celda A</div>
</div>

</td>
<td> <a onClick="start1()" >Muestra capa1 con script1 </a></td>
<td> <a onClick="start2()"> Muestra capa2 con script2 </a></td>
</tr> </table>
<div id="capaSubmenu1" style="position:absolute; visibility:hidden">Capa1 bajo celda A</div>

</body>
</html>

Espero que sirva de resumen o aclaracion de todo este articulo

tatur2d2

14/4/2010
Basicamente CSS
Hola a todos!
Es mi primer comentario asi que espero que no cometa errores.
Bueno, hace unos meses comenze a aprender por mi cuenta html y css. Leyendo libros y manuales.
En esta parte del manual que supuse que era basico, veo q quieren solucionar esta parte usando javascript, en mi opinion si utilizaramos esto en esta parte del manual se desordenaria totalmente, pediria porfavor q reordenen este capitulo del manual, que al igual q yo muchas personas estan comenzando con css, no es muy bueno que comenzemos a utilizar otro lenguaje mas, asi sea solo para hacer un pequeño agregado.

Gracias y felicitaciones a Desarrollo web!
r2d2

Jailbreak

17/7/2010
Tamaño en porcentaje
Como están, primero que todo esta estupendo el manual, aprendí html con el manual de html y ahora estoy en las hojas de estilo, según iba avanzando un amigo me dijo que no hiciera mas la cochinada de usar tablas como separadores, y me sugirió los div, en el momento no entendí y hoy llegue a este articulo del manual y veo a lo que se refería con "agrupe secciones de texto, no use tablas"XD, y también me dio otro concejo y creo a muchos les puede servir, utilicen unidades em, que se ajustan a la resolución de la pantalla ya que como se vio en un capitulo de html se ajustan según la configuración del usuario 1em=(a la configuración del usuario por defecto), cuando se aprende a manejar esta medida es muy bueno y la que yo personalmente utilizo, porcentajes, ya que ocupa el tamaño porcentual de la pantalla no pixels la cosa es que hay que especificar tanto anchura como altura para no tener problemas de capas sobrepuestas, como me paso a mi me preocupe mucho por lo ancho y todo muy bien con diferentes resoluciones pero nunca especificaba largo y ahí tuve problemas, pero empece a especificar tanto alto como ancho y listo, bueno saludos.