Confina con righe specifiche in una tabella?


120

Sto cercando di progettare un po 'di HTML / CSS che possa mettere un bordo attorno a righe specifiche in una tabella. Sì, lo so che in realtà non dovrei usare le tabelle per il layout, ma non conosco ancora abbastanza CSS per sostituirlo completamente.

Ad ogni modo, ho una tabella con più righe e colonne, alcune unite con rowspan e colspan, e mi piacerebbe mettere un semplice bordo attorno a parti della tabella. Attualmente, sto utilizzando 4 classi CSS separate (in alto, in basso, a sinistra, a destra) che allego alle <td>celle che si trovano rispettivamente lungo la parte superiore, inferiore, sinistra e destra della tabella.

.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>

C'è un modo più semplice per fare quello che voglio? Ho provato ad applicare la parte superiore e inferiore a un <tr>ma non ha funzionato. (ps sono nuovo in CSS, quindi probabilmente c'è una soluzione davvero di base a questo che mi è sfuggito.)

nota: ho bisogno di più sezioni delimitate. L'idea di base è avere più cluster con bordi, ciascuno contenente più righe.


9
Fuori tema ma volevo solo dire che le tabelle sono perfettamente appropriate e consigliate quando si visualizzano dati tabulari ...
md1337

Risposte:


114

Che ne dici tr {outline: thin solid black;}? Funziona per me su elementi tr o tbody e sembra essere compatibile con la maggior parte dei browser, incluso IE 8+ ma non prima.


Stavo chiedendo di mettere un singolo bordo attorno a più righe in una tabella, essenzialmente dividendolo visivamente in più sezioni ma all'interno della stessa tabella in modo che le cose di sezioni diverse si allineino.
Kyle Cronin

3
Capito, ne avevo bisogno anche io. Racchiudi l'insieme di righe intorno alle quali desideri un bordo nel proprio corpo e il CSS sopra creerà un bordo attorno all'insieme di esse - cioè, un bordo superiore sulla riga superiore, un bordo inferiore sulla riga inferiore e sinistra e i bordi a destra su tutte le righe nel tbody. I bordi non sono in realtà "su" quelle righe, sono sul contorno del corpo stesso, provano solo a descrivere l'effetto.
enigment

Oh, vedo, più tbodys - che funziona, ed è qualcosa che non avevo considerato. Upvoted :)
Kyle Cronin

Suggerirei di utilizzare la proprietà css nth-child () piuttosto che definire tbodys a meno che non si disponga di dati piuttosto dinamici. Usando nth-child (), nth-last-child () e not (), puoi selezionare qualsiasi riga / cella che desideri (purché tu conosca gli indici relativi delle cose nella tabella). Ad esempio, puoi selezionare tutte le righe tranne le prime due e l'ultima con tr: not (: nth-child (-n + 2)): not (: nth-last-child (1))
BT

1
Nota che il contorno non ha la possibilità di delimitare lati specifici di un elemento. Ad esempio, non esiste un "outline-top". Questa è una soluzione limitata
BT

53

Grazie a tutti quelli che hanno risposto! Ho provato tutte le soluzioni presentate qui e ho fatto più ricerche su Internet per altre possibili soluzioni, e penso di averne trovata una promettente:

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>

Produzione:

inserisci qui la descrizione dell'immagine

Invece di dover aggiungere i top, bottom, left, e rightclassi per ogni <td>, tutto quello che devo fare è aggiungere top rowalla parte superiore <tr>, bottom rowverso il basso <tr>, e rowad ogni <tr>in mezzo. C'è qualcosa di sbagliato in questa soluzione? Ci sono problemi multipiattaforma di cui dovrei essere a conoscenza?


Ho appena eseguito un test tramite browser e sembra che a IE (tutte le versioni) non piacciano gli attributi first-child e last-child. : - /
Kyle Cronin

1
Sembra che IE 7 e 8 supportino il primo figlio, ma nessuno supporta l'ultimo figlio (!) Msdn.microsoft.com/en-us/library/cc351024(VS.85).aspx
Mechanical_meat

Il cellspacing attributo è obsoleto in HTML5. Sembra che i CSS table { border-collapse: collapse; border-spacing: 0; }siano la strada da percorrere ora.
Stefan van den Akker

36

Se imposti lo border-collapsestile collapsesu nella tabella genitore dovresti essere in grado di applicare uno stile a tr: (gli stili sono in linea per la demo)

<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>

Produzione:

Output HTML


8

Stavo solo giocando anche con questo, e questa sembrava essere l'opzione migliore per me:

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

Nota che questo impedirà l'uso di larghezze di colonna fluide / automatiche , poiché le celle non si allineeranno più con quelle in altre righe, ma la formattazione del bordo / colore funziona ancora bene. La soluzione è dare a TR e TD una larghezza specificata (px o%).

