Cómo poner espacio entre elementos TBODY

95

Tengo una mesa como esta:

<table>
    <tfoot>
        <tr><td>footer</td></tr>
    </tfoot>
    <tbody>
        <tr><td>Body 1</td></tr>
        <tr><td>Body 1</td></tr>
        <tr><td>Body 1</td></tr>
    </tbody>
    <tbody>
        <tr><td>Body 2</td></tr>
        <tr><td>Body 2</td></tr>
        <tr><td>Body 2</td></tr>
    </tbody>
    <tbody>
        <tr><td>Body 3</td></tr>
        <tr><td>Body 3</td></tr>
        <tr><td>Body 3</td></tr>
    </tbody>
</table>

Me gustaría poner algo de espacio entre cada elemento tbody, pero el relleno y el margen no tienen ningún efecto. ¿Algunas ideas?

nickf
fuente
¿Es correcto repetir las etiquetas 'tbody'? Lo que siempre he visto es que todos los "<tr> .. </tr>" están dentro de una sola etiqueta "tbody".
Saneef
23
Sí, esto es válido. La especificación dice: <! ELEMENT TABLE - - (CAPTION ?, (COL * | COLGROUP *), THEAD ?, TFOOT ?, TBODY +)> lo que significa que tiene que haber uno o más tbodies. w3.org/TR/html4/struct/tables.html#h-11.2.1
nickf

Respuestas:

56

Pruebe esto, si no le importa no tener fronteras.

<style>
table {
  border-collapse: collapse;
}

table tbody {
  border-top: 15px solid white;
}
</style>

<table>
    <tfoot>
        <tr><td>footer</td></tr>
    </tfoot>
    <tbody>
        <tr><td>Body 1</td></tr>
        <tr><td>Body 1</td></tr>
        <tr><td>Body 1</td></tr>
    </tbody>
    <tbody>
        <tr><td>Body 2</td></tr>
        <tr><td>Body 2</td></tr>
        <tr><td>Body 2</td></tr>
    </tbody>
    <tbody>
        <tr><td>Body 3</td></tr>
        <tr><td>Body 3</td></tr>
        <tr><td>Body 3</td></tr>
    </tbody>
</table>
Dave Jensen
fuente
7
Pruebe border-top: 15px sólido transparente;
Steve Almond
3
Quería enfatizar esto. Úselo transparentcomo color de borde. Lo que dijo @SteveAlmond.
iheartcsharp
si la tabla / tbody / tr / td tiene un color de fondo, establecer el color del borde en transparentle dará el color de fondo del elemento, esencialmente indistinguible del cuerpo del elemento. Debería colorear explícitamente el borde del color que desea que aparezca (para hacerlo supuestamente invisible)
Guy Passy
81

Algo como esto funcionará, según los requisitos de compatibilidad de su navegador:

tbody::before
{
  content: '';
  display: block;
  height: 15px;

}
MacNimble
fuente
1
Esta es la única solución que funciona cuando sus celdas tienen un fondo que el espacio no debería tener.
Laradda
Esto funcionó bien para mí. ¿Hay algún inconveniente? Además, ¿por qué dos dos puntos?
nh2
Gran solucion ¡Mantiene todo accesible!
Jason T Featheringham
1
@ nh2: los dos puntos son para pseudocontenido y los dos puntos simples son para pseudo-selectores. Es una actualización de la sintaxis CSS. Todo solía usar solo dos puntos. Los navegadores más antiguos no admiten dos puntos dobles (como, IE <= 8).
dbmikus
3
¿No es más seguro de usar display: table-row;?
Rachel
20

La gente siempre tendrá opiniones controvertidas sobre el uso de elementos de tabla vacíos para diseñar una página (como lo demuestra el voto negativo de esta respuesta). Reconozco esto, pero a veces es más fácil usarlos de esta manera cuando se trabaja de una manera " rápida y sucia ".

He usado filas vacías en proyectos anteriores para espaciar grupos de filas de tablas. Asigné a las filas espaciadoras una clase css propia y definí una altura para esa clase que actuaba como un margen superior e inferior para ese grupo de filas de la tabla.

    .separator{
             height: 50px;
    }

   <table>
           <tr><td>Cell 1</td><td>Cell 2</td></tr>
           <tr><td>Cell 1</td><td>Cell 2</td></tr>
           <tr><td>Cell 1</td><td>Cell 2</td></tr>

           <tr class="separator" colspan="2"></tr>

           <tr><td>Cell 1</td><td>Cell 2</td></tr>
           <tr><td>Cell 1</td><td>Cell 2</td></tr>
           <tr><td>Cell 1</td><td>Cell 2</td></tr>

           <tr class="separator" colspan="2"></tr>

           tr><td>Cell 1</td><td>Cell 2</td></tr>
           <tr><td>Cell 1</td><td>Cell 2</td></tr>
           <tr><td>Cell 1</td><td>Cell 2</td></tr>
   </table>

Si no tiene bordes en las celdas de su tabla, también puede definir una altura para su celda o fila típica en su hoja de estilo que espacia uniformemente todas las filas de su tabla.

tr{
   height: 40px;
}
kevtrout
fuente
Bueno, si va a agregar un marcado adicional, ¿por qué no simplemente coloca una clase en la primera fila de cada tbody?
Nickf
Bueno, eso podría deberse a que las filas son código generado, y agregar una fila separada en el marcado podría ser más fácil de mantener que crear un caso especial para la primera fila de contenido generado.
Rolf Rander
12
Vota todo lo que quieras, pero esta es la única solución sin inconvenientes, e incluso si viola la separación, una fila vacía no es un gran problema, en mi opinión.
Xkeeper
11
¡Sin inconvenientes, mi trasero! Intente usar un lector de pantalla en esto y observe el recuento de filas incorrecto. Mejor aún, intente copiar y pegar la tabla en una hoja de cálculo. Volverá a formatear durante horas si tiene mucho contenido. Las tablas están diseñadas para mostrar datos (y ser extremadamente accesibles), no para ajustar la presentación entre secciones.
Jason T Featheringham
Es solo visual. Tenga en cuenta que los html también son documentos que se pueden procesar, por lo tanto, el contenido que contienen debe estar bien formateado. Como se mencionó anteriormente, la tabla de copiar y pegar o el uso del lector de pantalla simplemente fallará. Este diseño no debe fomentarse. :: La solución de contenido es mejor porque no estropea el marcado.
pawel-kuznik
12

Había tenido problemas para espaciar correctamente múltiples <tbody>con ::beforepseudo, en presencia de <tr>contener <td>con rowspan en un par de navegadores.

Básicamente, si tiene una <tbody>estructura como esta:

<tbody>
    <tr>
        <td>td 1</td>
        <td rowspan"2">td 2</td>
        <td>td 3</td>
        <td>td 4</td>
    </tr>
    <tr>
        <td>td 1</td>
        <td>td 2</td>
        <td>td 4</td>
    </tr>
</tbody>

Y sigue a quién aconseja escribir css en un ::beforepseudo elemento de esta manera:

tbody::before
{
    content: '';
    display: block;
    height: 10px;
}

Esto afectará el intervalo de filas , haciendo que la tabla "pierda" en el segundo <tr>la cantidad de <td>intervalos de fila presentes en el primero.

Entonces, si alguien se encuentra con ese tipo de problema, la solución es diseñar ::beforepseudo de esta manera:

tbody::before
{
    content: '';
    display: table-row;
    height: 10px;
}

Aquí hay un violín

Nineoclick
fuente
6

Aquí hay otra posibilidad en la que se basa: first-child que no está disponible en todos los navegadores:

<style>
table {
  border-collapse: collapse;
}

td {
  border: 1px solid black;
}

tbody tr:first-child td {
  padding-top: 15px;
}

</style>

<table>
    <tfoot>
        <tr><td>footer</td></tr>
    </tfoot>
    <tbody>
        <tr><td>Body 1</td></tr>
        <tr><td>Body 1</td></tr>
        <tr><td>Body 1</td></tr>
    </tbody>
    <tbody>
        <tr><td>Body 2</td></tr>
        <tr><td>Body 2</td></tr>
        <tr><td>Body 2</td></tr>
    </tbody>
    <tbody>
        <tr><td>Body 3</td></tr>
        <tr><td>Body 3</td></tr>
        <tr><td>Body 3</td></tr>
    </tbody>
</table>
Dave Jensen
fuente
3
Este no funcionará muy bien si tiene algo que dependa de la posición del contenido en relación con el tamaño de la celda, como sombra de cuadro, imágenes de fondo o prácticamente cualquier otra cosa.
Xkeeper
1
Solo para aclarar a los demás que encuentren esta respuesta en Google, supongo que como esto se escribió en 2008, esta respuesta ahora (2015) tiene soporte completo en todos los principales navegadores. ¿Al menos comprobar en caniuse.com first-child parece estar bien respaldado?
redfox05
6

Simplemente configúrelo displaycomo blocky funcionará.

table tbody{
    display:block;
    margin-bottom:10px;
    border-radius: 5px;
}
user007
fuente
1
esta respuesta debería ser la respuesta aceptada porque es la única que permite usar un tbody con borde con columnas "sin borde".
robsonrosa
13
display:blockrompe la alineación de la columna entre los elementos tbody. Ya no obtiene los beneficios del motor de diseño de tablas
M Conrad
4

De todas las respuestas dadas anteriormente, solo las respuestas de djenson47 mantienen la separación de presentación y contenido . El inconveniente del método del modelo de borde contraído es que ya no puede usar el borde de la tabla o los atributos de espacio entre celdas para separar las celdas individuales. Se podría argumentar que esto es algo bueno y que existen algunas soluciones, pero puede ser un fastidio. Entonces creo que el método del primer hijo es el más elegante.

Alternativamente, también puede establecer la propiedad de desbordamiento de su clase TBODY en cualquier cosa que no sea "visible". Este método también le permite conservar un modelo de bordes separados:

<style>
tbody {
    overflow: auto;
    border-top: 1px solid transparent;
}
</style>
<table>
    <tfoot>
        <tr><td>footer</td></tr>
    </tfoot>
    <tbody>
        <tr><td>Body 1</td></tr>
        <tr><td>Body 1</td></tr>
        <tr><td>Body 1</td></tr>
    </tbody>
    <tbody>
        <tr><td>Body 2</td></tr>
        <tr><td>Body 2</td></tr>
        <tr><td>Body 2</td></tr>
    </tbody>
    <tbody>
        <tr><td>Body 3</td></tr>
        <tr><td>Body 3</td></tr>
        <tr><td>Body 3</td></tr>
    </tbody>
</table>
Calvin
fuente
Estaba buscando hacer algo similar, esto es perfecto para mí
Eruant
4

Debido a que el relleno se puede aplicar a los TD, puede hacer un truco con el signo +. Entonces será posible dar un relleno superior a los TD del primer TR de un tbody:

// The first row will have a top padding
table tbody + tbody tr td {
    padding-top: 20px;
}

// The rest of the rows should not have a padding
table tbody + tbody tr + tr td {
    padding-top: 0px;
}

He añadido el "tbody + tbody" para que el primer tbody no tenga un relleno superior. Sin embargo, no es obligatorio.

Hasta donde yo sé, no hay inconvenientes :), aunque no probé los navegadores más antiguos.

Maarten
fuente
2

Puede usar border-spacingen una tabla con grupos de filas de tabla para agregar un espacio entre esos grupos. Sin embargo, no creo que haya una forma de especificar qué grupos están espaciados y cuáles no.

<table>
  <thead>
    ...
  </head>
  <tbody>
    ...
  </tbody>
  <tbody>
    ...
  </tbody>
  <tfoot>
    ...
  </tfoot>
</table>

CSS

table {
  border-spacing: 0px 10px; /* h-spacing v-spacing */
}
OdraEncoded
fuente
0

NUEVA RESPUESTA

Puede utilizar tantas <tbody>etiquetas como desee. No me di cuenta de que W3C estaba bien hasta ahora. No quiero decir que mi solución a continuación no funcione (lo hace), pero para hacer lo que está tratando de hacer, asigne sus <tbody>clases de etiquetas y luego haga referencia a sus <td>etiquetas individuales a través de CSS así:

table tbody.yourClass td {
    padding: 10px;
}

y su HTML así:

<table> 
<tbody>
<tr><td>Text</td></tr>
<tr><td>Text</td></tr>
<tr><td>Text</td></tr>
</tbody>
<tbody class="yourClass">    
<tr><td>Text</td></tr>
<tr><td>Text</td></tr>
<tr><td>Text</td></tr>
</tbody>
<tbody>
<tr><td>Text</td></tr>
<tr><td>Text</td></tr>
<tr><td>Text</td></tr>
</tbody>
</table>

Prueba a ese chico :)

ANTIGUA RESPUESTA

hagas lo que hagas, NO insertes filas en blanco ...

no debería tener más de 1 elemento tbody en su tabla. lo que puede hacer es establecer el atributo class o id en sus <tr>elementos y darles <td>relleno a sus etiquetas correspondientes :

table {
    border-collapse: collapse;
}

tr.yourClass td {
    padding: 10px;
}

Incluso puede asignar a la parte superior e inferior <tr>una clase adicional para que solo realicen relleno superior o inferior, respectivamente:

tr.yourClass.topClass td {
    padding: 10px 0 0 0;
}

tr.yourClass.bottomClass td {
    padding: 0 0 10px 0;
}

y en su HTML, su <tr>etiqueta se vería así:

<table> 
<tbody>
<tr><td>Text</td></tr>
<tr><td>Text</td></tr>
<tr><td>Text</td></tr>
<tr class="yourClass topClass"><td>Text</td></tr>
<tr class="yourClass"><td>Text</td></tr>
<tr class="yourClass bottomClass"><td>Text</td></tr>
<tr><td>Text</td></tr>
<tr><td>Text</td></tr>
<tr><td>Text</td></tr>
</tbody>
</table>

¡Espero que esto ayude!

Jason
fuente
0

La respuesta de djensen47 funciona muy bien para los navegadores más nuevos, sin embargo, como se señaló, IE7 no funciona.

Mi solución para que este problema sea compatible con los navegadores más antiguos fue envolver el contenido de cada celda dentro de un div. Luego agregue un margin-top al div.

<table class="tbl">
<tr></tr>
<tr></tr>
<tr></tr>
<tr><td><div></div></td></tr>
</table>

CSS

.tbl tr td div {
    height:30px;
    margin-top:20px;
}

La configuración de altura mantiene las celdas al menos 30px de alto para evitar que cualquier color de celda utilizado dentro del div se colapse alrededor del texto. El margen superior crea el espacio deseado haciendo que toda la fila sea más alta.

Jereme Guenther
fuente
0

Encontré esto mientras intentaba resolverlo yo mismo. Tuve éxito al poner una <br>etiqueta justo antes de la </tbody>etiqueta de cierre . Es una solución puramente visual, pero parece funcionar en la mayoría de los navegadores que probé.

<table>
    <tbody>
        <tr>
            <td></td>
        </tr>
        <br>
    </tbody>
    <tbody>
        <tr>
            <td></td>
        </tr>
    </tbody>
</table>

Debería ser accesible también.

Ian
fuente