Ir directamente al contenido de esta página

codexexempla.org

Limpiar con sentido

Tabla de contenidos

  1. El escenario
  2. Limpiar por medio de un div
  3. Limpiar de manera semántica

El escenario

Creo que todos, sin excepción, al empezar a trabajar con CSS hemos tenido que revisar páginas y páginas para aprender a crear diseños a varias columnas. La verdad es que es todo un arte, y no hay curso o manual de CSS que se precie que no tenga una sección dedicada a ese tema —por cierto, ésta es la mía—. Y entonces viene una secuencia de pasos como esta:

  1. Creamos dos columnas, y asignamos un color a cada una.
  2. Comprobamos que la columna más corta no se extiende hasta alcanzar la altura de la/s otra/s columna/s, y que si no asignamos una altura fija, tenemos que recurrir a JavaScript.
  3. Nos rascamos insistentemente el craneo.
  4. Buscamos en Google, y llegamos al artículo de Dan Cederholm, Faux Columns (inglés), que nos ofrece una solución, y que recomiendo leer en este momento si no se conoce.

Contentísimos, nos ponemos a aplicarlo, y parece que funciona, como en este ejemplo

Faux Columns en Internet Explorer 6

…siempre y cuando empleemos Internet Explorer. Para Firefox, u Opera o Safari, el resultados es éste:

Faux Columns en Firefox 2

Como se ve, la imagen que hemos empleado para crear las falsas columnas no se muestra. ¿Por qué? Bueno, en realidad se debe a que al principio todos tenemos la tendencia a crear un marcado como éste:


    <div id="contenedor">
        <div id="contenido">
            …
        </div>
        <div id="contenido_secundario">
            …
        </div>
    </div>        
            

En realidad, si nos fijamos, esa capa llamada contenedor no es muy semántica. Pero lo importante es que no tiene más contenido que los dos elementos que se flotan. Y la especificación dice:

Since a float is not in the flow, non-positioned block boxes created before and after the float box flow vertically as if the float didn't exist.

[En al medida en que un flotado no pertenece al flujo, las cajas de bloque no posicionadas creadas antes y después de la caja flotada fluyen verticalmente como si el flotado no existiese.]

Recomendación CSS 2.1, «9.5 Floats» (inglés)

En idioma común, supone que la caja que contiene al elemento flotado sólo debe extenderse hasta lo necesario para albergar el contenido no flotado. Como contenedor no tiene ninguno, se contrae hasta desaparecer. Sí, lo de Internet Explorer es un error en el soporte de la especificación.

Como tantas otras veces, solucionar un problema nos lleva a descubrir otros.

Limpiar por medio de un div

Llegados a este punto, sabemos que el problema es que necesitamos algún contenido en contenedor tras las columnas que podamos limpiar por medio de clear, y así forzar al elemento padre a extenderse hasta cubrir nuestras columnas.

Y antes o después algún oscuro mecanismo se dispara en la cabeza de todo iniciado al CSS que se enfrenta a esta situación, y que le hace codificar esto:


    <div id="contenedor">
        <div id="contenido">
            …
        </div>
        <div id="contenido_secundario">
            …
        </div>
        <div style="clear:both"></div>
    </div>        
            

Reconocedlo.

Y si no lo hacéis, bueno, creo que los datos de Google me respaldan: <div style="clear:both"></div> tal día como hoy ofrece 817.000 resultados, mientras que su versión <div><span style="clear:both"> </span></div> —más absurda, sin duda alguna …1— suma 583.000.

El caso es que funciona. En este punto, si emplear un elemento estructural de manera no semántica no supone un problema para el lector, puede dejar de leer.

Bien, si sigue leyendo al menos tiene curiosidad.

Personalmente, para evitar este problema, si puedo asignar la imagen de las falsas columnas al body, lo hago, con lo que además me ahorro la capa contenedor. Pero esta solución sólo se puede aplicar en dos supuestos:

  1. en un entorno controlado, es decir, una red cerrada donde conozco la resolución y los navegadores, y sé que los documentos siempre van a superar el alto de la ventana del navegador, o
  2. si las columnas deben —o pueden— extenderse hasta el final del documento sin una imagen «de cierre» en el pie.

En los demás casos —mal que me pese— necesito la capa contenedor, porque si no ocurre algo como esto:

Imagen de fondo en el body, cuando el documento no ocupa toda la ventana

Pero eso no significa que tenga que resignarme y aceptar además otro div vacío para limpiar los flotados, así que…

Limpiar de manera semántica

Así que, recuerdo un elemento bastante devaluado —aunque aún válido— que es hr2, que crea una regla horizontal cuya finalidad es precisamente dividir visualmente un contenido indicando diferentes secciones estructurales. En este caso, lo empleo para separar el contenido del documento de su pie, lo que no creo que sea forzar su semántica. En última instancia, al menos, no la fuerza tanto como un div vacío.

En este ejemplo se puede comprobar su funcionamiento.

Para finalizar, una nota sobre cómo hacerlo invisible:

Bien, sigue sin ser la solución ideal, pero tampoco vivimos en un mundo perfecto…

Otra solución alternativa es la de emplear el pseudoelemento :after para añadir un contenido tras el elemento a limpiar. Si bien desde el punto de vista del marcado es más semántico, resulta una solución muy poco elegante, por los problemas adicionales que plantea. Y si no, ver How To Clear Floats Without Structural Markup en positioniseverything.net (inglés). Así que, por supuesto, defiendo mi método para la situación que he descrito.

Notas

  1. …puesto que luego de alguna forma hay que asignar display:block a ese span para que funcione. Así que ya puestos, propongo la versión a-semántica definitiva:

    
        <div style="height:0;overflow:hidden;">
        <p><span><strong><span><i>
        <span style="clear:both;">&nbsp;</span>
        </i></span></strong></span></p>
        </div>
                    

    Ésta además tiene la virtud de no generar advertencias en el Tidy. Volver

  2. Es cierto que hr está condenado a desaparecer. En XHTML 1.1 está relegado al módulo de presentación (inglés), y en el actual boceto de XHTML 2.0 desaparece en favor de separator (inglés). Pero de momento no tenemos nada mejor. Volver

Contacto

En virtud de la Ley Orgánica 15/1999 de Protección de Datos de Carácter Personal le informo de que los datos que proporcione no serán empleados para otro fin que el de responder a su mensaje. En especial, me comprometo a no cederlos a terceros ni a emplearlos para enviar información no solicitada.

Del blog de Digital Icon