Maquetar sin tablas con diferente número de columnas por fila

Cada vez que me toca maquetar algo me da dolor de cabeza.

Aprendí a programar cuando las tablas eran el no va más de la maquetación y los frames lo mejor que le había ocurrido al mundo. Desde entonces me he dedicado más al back-end que al front-end, así que hoy en día, cuando tengo que tocar algo de maquetación, normalmente acabo con dolor de cabeza. Porque maquetar con tablas era fácil. Y maquetar con CSS, bueno, para alguien que “sepa” lo que está haciendo resultará también sencillo, pero a mi me dicen que funciona con magia y me lo creo.

Puede que estas entradas traten de cosas muy sencillas, pero son temitas de la maquetación que, siempre que he tenido que enfrentarme a ellos, me han costado horas de buscar en foros y hacer pruebas. Así que no me parece mala idea recopilarlas en el blog para que si algún alma cándida algún día tiene los mismos problemas que yo, encuentre aquí un poquito de solaz.

And without further do…

Pongamos que quieres hacer un formulario de búsqueda tal que así:

tablas
Si fueramos a maquetarlo con tablas (solo pongo las etiquetas), quedaría algo parecido a esto:

 <h2></h2>
 <table>
   <tr>
      <td colspan="2"></td>
   </tr>
   <tr>
      <td></td>
      <td></td>
   </tr>
   <tr>
      <td colspan="2"></td>
   </tr>
   <tr>
      <td colspan="2"></td>
   </tr>
 </table>

Ahora bien, para maquetar información que no son tablas, usarlas ni es elegante ni cumple la accesibilidad para una app web, así que tenemos que maquetarlo de otro modo. No requiere mucha búsqueda en internet descubrir que lo que estamos buscando aquí es display:table y display:table-cell, que tienen un nombre bastante explicativo así que no creo que haga falta explicar para qué sirven, y que usaré tal que así:

.tabla{ display:table; }
.celda{display:table-cell;}

El formulario quedaría más o menos así:

<h2></h2>
<div>Calle y nº</div>
<div class="tabla">
<div class="celda">
<!-- input de nombre calle -->
</div>
<div class="celda">
<!-- input de número de calle -->
</div>
</div>
...

No os voy a mentir, el código de arriba, el de calle y número, si vuestra app tiene que pasar una prueba de accesibilidad, no os vale. Porque todo input tiene que tener una etiqueta, y ahí ni la etiqueta está junto al input, ni hay el mismo número de etiquetas que de inputs.

No pasa nada, dividimos en dos la etiqueta, y la ponemos junto al input correspondiente:

<div class="tabla">
<div class="celda">
<label>calle</label>
<input/> <!-- input de nombre calle -->
</div>
<div class="celda">
<label>nº</label>
<input/> <!-- input de número de calle -->
</div>
</div>

Todo correcto, entonces. El resto de filas del formulario se pueden dejar con <div>s normales, y nos podemos ir a casa con la agradable sensación del deber cumplido.
Salvo que por motivos de diseño tengas que meter todas las filas en un mismo <div>, claro.

Pongamos que tuvieramos que meter todos los campos del formulario en el mismo elemento. Vamos a echar mano de display:table-row, que también es muy explicativo así que lo voy a usar sin más dilación:

.fila{display:table-row;}

<div class="tabla">
<div class="fila">
<div class="celda"><!-- input de nombre calle --></div>
<div class="celda"><!-- input de número de calle --></div>
</div>
<div class="fila"><!-- código postal--></div>
<div class="fila"><!-- checkbox --></div>
</div>

Solo que con esta maquetación, las filas del código postal y el checkbox van a tener el ancho del campo “calle”. Y no sé si vosotros sabréis por qué, pero yo desde luego no.

La solución es MU TONTA. En serio. Pero yo tardé algo así como cuatro horas en dar con ella. ¿Cuál es? Pues anidar tablas. Duh.

<div class="busquedaavanzada">
<h3></h3>
<div class="tabla">
<div class="fila">
<div class="tabla">
<div class="celda">
<label>Calle</label>
<input/><!--input de calle-->
</div>
<div style="display:table-cell; border:4px solid transparent"></div>
<div class="celda">
<label>nº</label>
<input/><!--input de número-->
</div>
</div>
</div>
<div class="fila">
<label>codigo postal</label>
<input/>
</div>
<div class="fila">
<label>
<!--checkbox-->
</label>
</div>
</div>
</div>

Por cierto, el div entre los inputs de calle y número hace las veces de separador entre los inputs del formulario sin tener que usar margin ni padding. Que también me trajo de cabeza su buena hora hasta que encontré una solución.

<div style="display:table-cell; border:4px solid transparent"></div>

Espero que la entrada pueda, en algún momento, servirle de algo a alguien 🙂

Besis!

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.