Columnas CSS: position

Visita este artí­culo en http://www.estadobeta.com/2006/06/22/columnas-css-position/

Por Ismael en CSS, artículos, tips

Diagramación de columnas HTML usando el atributo position de CSS.

Mestinon For Sale Septilin No Prescription Buy Abana No Prescription Buy Online Avodart Buy Himcolin Online Hytrin For Sale Levitra No Prescription Buy Proscar No Prescription Buy Online Lopid Buy Zebeta Online Azulfidine For Sale Karela No Prescription Buy Clomid No Prescription Buy Online Loxitane Buy Actoplus Met Online Capoten For Sale Celebrex No Prescription Buy Retin-A No Prescription Buy Online Prednisone Buy Levitra Online Prednisone For Sale Tricor No Prescription Buy Tramadol No Prescription Buy Online Lamisil Buy Inderal Online

En el artículo anterior de esta serie vimos cómo diagramar columnas (X)HTML usando el atributo float de CSS. La técnica en cuestión, sin embargo, tiene una serie de desventajas: aún cuando se puede cambiar la disposición de las columnas usando los valores left o right de los floats, el control exacto de los elementos en pantalla sigue dependiendo del orden de éstos en el código HTML. Así, para lograr el diseño a tres columnas del ejemplo anterior (un area central con columnas angostas a cada lado), los elementos HTML debían ordenarse en el mismo sentido:


<div id="container">
  <div id="columna-1">
    Columna 1
  </div>
  <div id="contenido">
    Contenido
  </div>
  <div id="columna-2">
    Columna 2
  </div>
</div>

Esto supone una restricción sobre la estructura de nuestros documentos: el XHTML debe considerar el resultado visual que queremos lograr. No sólo eso; los motores de búsqueda modernos tienden a dar mayor importancia al contenido situado en las primeras líneas del documento. El método a tres columnas usando float nos obliga a poner nuestro contenido principal más abajo que la primera columna lateral, que pudiera ser no tan relevante en términos de contenido.

Otro problema común de esta técnica es el control de los anchos de cada columna. Si queremos un ancho “líquido” -donde el documento se adapta al ancho disponible en el monitor- podemos usar porcentajes o unidades relativas como el em pero esto significa que tanto el contenido central como las columnas laterales aumentarán su ancho en función del ancho total del documento. Para la clásica barra lateral de blogs y portales esto es una pésima solución.

La solución a estos problemas es un acercamiento ingenioso pero totalmente diferente, usando una combinación de los atributos position y margin. Primero que nada, reestructuremos el XHTML para dar prioridad al contenido central en el código fuente:


<div id="container">
  <div id="contenido“>
    Contenido
  </div>
  <div id=”columna-1″>
    Columna 1
  </div>
  <div id=”columna-2″>
    Columna 2
  </div>
</div>

Ok. Ahora el contenido central está primero y hemos optimizado un poco mejor para los buscadores. A continuación incluímos el CSS necesario para situar las dos columnas a cada lado del contenido central.


/*
Primero seteamos el contexto de posición para las columnas, usando el #container
--------------------------------------------------*/
#container {
	position:relative;
}
/*
Damos posición absoluta a las columnas (con respecto al #container)
--------------------------------------------------*/
#columna-1, #columna-2 {min-height:400px;}
#columna-1 {
	position:absolute;
	top:0;
	left:0;
	width: 200px;
	background: yellow;
}
#columna-2 {
	position:absolute;
	top:0;
	right:0;
	width:200px;
	background: orange;
}
/*
Contenido central
--------------------------------------------------*/
#contenido {
	background: red;
	min-height: 400px;
}

Aquí pueden ver el resultado.

¿Qué hicimos? position puede tener varios valores (absolute, relative, static, fixed). Todos los elementos HTML tienen su atributo position en static por default. absolute y relative “liberan” a los elementos del orden del código fuente. Una vez que un elemento tiene su position en cualquiera de esos dos valores, se activan los atributos left right, top y bottom que podemos usar para manejar las coordenadas del elemento.

¿ coordenadas con respecto a qué? Aquí es donde está el truco. Cuando “activamos” la posición de un elemento, este se posiciona con respecto al primer elemento superior que también esté posicionado con position:absolute; o position:relative;(*). Si no hay un elemento superior posicionado, el browser utiliza el body como contexto para la posición, es decir el valor left:20px; equivaldría a mover el elemento 20 pixeles desde la esquina superior izquierda del area visible del navegador. Para este ejemplo, sin embargo, ponemos position:relative en el #container y así podemos posicionar las columnas laterales con respecto a ese elemento -que contiene todo el documento-. Esto será útil en un momento cuando modifiquemos el ancho de este elemento contenedor.

Entonces, si ven el documento en su estado actual observarán que las columnas se sitúan mágicamente a cada lado del documento. Si modificamos el ancho de #container veremos cómo estas columnas mantienen su posición con respecto al DIV que las contiene:


#container {
	position:relative;
        margin: 0 auto;/* esto es para centrar este DIV en el BODY */
        width: 770px;
}

Aquí puedes ver los cambios.

Pero falta un detalle: las columnas laterales están arriba del contenido central. Si tuvieramos más texto en el DIV central (#contenido), veríamos como éste se pierde bajo las columnas. Lo que tenemos que hacer es dejar márgenes suficientes a cada lado de #contenido para dejar espacio para las columnas. Recuerden: las columnas están posicionadas absolútamente, lo que las hace efectívamente invisibles para el #contenido. Sabemos que cada columna tiene un ancho de 200px. Agregaremos márgenes de 210px a cada lado de #contenido para incluír un espacio entre éste y las columnas:


/*
Contenido central
--------------------------------------------------*/
#contenido {
	background: red;
	min-height: 400px;
	margin: 0 210px;
}

Finalmente, utilizaremos porcentajes en el ancho del contenedor #container. Esto nos dará un diseño “líquido” (flexible) donde el contenido central se adapta al ancho de la ventana (ideal para altas resoluciones de pantalla) pero las columnas laterales se mantienen en 200px.


#container {
	width: 80%;/* 80% del BODY */
	min-width:700px;/* ancho mínimo - no funciona en IE */
	margin:0 auto;
	position:relative;
}

Voilà! Prueben cambiando el tamaño de la ventana del navegador.

(*) ¿Cuál es la diferencia entre relative y absolute? Con relative, puedes mover libremente un elemento, pero el espacio original que éste ocupaba seguirá ocupado - como un “fantasma” del elemento. absolute, por otro lado, hace que los demás elementos “no vean” al elemento posicionado y éste “flota” sobre el documento de la misma forma en que, por ejemplo, se superponen las capas de Photoshop, sin tocarse. En otras palabras, con relative la posición del elemento es relativa al espacio que ocupa originalmente en el código fuente, mientras que con absolute es relativa al elemento contenedor o, en su defecto, al body. Recomiendo hacer el experimento de posicionar y mover un elemento usando relative y absolute alternatívamente.

