Columnas CSS: position
Visita este artículo en http://www.estadobeta.com/2006/06/22/columnas-css-position/
Por Ismael en CSS, artículos, tipsDiagramación de columnas HTML usando el atributo position de CSS.
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;
}
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.
body. Recomiendo hacer el experimento de posicionar y mover un elemento usando relative y absolute alternatívamente.
- Servicios:
- Comentarios RSS
- Menear!
- Del.icio.us

6/22/2006 at 7:47 pm
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.
6/23/2006 at 12:33 am
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;
6/23/2006 at 10:15 pm
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;yrelative, porque si un elemento tiene posición absoluta, es relativa al body de la web, pero cuando hay un elemento conposition: absolute;dentro de uno conposition: 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
staticpara los elementos de bloque yrelativepara el body.Ojalá expliques la posición
fixed, que es hija de la absoluta.6/24/2006 at 4:26 am
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!
6/24/2006 at 5:13 am
Wachunei: un elemento
absolutees relativo a cualquier elemento superior que searelativeOabsolute. Un elementorelative, por otro lado, es relativo a la posición que ocupa normalmente en el código fuente (HTML). A diferencia de unstatic, sin embargo, un elementorelativepuede 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,
fixedes siempre relativo a la ventana, o sea el elemento permanece en el mismo lugar sin importar los scrolls. También es cierto quefixedno 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/24/2006 at 4:25 pm
No sabía que un elemento
absolutepuede ser relativo a otroabsolute, 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 :))
6/24/2006 at 4:34 pm
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/
6/24/2006 at 8:11 pm
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).6/24/2006 at 10:19 pm
Sí. Ese es un problema grave. De hecho, en su momento yo descarté el uso de ese hack.
6/24/2006 at 10:21 pm
Está de más decir que todavía estoy buscando una mejor opción (ojalá sin uso de javascript).
6/30/2006 at 10:36 pm
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.
6/30/2006 at 10:54 pm
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 usarposition.¿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-heightal 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!).
7/2/2006 at 4:29 pm
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.
7/2/2006 at 6:33 pm
Hola seba esta kedando muy bueno tu blog felicitaciones.
7/3/2006 at 3:49 pm
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.
9/26/2006 at 9:21 pm
Magnífico artículo …
El primer ejemplo no me funciona en IE6 :o(
A alguién le sucede lo mismo?
Saludos.
9/27/2006 at 5:30 pm
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
9/27/2006 at 5:37 pm
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:
De todas maneras no me queda claro el problema en su totalidad.
9/27/2006 at 6:20 pm
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
centerse 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)
9/27/2006 at 7:03 pm
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.
9/27/2006 at 8:55 pm
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
9/28/2006 at 3:32 pm
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)
9/28/2006 at 3:34 pm
que podria hacer para resolver este problemita?
Les agradeceria la ayuda
A proposito esta muy bueno el debate
9/28/2006 at 4:48 pm
El primer ejemplo, en IE6, se me rompe totalmente el maquetado.
La columna1 aparece casi pegada a la columna2.
Saludos
10/22/2006 at 11:08 am
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.
10/22/2006 at 11:11 am
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.
10/22/2006 at 11:12 am
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
10/22/2006 at 11:16 am
aaaa, ya se por qué no se muestra, resulta que el menor que (’\
10/22/2006 at 5:36 pm
Jose Luis, está buena tu solución.
Para los caracteres < y > tienes que usar las entidades < y >, respectivamente.
10/23/2006 at 7:58 am
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?
4/7/2007 at 4:51 pm
ahora ya comprendo todo.

muchas gracias ismael.
5/18/2007 at 2:20 am
[…] una descripción más completa de la técnica y código de ejemplo, pueden ver éste artÃculo en mi […]
6/8/2007 at 8:55 pm
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…
6/8/2007 at 10:46 pm
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.
6/12/2007 at 7:50 pm
ALGUIEN SABE COMO PUEDO REGRESAR LA PANTALLA A SU POSICION ORIGINAL, SE ME GIRO A 90 GRADOS
7/24/2009 at 12:06 pm
sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss