¿Borde alrededor de filas específicas en una tabla?


120

Estoy tratando de diseñar algo de HTML / CSS que pueda poner un borde alrededor de filas específicas en una tabla. Sí, sé que se supone que no debo usar tablas para el diseño, pero aún no sé suficiente CSS para reemplazarlo por completo.

De todos modos, tengo una tabla con varias filas y columnas, algunas fusionadas con rowspan y colspan, y me gustaría poner un borde simple alrededor de partes de la tabla. Actualmente, estoy usando 4 clases CSS separadas (superior, inferior, izquierda, derecha) que adjunto a las <td>celdas que se encuentran en la parte superior, inferior, izquierda y derecha de la tabla, respectivamente.

.top {
  border-top: thin solid;
  border-color: black;
}

.bottom {
  border-bottom: thin solid;
  border-color: black;
}

.left {
  border-left: thin solid;
  border-color: black;
}

.right {
  border-right: thin solid;
  border-color: black;
}
<html>

<body>

  <table cellspacing="0">
    <tr>
      <td>no border</td>
      <td>no border here either</td>
    </tr>
    <tr>
      <td class="top left">one</td>
      <td class="top right">two</td>
    </tr>
    <tr>
      <td class="bottom left">three</td>
      <td class="bottom right">four</td>
    </tr>
    <tr>
      <td colspan="2">once again no borders</td>
    </tr>
    <tr>
      <td class="top bottom left right" colspan="2">hello</td>
    </tr>
    <tr>
      <td colspan="2">world</td>
    </tr>
  </table>

</html>

¿Hay alguna forma más fácil de hacer lo que quiero? Intenté aplicar la parte superior e inferior a a <tr>pero no funcionó. (PD Soy nuevo en CSS, por lo que probablemente haya una solución realmente básica para esto que me he perdido).

nota: necesito tener varias secciones con bordes. La idea básica es tener varios clústeres con bordes, cada uno de los cuales contiene varias filas.


9
Fuera de tema, pero solo quería decir, las tablas son perfectamente apropiadas y recomendadas al mostrar datos tabulares ...
md1337

Respuestas:


114

¿Qué tal tr {outline: thin solid black;}? Funciona para mí en elementos tr o tbody, y parece ser compatible con la mayoría de los navegadores, incluido IE 8+, pero no antes.


Estaba preguntando acerca de poner un solo borde alrededor de varias filas en una tabla, esencialmente dividiéndolo visualmente en múltiples secciones pero dentro de la misma tabla para que las cosas de diferentes secciones se alineen.
Kyle Cronin

3
Entendido, yo también lo necesitaba. Incluya el conjunto de filas alrededor del cual desea un borde en su propio tbody, y el CSS anterior creará un borde alrededor del conjunto de ellos, es decir, un borde superior en la fila superior, un borde inferior en la fila inferior y a la izquierda y bordes derechos en todas las filas del tbody. Los bordes no están realmente "en" esas filas, están en el contorno del tbody en sí, solo tratando de describir el efecto.
enigment

Oh, ya veo, varios tbodys, eso funciona, y es algo que no había considerado. Upvoted :)
Kyle Cronin

Sugeriría usar la propiedad css nth-child () en lugar de definir tbodys a menos que realmente tenga algunos datos bastante dinámicos. Usando nth-child (), nth-last-child () y not (), puede seleccionar las filas / celdas que desee (siempre que conozca los índices relativos de las cosas en la tabla). Por ejemplo, puede seleccionar todas las filas excepto las dos superiores y la inferior con tr: not (: nth-child (-n + 2)): not (: nth-last-child (1))
BT

1
Tenga en cuenta que el contorno no tiene la posibilidad de bordear lados específicos de un elemento. Por ejemplo, no hay un "esquema superior". Esta es una solución limitada
BT

53

¡Gracias a todos los que han respondido! Probé todas las soluciones presentadas aquí y busqué más en Internet otras posibles soluciones, y creo que encontré una que es prometedora:

tr.top td {
  border-top: thin solid black;
}

tr.bottom td {
  border-bottom: thin solid black;
}

tr.row td:first-child {
  border-left: thin solid black;
}

tr.row td:last-child {
  border-right: thin solid black;
}
<html>

<head>
</head>

<body>

  <table cellspacing="0">
    <tr>
      <td>no border</td>
      <td>no border here either</td>
    </tr>
    <tr class="top row">
      <td>one</td>
      <td>two</td>
    </tr>
    <tr class="bottom row">
      <td>three</td>
      <td>four</td>
    </tr>
    <tr>
      <td colspan="2">once again no borders</td>
    </tr>
    <tr class="top bottom row">
      <td colspan="2">hello</td>
    </tr>
    <tr>
      <td colspan="2">world</td>
    </tr>
  </table>

</body>

</html>

Salida:

ingrese la descripción de la imagen aquí

