en CSS

Problema float css

Repasaremos algunas soluciones al problema de los float que desbordan su contenedor.

Muchos de vosotros conoceréis este problema y las viejas soluciones, como añadir un elemento con clear: both o aplicar un attributo overflow, y habréis sufrido la contrariedad del primero y las inconsistencias del segundo.

El problema consiste básicamente en la pérdida de layout del elemento flotado. Así­, una imagen a la que le hemos aplicado la propiedad float, no forzará el tamaño de su contenedor. Podemos ver el efecto en el siguiente ejemplo:

Imagen con float de ejemploLorem ipsum dolor sit amet, consectetur adipiscing elit.

Vamos a repasar cada solución y ver cuando podemos usarlas y cuando no.

Clear: both div

Consiste en añadir un <div> u otro elemento html vacío tras cada contenido flotado con la propiedad CSS clear: both. De esa forma fuerza al contenedor que aparentemente engloba todo el contenido.
Desaconsejo esta solución totalmente ya que implica añadir html innecesario que, si no por el peso extra que puede llegar a añadir, que sería poco, sí por una cuestión de limpieza a la hora de trabajar y mantener el código.
Usarlo en el elemento siguiente, por ejemplo en cada encabezado Hn, tampoco es recomendable ya que podrí­amos querer flotar esos mismos tí­tulos a la derecha de una imagen.
Sin embargo hay una solución basada en clear:both no tan intrusiva: el nuevo clear fix, que utiliza la pseudoclase :after de CSS para crear un nuevo elemento al que aplica el clear:both. Funciona sin problema para todos los navegadores modernos incluyendo IE8 o superior.

Overflow: hidden

El uso del overflow fue la solución sugerida por Alex Walker quién también repasa otras soluciones de distintos Gurus del CSS. ɉsta concretamente es de Paul O’Brien. Consiste básicamente en devolver el layout al contenedor del texto flotante aplicando la propiedad overflow:hiden/auto.

Resulta muy útil cuando necesitas flotar texto alrededor de una imagen y es probablemente una de las soluciones más recurrentes. Sin embargo tras algo de análisis y testes, vemos algunas inconsistencias en diseños más elaborados.

Cuando encontré esta solución al problema de los floats, me pareció un error conceptual usar un overflow:auto/hidden… ya que no es nuestra intención ocultar un contenido que sobrepase de un espacio fijo o mostrar el scroll, cosa que si quisiéramos hacer se contradecirí­a con la necesidad inicial de hacer crecer el contenedor en función de su contenido. Y efectivamente no podremos usarlo en conjunto con un position: absolute negativo para posicionar algún elemento fuera de su marco, ya que todo aquello que salga de dicho marco quedará oculto tras él.

Por otro lado choca con otras técnicas.  Por ejemplo, cuando necesitamos un min-heigh para evitar usar Expresiones dentro de nuestro CSS para IE6 usábamos sencillamente el atributo height, si este height lo combinamos con un overflow:auto,  al sobrepasar el contenido la altura definida obtendremos un escroll indeseado que nos obliga a contrarrestar ese overflow: auto con un overflow: inherit, que es un valor que IE6 no reconoce y por lo tanto nos permite “hackear” el valor. Con la llegada de IE7, que ya responde a min-height, nos encontramos con que height nos fuerza una altura fija que no se expande con el contenido. Razón por la cual nos vemos obligados a hacer la excepción para IE6 y usar min-height para el resto de navegadores.

Aún así, es una solución válida en la mayoría de los casos en los que usamos correctamente float para dejar fluir el texto alrededor de una imagen. Yo mismo he acabado adoptándola.

Display: table-cell

Os comentaba que overflow me sugería un error de concepto. Os explico pues una de las soluciones que yo vengo usando de un tiempo a esta parte. Si analizamos qué es lo que queremos qué haga nuestro elemento contenedor, obtendremos la solución a nuestro problema. Si analizamos un elemento y buscamos su esencia, veremos que muchos de sus atributos son puramente decorativos, font, background, border, width, heigth… otros se refieren a su posición en el espacio y a su relación espacial con otros objetos, como position, left, right o float, y otros a su interacción con el contenido como sucede con overflow, pero ninguno de ellos lo define como objeto, como elemento. Para entendernos, una persona puede ser alta, baja, negra, blanca, tener varicela, llevar zapatos o ir descalza, incluso tener uno u otro sexo o “incluso ambos”, gustarle un tipo de alimentos o interactuar con sus mascotas de una forma u otra, pero seguirá siendo una persona. No será un perro, ni un gato.

En Html no tenemos la misma variedad de especies, pero sí­ tenemos 3 tipos de elementos básicos, los elementos de bloque, los elementos en lí­nea y las tablas. A diferencia de los seres vivos, un elemento html tiene la propiedad de trasformarse genéticamente y mostrarse como aquello que no es gracias al atributo display de CSS, que además nos ofrece un par de híbridos, pero la compatibilidad de los navegadores es poca y defectuosa como nos muestran nuestros amigos de kirskmode.org.

Si observamos el comportamiento y las propiedades de los 3 distintos elementos veremos que hay uno que se comporta exactamente como necesitamos. Es el <table> y sus hijos. Estamos llegando pues a una solución compatible con todos los navegadores que respetan los estándares, tanto los basados en Gecko como en WebKit o Presto y que, puesto que el problema de los floats no afecta a IE6/7, es tan sencilla y limpia como aplicar un display:table;

Aquí­ tenéis el ejemplo:

Lorem ipsum dolor sit amet, consectetur adipiscing elit.

<div style="display: table;">
<img style="float: left;" src="URl_de_la_imagen" width="100" /> Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</div>

Actualización:
Actualizo este artí­culo aquí­ y ahora, a raíz de uno de los comentarios de este articulo. La solución parece ser poco estable en versiones antiguas de FF, quién debido a sus ya consabidos problema de memoria, no es capaz de renderizar correctamente el elemento. Si la carga es rápida suele funcionar, pero en páginas de mayor peso no obtenemos el resultado correctamente hasta que recargamos la página.

Esa inestabilidad viene dada a causa de usar un layout incompleto. Una tabla no es una tabla si no dispone de filas y celdas. Por ello en el momento que montamos dicha estructura completa se estabiliza y desaparece el problema. Aún sí­, en versiones más actuales de FF se puede utilizar sólo display: table-cell.

Evita float

Ésta es la mejor solución que os puedo sugerir. Usad sólo float para flotar texto alrededor de una imagen, que es su finalidad. Para montar listas en una estructura matricial/regilla/cuadrícula, o menús horizontales, usad otras técnicas CSS y, en todo caso haced una excepción para IE en la versión que lo necesite -no uséis hacks-, ahí usáis float y, cuando esa versión desaparezca, sólo tendréis que eliminar el archivo CSS de ese navegador.

Os dejo algunas soluciones alternativas:

  • Display: inline-block. Muy útil para crear menús horizontales o listas matriciales. Puede usarse sobre el enlace o sobre el elemento de lista que lo contiene. En IE7 sólo funcionará si el elemento era previamente de tipo inline.
  • Position, left, right. Usa estas propiedades cuando necesites enfrentar elementos alineándolos uno a la izquierda y el siguiente a la derecha, por ejemplo. También podría usarse un display: inline-block junto con la propiedad text-align.
  • Display: table-cell. Puede usarse junto con table y table-row para por ejemplo crear una estructura de varias columnas de la misma altura indistintamente del contenido. Encaja muy bien con los elementos que se suelen utilizar: contenedor, que sería display: table, cabecera, cuerpo y pie, que serían display: table-row, y finalmente las columnas dentro del cuerpo, que utilizarían display: table-cell.
    Podéis ver el uso de este método en el artículo columnas css

Espero que mis sugerencias os sean útiles. Como siempre “Que la semántica os acompañe”.

Deja tu comentario

Comentario

  1. Muy claro tu artículo. Hoy justamente me acordaba del display:table porque parece ser que ha generado un pequeño problema en un sitio en el que estoy trabajando.

    Para conseguir un una solución al ‘problema float’, utilizaba el display:table para que el contenedor envolviera a mis elementos internos flotados (mi contenedor era una lista UL, y los flotados, LIs)

    Todo bien en todos los navegadores, sin embargo, oh, al subir a producción, y no en local, en Firefox, los LIs dejaban de flotar correctamente para hacer lo que les daba la gana. Pero en local salen todos la mar de monos.

    Encontré la solución en Google en esta página, donde el autor parece que desaconseja el uso de display:table, limpiar con un div ‘clearfix’ o incluso prefieriendo flotar parents antes que display:table.

    A mí, con la solución que da, me solucionó el problema. Así que voy a seguir usando display:table.

  2. Firefox tiene un serio problema con la carga. Cuando ésta es muy lenta, ya sea porque tienes muchas pestañas, porque te estás bajando algo con tu P2P favorito o porque decidiste poner imágenes de 1MB en tu site, todos los elementos flotados o con display: table-cell que se encuentren directamente bajo un display:table dejan de funcionar hasta que refrescas y le permites hacer correctamente la carga.
    Esto no sucede en los WebKit ni en Opera, ni aún en IE. Pero sí en FF lamentablemente. Por aquí nos encontramos buscando una solución al problema.. Espero poder publicarla en breve.

    No se si es lo que te pasaba, pero ciertamente es raro que dejen de funcionarte los floats por culpa del display:table a menos que coincidiese con ese caso. Me gustaría ver tu caso concreto, Waldo.

  • Contenido relacionado por Etiqueta