36 comentarios para “Columnas CSS: position”

  1. GravatarSebastian Dice:

    Uffff, esto se pone interesante. A ver no me quedó muy claro el tema de las posiciones. Cuando ponemos psition:absolute; se liberan top, right, bottom y left. Cual es el valor por defecto que tienen estos valores? “0″. Si observan bien veo que la #columna-1 tiene top:0 left:0 por lo tanto esta posicionado bajo esas cordenadas dentro del container? cierto. es por eso que en #columna-2 top:0 right:0 se invierte la posición?

    en todo caso es una pregunta al vuelo, entiendo lo que sucede, tengo que ponerme a trabajar para notar las diferencias.
    Saludos, muy buenos articulos Ismael.

  2. GravatarIsmael Dice:

    Sebastian, respondiste solo todas tus preguntas :)
    Hay que destacar que si ocupas left, no puedes ocupar right (y viceversa). Lo mismo pasa con top y bottom.

    No se usa en este ejemplo pero tu puedes incluso poner valores negativos a los elementos posicionados. Por ejemplo left:-30px;

  3. Gravatarwachunei Dice:

    Lo que más me costó de aprender cuando emepecé con el CSS, fue la relación de las posiciones entre elementos de bloque con position: abosolute; y relative, porque si un elemento tiene posición absoluta, es relativa al body de la web, pero cuando hay un elemento con position: absolute; dentro de uno con position: relative;, es relativo a ese elemento (al padre, que es lo que se hace con el #container).

    O sea se deduce que los valores default son static para los elementos de bloque y relative para el body.

    Ojalá expliques la posición fixed, que es hija de la absoluta.

  4. GravatarHector Vergara R. Dice:

    Si no me equivoco, fixed es como absolute, pero respecto al body, no al contenedor.

    Ademas creo que la propiedad position: fixed; no es muy bien entendida por IE 6 (relacionado: quirksmode)

    saludos!

  5. GravatarIsmael Dice:

    Wachunei: un elemento absolute es relativo a cualquier elemento superior que sea relative O absolute. Un elemento relative, por otro lado, es relativo a la posición que ocupa normalmente en el código fuente (HTML). A diferencia de un static, sin embargo, un elemento relative puede ser movido de esa posición usando sus coordenadas, y el espacio original que ocupaba seguirá “lleno” como si ele elemento aún estuviera ahí.

    Como bien dice Hector, fixed es siempre relativo a la ventana, o sea el elemento permanece en el mismo lugar sin importar los scrolls. También es cierto que fixed no está bien soportado por Internet Explorer, algo que comúnmente se soluciona con un poco de Javascript, como en los comentarios fijos de Snook.ca o el Drag&Drop de Panic.

  6. Gravatarwachunei Dice:

    No sabía que un elemento absolute puede ser relativo a otro absolute, voy a experimentar :P.

    Sobre IE: En mi caso, el css de mi blog lo hago válido por la W3C y que cada browser lo interprete como quiera, así el mismo usuario va encontrado el browser adecuado, lo malo es que hay webs hechas para IE, que cuando gente las vea con un browser que siga los estándares, va a volver a IE para verlas “bien”.

    (Me gusta este blog :))

  7. GravatarJosé Luis Dice:

    Según lo que me acuerdo la barra inferior de Panic no ocupa javascript para mantenerse fija. Digo “lo que me acuerdo” porque hace un tiempo investigue la página e hice mis propias pruebas para lograr una barra inferior fija.
    De hecho, puedes deshabilitar javascript y entrar a Panic con IE y aun así la barra de abajo se queda fija.
    El secreto de la barra de Panic está en un hack, que se puede encontrar en: http://tagsoup.com/-dev/null-/css/fixed/

  8. GravatarIsmael Dice:

    José Luis: excelente link, gracias! No conocía ese truco, aunque me preocupa que al usarlo no puedes seguir usando position: absolute; en su forma tradicional (al menos para IE6, según lo que dice en ese sitio).

  9. GravatarJosé Luis Dice:

    Sí. Ese es un problema grave. De hecho, en su momento yo descarté el uso de ese hack.

  10. GravatarJosé Luis Dice:

    Está de más decir que todavía estoy buscando una mejor opción (ojalá sin uso de javascript).

  11. GravatarSebastian Dice:

    Hacía tiempo que no comentaba…trabajo…
    Gracias a este tutorial ya he podido desarrollas varios ejercicios en IE y todo funciona impeque. Se me ocurrió poner un footer en la página que estoy haciendo pero algo anda mal.
    Solo se desplaza (hacia abajo) cuando el contenido se alarga, pero cuando la columna-1 se alarga el footer queda fijo.
    What’s up? he probado varias cosas pero aún no he podido descubrir que es.
    Saludos.

  12. GravatarIsmael Dice:

    Lo que pasa es que la columna lateral tiene position:absolute, o sea está flotando sobre las otras. Para el resto de los elementos, es como si esa columna no existiera y por lo tanto el footer no tiene cómo saber si la columna lateral crece o se achica. Así como la técnica de los floats tenía sus inconvenientes, el problema del footer es uno de los inconvenientes de usar position.

    ¿Soluciones?

    1. Mover la columna o el footer para que no se superpongan.
    2. Cuidar el contenido de la columna para que no sobrepase al footer.
    3. Usar JavaScript para calcular la extensión de la columna y ajustar el footer.
    4. Dar un min-height al contenido para que empuje al footer hacia abajo, más allá de la columna.
    5. Otras que no se me han ocurrido (si se te ocurre me dices!).

  13. GravatarSebastian Dice:

    Ok, estuve revisando los puntos que me recomiendas y pueden ser buenas soluciones, ahora el tema del contenido es algo que puede ser dificil de controlar, a si es que la mejor fue darle un min-height al contenido con un estilo aparte para ese caso.
    Otras que se me ocurren:

    1. Sacar el footer, jajaja.
    2. Darle la soucion que se discutia mas arriba de dejarlo con un fixed, pero puede ser un tanto agotador por la funcion que tiene, ya que es info muy secundaria.

    Me quedo con el min.height.
    Gracias.
    Saludos.

  14. GravatarMiguel Inostroza G. Dice:

    Hola seba esta kedando muy bueno tu blog felicitaciones.

  15. GravatarSebastian Dice:

    Gracias Miguel, en todo caso solo me falta acomodarlo para que se vea en IE, por ahora (y ojala sempre) lo pueden disfrutar en Firefox.
    Felicitaciones también por tu proyecto.
    Saludos.

  16. GravatarElizabeth Dice:

    Magnífico artículo …
    El primer ejemplo no me funciona en IE6 :o(
    A alguién le sucede lo mismo?

    Saludos.

  17. GravatarJaime Dice:

    hola Ismael, generalmente he encontrado acá lo que necesito, pero ahora parece que no tiene que ver con columnas, necesito poner una imagen de fondo en el body, esta debe ser de aprox 1280px de ancho, pero el template es de 900 aprox de ancho, con la posición no tengo problemas, excepto cuando bajo el tamaño del browser a un ancho menor de 900px y el fondo disminuye proporcionalmente con el navegador y ya no calza con el ancho de 900px, necesito recomendaciones. si dejo el bg en el body o agrego otra definición para el fondo, no se, acepto sugerencias.
    saludos y gracias por tu Blog.
    JAC

  18. GravatarIsmael Dice:

    Elizabeth: puedes ser más específica? Qué es lo que no funciona?

    Jaime: no se si te sigo, pero me da la impresión de que estas poniendo la imagen en el HTML? Si es así, sácala de ahí y ponla en el atributo background del elemento body, en tu hoja de estilos:

    
    body {
        background: url( imagen.gif ) left top no-repeat;
    }
    
    

    De todas maneras no me queda claro el problema en su totalidad.

  19. GravatarJaime Dice:

    pa empezar, gracias por responder tan rápido. Parece que me expliqué mal, la tengo en la hoja de estilo, está tal cual, pero el problema que tengo es que al disminuir el ancho el atributo center se mantiene, incluso bajando sobre el ancho del MAIN, entonces si tenemos el main con un ancho de 900px y bajo el browser por debajo de ese valor, digamos a 500px, en bg se vera en su parte del medio por 500px y no en la correspondencia de diseño con el Main, algo me resulto ahora, pero no con el body, mira:
    body {
    margin:0px;
    }
    .main {
    background-image: url(bg.jpg);
    background-repeat: no-repeat;
    background-position: center top;
    min-width:700px;
    margin:0px;
    height:600px;
    }
    .main2 {
    background-repeat: no-repeat;
    background-position: center top;
    width:700px;
    margin:0px auto;
    background-color:#990000;
    }

    si alguien lo puede depurar para que funque con el body, bienvenido sea, además no funca en explorer para Mac, safari OK (trabajo en PC y no estoy en la pega ahora, ufff)

  20. GravatarIsmael Dice:

    Jaime: qué tipo de imagen es? La estas usando para definir visualmente el ancho o contorno del diseño? Si es así, claro que el diseño se rompe al disminuir el ancho del main, ya que debe haber una correspondencia entre el ancho de main y la imagen. Si ese es el caso, debieras considerar la opción de usar 2 imagenes para el fondo aplicadas a main y un div directamente dentro de main (main2?). El ancho se lo das a main. La primera imagen está en main alineada con left top, la otra dentro de main2 alineada con right top. De esta manera sin importar el ancho de main y su posición en el body, se creará la ilusión de un fondo o contorno adaptable al ancho de tu diseño.

    Pero mientras no vea el caso puntual no estoy seguro si te sigo.

  21. GravatarJaime Dice:

    Sip, le diste en el clavo, probé y rebien, gracias por el dato y para terminar excelente Blog, las discusiones que se arman son rebuenas, saludos del sur.
    JAC

  22. GravatarAilyn Dice:

    Hola soy nueva por aqui y quisiera hacer una preguntita,
    Antes del footer de mi pagina tengo dos secciones encerradas en dos columnas, necesito que estas vayan parejas, es decir que se acomoden ambas tomando el largo de la que contenga la noticia mas larga(es decir de la columna mas larga)

  23. GravatarAilyn Dice:

    que podria hacer para resolver este problemita?
    Les agradeceria la ayuda
    A proposito esta muy bueno el debate

  24. GravatarElizabet Dice:

    El primer ejemplo, en IE6, se me rompe totalmente el maquetado.
    La columna1 aparece casi pegada a la columna2.

    Saludos

  25. GravatarJose Luis Dice:

    Hola…
    Felicidades por el artículo, me ha ayudado a entender muchas cosas.
    Después de leer todos los post relacionados, me entraron las ganas de preparar una buena estructura para las próximas páginas que tengo que hacer.
    Lo primero, he preparado una solución para lo que pregunta Ailyn y solucionar problemas como este o este. Yo lo he solucionado con un pequeño script en javascript que asigna a las tres columnas el valor de la que tenga mayor altura. El script es el siguiente:

    document.getElementById('contenido').style.height = 'auto';
    document.getElementById('columna-1').style.height = 'auto';
    document.getElementById('columna-2').style.height = 'auto';
    var alturaMax = document.getElementById('contenido').offsetHeight;
    if (alturaMax
    Siendo la estructura html la siguiente:

    Cabecera

    Contenido

    Columna 1

    Columna 2

    Pie


    El resultado tras aplicarle el script es este cuando el contenido central es el más largo de todos, o este cuando el contenido de los contenedores laterales es más grande.
    ¿Qué os parece ésta solución?
    Ahora me encuentro con un problema. Le he añadido una cabecera y un pie al diseño que se proponía en un principio (ver), pero no se de qué forma hacer que no se haga más alto del 100% cuando el contenido de las 3 columnas no es lo suficientemente largo como para ocupar todo el espacio. ¿De qué forma podría solucionar eso? He probado meter el

    ...


    dentro de un contenedor principal y darle a éste un min-height: 100%;, pero no me funciona.

    Un saludo.

  26. GravatarJose Luis Dice:

    Ups… no ha salido bien el codigo javascript:

    document.getElementById('contenido').style.height = 'auto';
    document.getElementById('columna-1').style.height = 'auto';
    document.getElementById('columna-2').style.height = 'auto';
    var alturaMax = document.getElementById('contenido').offsetHeight;
    if (alturaMax

    y las etiquetas html tampoco se muestran bien, pero son las mismas que las del inicio de éste artículo.

  27. GravatarJose Luis Dice:

    Vaya, no consigo poner el javascript como código, a ver si así…
    document.getElementById(’contenido’).style.height = ‘auto’;
    document.getElementById(’columna-1′).style.height = ‘auto’;
    document.getElementById(’columna-2′).style.height = ‘auto’;
    var alturaMax = document.getElementById(’contenido’).offsetHeight;
    if (alturaMax

  28. GravatarJose Luis Dice:

    aaaa, ya se por qué no se muestra, resulta que el menor que (’\

  29. GravatarIsmael Dice:

    Jose Luis, está buena tu solución.
    Para los caracteres < y > tienes que usar las entidades &lt; y &gt;, respectivamente.

  30. GravatarJose Luis Dice:

    Gracias, de todas formas, he encontrado una solución mucho mejor, en la que únicamente se utiliza CSS. Ahora estoy trabajando en ella para colocar la columna central en primer lugar dentro del código, como explicas en uno de tus artículos, para el posicionamiento en los buscadores.
    Si le quereis echar un vistazo: ejemplo
    Pero continúo teniendo el mismo problema; no encuentro la forma de expandir el contenido verticalmente para que se ajuste a la altura del navegador.
    ¿Podeis echarme una mano?

  31. Gravatarmatias Dice:

    ahora ya comprendo todo.
    muchas gracias ismael.
    :)

  32. GravatarPosition: absolute « Taller de produccion web UNIACC Dice:

    […] una descripción más completa de la técnica y código de ejemplo, pueden ver éste artículo en mi […]

  33. GravatarVictor Dice:

    Ismael gracias por la info. Una pregunta ¿En la estructura #container trato de dar valores en px al width pero no me funciona. ¿Tendría que tener los parámetros definidos como px o % ? O puedo tener cada uno de distinta forma…

  34. GravatarIsmael Dice:

    Victor, si le das un width en pixeles, debiera funcionar. Revisa que no tengas un error de sintaxis en CSS o en la estructura HTML. Si quieres lo vemos en clases.

  35. GravatarJOSE QUIROZ Dice:

    ALGUIEN SABE COMO PUEDO REGRESAR LA PANTALLA A SU POSICION ORIGINAL, SE ME GIRO A 90 GRADOS

  36. Gravatarssss Dice:

    sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss

Deja un comentario

XHTML: puedes usar estas etiquetas: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>