En lugar de tener que añadir los top, bottom, left, y rightclases para todas <td>, todo lo que tengo que hacer es añadir top rowa la parte superior <tr>, bottom rowa la parte inferior <tr>, y rowpara cada <tr>en el medio. ¿Hay algún problema con esta solución? ¿Hay algún problema multiplataforma que deba tener en cuenta?


Acabo de ejecutar una prueba a través de exploradores y parece que a IE (todas las versiones) no le gustan los atributos de primer hijo y último hijo. : - /
Kyle Cronin

1
Se parece a IE 7 y 8 de soporte de primer hijo, pero ninguno de apoyo last-child (!) Msdn.microsoft.com/en-us/library/cc351024(VS.85).aspx
mechanical_meat

El cellspacingatributo está obsoleto en HTML5. Parece que CSS table { border-collapse: collapse; border-spacing: 0; }es el camino a seguir ahora.
Stefan van den Akker

36

Si configura el border-collapseestilo collapseen la tabla principal, debería poder diseñar el tr: (los estilos están en línea para la demostración)

<table style="border-collapse: collapse;">
  <tr>
    <td>No Border</td>
  </tr>
  <tr style="border:2px solid #f00;">
    <td>Border</td>
  </tr>
  <tr>
    <td>No Border</td>
  </tr>
</table>

Salida:

Salida HTML


8

Yo también estaba jugando con esto, y esta parecía ser la mejor opción para mí:

<style>
    tr { 
        display: table;            /* this makes borders/margins work */
        border: 1px solid black;
        margin: 5px;
    }
</style>

Tenga en cuenta que esto evitará el uso de anchos de columna fluidos / automáticos , ya que las celdas ya no se alinearán con las de otras filas, pero el formato de borde / color seguirá funcionando correctamente. La solución es dar a los TR y TD un ancho específico (px o%).