Ovviamente potresti creare il selettore tr.myClassse lo desideri applicare solo a determinate righe. Apparentemente display: tablenon funziona per IE 6/7, tuttavia, ma probabilmente ci sono altri hack (hasLayout?) Che potrebbero funzionare per quelli. :-(


6
Questa soluzione non è corretta: "display: table" mette l'intera riga in una cella della tabella --- si perde la formattazione rispetto alle altre righe della tabella. Ho provato questo in Firefox e Chromium.
Yaakov Belch

Yaakov, penso che ciò a cui ti riferisci è che le larghezze delle colonne fluide non si allineano più con le altre righe nella tabella (come si vede in questo violino: jsfiddle.net/MrKtw ) ma la formattazione del bordo / colore funziona ancora bene. La soluzione è dare a TR e TD una larghezza specificata (px o%).
Simon East

Simon, per mostrare cosa intendo, ho biforcato e ho cambiato il tuo violino. Guarda questo: jsfiddle.net/a6DZV --- Applico la formattazione "display: table" a una sola riga. Come vedi, questo trasforma effettivamente questa riga in una cella della tabella. In altre parole: ottieni lo stesso output dell'annidamento di tabelle di una riga all'interno di una cella di un'altra tabella (e che mostra il bordo di questa tabella interna). La tua soluzione salva alcuni nodi nel DOM ma non è compatibile.
Yaakov Belch

3

Ecco un approccio che utilizza elementi tbody che potrebbe essere il modo per farlo. Non puoi impostare il bordo su un tbody (come non puoi su un tr) ma puoi impostare il colore di sfondo. Se l'effetto che vuoi ottenere può essere ottenuto con un colore di sfondo sui gruppi di righe invece di un bordo, questo funzionerà.

<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

Raggruppa le righe utilizzando il <tbody>tag e quindi applica lo stile.

<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>  

E il css in style.css

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

1

L'unico altro modo in cui posso pensare di farlo è racchiudere ciascuna delle righe di cui hai bisogno un bordo in una tabella nidificata. Ciò renderà il bordo più facile da fare ma potenzialmente creerà altri problemi di layout, dovrai impostare manualmente la larghezza sulle celle della tabella ecc.

Il tuo approccio potrebbe essere il migliore a seconda degli altri requisiti di layout e l'approccio suggerito qui è solo una possibile 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>

Grazie per la tua risposta; hai ragione sui problemi di layout però - preferirei che le colonne si allineassero senza farlo a mano. Che dire dell'applicazione di una classe a un tag <tr>: è possibile?
Kyle Cronin

Se utilizzi una tabella con "table-layout: fixed" e imposti esplicitamente la larghezza di ogni colonna (usando <col> o semplicemente impostando la larghezza delle celle nella prima riga), le colonne si allineeranno indipendentemente dal contenuto. Non è nemmeno necessario annidare le tabelle, tre tabelle separate farebbero bene l'esempio.
bobince

1

In base alla tua esigenza di mettere un bordo attorno a un blocco arbitrario di celle MxN, non esiste davvero un modo più semplice per farlo senza utilizzare Javascript. Se le tue celle sono fisse puoi usare i float, ma questo è problematico per altri motivi. quello che stai facendo può essere noioso ma va bene.

Ok, se sei interessato a una soluzione Javascript, usando jQuery (il mio approccio preferito), ti ritroverai con questo pezzo di codice abbastanza spaventoso:

<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>

Accetterò volentieri suggerimenti su modi più semplici per farlo ...


1
Sembra che tu stia solo aggiungendo classi ai tag td? Perché non è stato possibile farlo con uno script lato server, generato staticamente o nel peggiore dei casi solo a mano? A me sembra un abuso di JavaScript.
Thomas,

3
In realtà il poster ha chiesto una soluzione Javascript. Non si può dire che sia un abuso di Javascript poiché non ci sono abbastanza informazioni. Ad esempio, i bordi vengono aggiunti a causa del clic dell'utente? In tal caso, una soluzione server non è corretta.
cletus

Ci scusiamo per la mancanza di informazioni. Questo verrà generato lato server, quindi è vero che potrei semplicemente aggiungere le classi manualmente, ma mi piace come la soluzione JS fornisce un'interfaccia più semplice per farlo. Quindi, anche se probabilmente non andrò con il JS, è una buona soluzione da vedere.
Kyle Cronin

0

il trucco è con la proprietà outline grazie alla risposta enigment con poche modifiche

usa questa classe

.row-border{
    outline: thin solid black;
    outline-offset: -1px;
}

poi nell'HTML

<tr>....</tr>
<tr class="row-border">
    <td>...</td>
    <td>...</td>
</tr>

e il risultato è che inserisci qui la descrizione dell'immagine spero che questo ti aiuti


-5

Un modo più semplice è rendere la tabella un controllo lato server. Potresti usare qualcosa di simile a questo:

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 chiede un modo più semplice per farlo
orique

2
Fai attenzione, OP chiede anche un modo più semplice per farlo in HTML / CSS. Non vedo da nessuna parte nella sua domanda la parola chiave VB o VBA. Ti suggerisco di dare un'occhiata alla nostra sezione Aiuto: stackoverflow.com/help/how-to-answer Good Luck.
ForceMagic
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.