Por supuesto, podría hacer el selector tr.myClasssi quisiera aplicarlo solo a ciertas filas. display: tableSin embargo, aparentemente no funciona para IE 6/7, pero probablemente haya otros trucos (¿hasLayout?) Que podrían funcionar para ellos. :-(


6
Esta solución es incorrecta: "display: table" coloca toda la fila en una celda de la tabla --- pierde el formato con respecto a las otras filas de la tabla. Probé esto en Firefox y Chromium.
Yaakov Belch

Yaakov, creo que a lo que te refieres es que los anchos de columna fluidos ya no se alinean con otras filas en la tabla (como se ve en este violín: jsfiddle.net/MrKtw ) pero el formato de borde / color aún funciona bien. La solución es dar a los TR y TD un ancho específico (px o%).
Simon East

Simon, para demostrar lo que quiero decir, bifurqué y cambié tu violín. Mire esto: jsfiddle.net/a6DZV --- Aplico el formato "display: table" a una sola fila. Como puede ver, esto convierte esta fila efectivamente en una celda de la tabla. En otras palabras: obtiene el mismo resultado que anidar tablas de una fila dentro de una celda de otra tabla (y mostrar el borde de esta tabla interna). Su solución guarda algunos nodos en el DOM pero no es tan compatible.
Yaakov Belch

3

Aquí hay un enfoque que utiliza elementos tbody que podría ser la forma de hacerlo. No puede establecer el borde en un tbody (lo mismo que no puede en un tr) pero puede establecer el color de fondo. Si el efecto que desea lograr se puede obtener con un color de fondo en los grupos de filas en lugar de un borde, esto funcionará.

<table cellspacing="0">  
    <tbody>
        <tr>    
            <td>no border</td>    
            <td>no border here either</td>  
        </tr>  
    <tbody bgcolor="gray">
        <tr>    
            <td>one</td>    
            <td>two</td>  
        </tr>  
        <tr>    
            <td>three</td>    
            <td>four</td>  
        </tr>  
    <tbody>
        <tr>    
             <td colspan="2">once again no borders</td>  
        </tr>  
    <tbody bgcolor="gray">
        <tr>    
             <td colspan="2">hello</td>  
        </tr>
    <tbody>
    <tr>    
         <td colspan="2">world</td>  
    </tr>
</table>

2

Agrupe filas con la <tbody>etiqueta y luego aplique estilo.

<table>
  <tr><td>No Style here</td></tr>
  <tbody class="red-outline">
    <tr><td>Style me</td></tr>
    <tr><td>And me</td></tr>
  </tbody>
  <tr><td>No Style here</td></tr>
</table>  

Y el css en style.css

.red-outline {
  outline: 1px solid red;
}

1

La única otra forma que se me ocurre de hacerlo es encerrar cada una de las filas alrededor de las que necesita un borde en una tabla anidada. Eso hará que el borde sea más fácil de hacer, pero potencialmente creará otros problemas de diseño, tendrá que establecer manualmente el ancho en las celdas de la tabla, etc.

Su enfoque puede ser el mejor dependiendo de sus otros requisitos de diseño y el enfoque sugerido aquí es solo una posible alternativa.

<table cellspacing="0">  
    <tr>    
        <td>no border</td>    
        <td>no border here either</td>  
    </tr>  
    <tr>
        <td>
             <table style="border: thin solid black">
                  <tr>    
                        <td>one</td>    
                        <td>two</td>  
                  </tr>  
                  <tr>    
                      <td>three</td>    
                      <td>four</td>  
                  </tr>  
             </table>
         </td>
    </tr>
    <tr>    
         <td colspan="2">once again no borders</td>  
    </tr>  
    <tr>
        <td>
             <table style="border: thin solid black">
                  <tr>    
                        <td>hello</td>  
                   </tr>
             </table>
         </td>
    </tr>
    <tr>    
         <td colspan="2">world</td>  
    </tr>
</table>

Gracias por tu respuesta; Sin embargo, tienes razón sobre los problemas de diseño: preferiría que las columnas se alineen sin hacerlo a mano. ¿Qué hay de aplicar una clase a una etiqueta <tr>? ¿Es eso posible?
Kyle Cronin

Si usa una tabla con "table-layout: fixed" y establece explícitamente el ancho de cada columna (usando <col> o simplemente estableciendo el ancho de las celdas en la primera fila), las columnas se alinearán independientemente del contenido. Ni siquiera necesita anidar las tablas, tres tablas separadas servirían para el ejemplo.
Bobince

1

De acuerdo con su requisito de que desea poner un borde alrededor de un bloque arbitrario de celdas MxN, realmente no hay una manera más fácil de hacerlo sin usar Javascript. Si sus celdas están arregladas con, puede usar flotadores, pero esto es problemático por otras razones. lo que estás haciendo puede ser tedioso pero está bien.

Ok, si estás interesado en una solución de Javascript, usando jQuery (mi enfoque preferido), terminas con este código bastante aterrador:

<html>
<head>

<style type="text/css">
td.top { border-top: thin solid black; }
td.bottom { border-bottom: thin solid black; }
td.left { border-left: thin solid black; }
td.right { border-right: thin solid black; }
</style>
<script type="text/javascript" src="jquery-1.3.1.js"></script>
<script type="text/javascript">
$(function() {
  box(2, 1, 2, 2);
});

function box(row, col, height, width) {
  if (typeof height == 'undefined') {
    height = 1;
  }
  if (typeof width == 'undefined') {
    width = 1;
  }
  $("table").each(function() {
    $("tr:nth-child(" + row + ")", this).children().slice(col - 1, col + width - 1).addClass("top");
    $("tr:nth-child(" + (row + height - 1) + ")", this).children().slice(col - 1, col + width - 1).addClass("bottom");
    $("tr", this).slice(row - 1, row + height - 1).each(function() {
      $(":nth-child(" + col + ")", this).addClass("left");
      $(":nth-child(" + (col + width - 1) + ")", this).addClass("right");
    });
  });
}
</script>
</head>
<body>

<table cellspacing="0">
  <tr>
    <td>no border</td>
    <td>no border here either</td>
  </tr>
  <tr>
    <td>one</td>
    <td>two</td>
  </tr>
  <tr>
    <td>three</td>
    <td>four</td>
  </tr>
  <tr>
    <td colspan="2">once again no borders</td>
  </tr>
</tfoot>
</table>
</html>

Con mucho gusto aceptaré sugerencias sobre formas más fáciles de hacer esto ...


1
¿Parece que solo está agregando clases a las etiquetas td? ¿Por qué no se puede hacer esto con algún script del lado del servidor, generado de forma estática o en el peor de los casos solo a mano? Me parece un abuso de JavaScript.
Thomas

3
En realidad, el cartel PIDIÓ una solución de Javascript. No se puede decir que sea abuso de Javascript ya que no hay suficiente información. Por ejemplo, ¿se están agregando los bordes debido a que el usuario hace clic? Si es así, una solución de servidor es incorrecta.
cletus

Perdón por la falta de información. Esto se generará en el lado del servidor, por lo que es cierto que podría agregar las clases manualmente, pero me gusta cómo la solución JS proporciona una interfaz más simple para hacerlo. Entonces, aunque probablemente no iré con JS, es una buena solución para ver.
Kyle Cronin


-5

Una forma más sencilla es convertir la mesa en un control del lado del servidor. Podrías usar algo similar a esto:

Dim x As Integer
table1.Border = "1"

'Change the first 10 rows to have a black border
 For x = 1 To 10
     table1.Rows(x).BorderColor = "Black"
 Next

'Change the rest of the rows to white
 For x = 11 To 22
     table1.Rows(x).BorderColor = "White"
 Next

1
OP está pidiendo una forma más fácil de hacerlo
orique

2
Tenga cuidado, OP también está pidiendo una forma más fácil de hacerlo en HTML / CSS. No veo en ninguna parte de su pregunta la palabra clave VB o VBA. Le sugiero que eche un vistazo a nuestra sección de Ayuda: stackoverflow.com/help/how-to-answer Good Luck.
ForceMagic
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.