Obramować wokół określonych wierszy w tabeli?

120

Próbuję zaprojektować HTML / CSS, który może umieścić obramowanie wokół określonych wierszy w tabeli. Tak, wiem, że tak naprawdę nie powinienem używać tabel do układu, ale nie znam wystarczającej liczby CSS, aby go całkowicie zastąpić.

W każdym razie mam tabelę z wieloma wierszami i kolumnami, niektóre są połączone za pomocą rowspan i colspan, i chciałbym umieścić prostą ramkę wokół części tabeli. Obecnie używam 4 oddzielnych klas CSS (góra, dół, lewa, prawa), które dołączam do <td>komórek znajdujących się odpowiednio na górze, na dole, po lewej i prawej stronie tabeli.

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

Czy jest łatwiejszy sposób na zrobienie tego, co chcę? Próbowałem zastosować górę i dół do a, <tr>ale to nie zadziałało. (ps Jestem nowy w CSS, więc prawdopodobnie istnieje naprawdę podstawowe rozwiązanie tego problemu, które przegapiłem).

Uwaga: muszę mieć wiele sekcji graniczących. Podstawowym pomysłem jest posiadanie wielu graniczących klastrów, z których każdy zawiera wiele wierszy.

Kyle Cronin
źródło
9
Nie na temat, ale chciałem tylko powiedzieć, że tabele są idealnie odpowiednie i zalecane przy wyświetlaniu danych tabelarycznych ...
md1337

Odpowiedzi:

114

A co powiesz tr {outline: thin solid black;}? Działa dla mnie na elementach tr lub tbody i wydaje się być kompatybilny z większością przeglądarek, w tym IE 8+, ale nie wcześniej.

enigment
źródło
Pytałem o umieszczenie pojedynczej ramki wokół wielu wierszy w tabeli, zasadniczo wizualnie dzieląc ją na wiele sekcji, ale w tej samej tabeli, aby elementy z różnych sekcji były wyrównane.
Kyle Cronin
3
Zrozumiałem, ja też tego potrzebowałem. Umieść zestaw wierszy, wokół których chcesz obramować, we własnym tekście, a powyższy css utworzy obramowanie wokół ich zestawu - tj. Górne obramowanie w górnym rzędzie, dolne obramowanie w dolnym rzędzie i po lewej i prawe obramowanie we wszystkich wierszach w korpusie. Granice nie są w rzeczywistości „na” tych wierszach, są na zarysie samego ciała, po prostu próbując opisać efekt.
enigment
Och, widzę, wiele razy - to działa i jest czymś, czego nie brałem pod uwagę. Głosowano za :)
Kyle Cronin,
Sugerowałbym użycie właściwości css nth-child () zamiast definiowania tbodys, chyba że naprawdę masz dość dynamiczne dane. Używając nth-child (), nth-last-child () i not (), możesz wybrać dowolne wiersze / komórki (o ile znasz względne indeksy elementów w tabeli). Na przykład możesz wybrać wszystkie wiersze z wyjątkiem dwóch górnych i dolnych za pomocą tr: not (: nth-child (-n + 2)): not (: nth-last-child (1))
BT
1
Zwróć uwagę, że kontur nie ma możliwości obramowania określonych boków elementu. Na przykład nie ma „góry konspektu”. To jest ograniczone rozwiązanie
BT,
53

Dziękuję wszystkim, którzy odpowiedzieli! Wypróbowałem wszystkie przedstawione tutaj rozwiązania i przeszukiwałem internet w poszukiwaniu innych możliwych rozwiązań i myślę, że znalazłem jedno, które jest obiecujące:

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>

Wynik:

wprowadź opis obrazu tutaj

Zamiast dodawać top, bottom, leftoraz rightzajęcia dla każdego <td>, wszystko co musisz zrobić, to dodać top rowdo góry <tr>, bottom rowdo dołu <tr>, i rowaby każdy <tr>w pomiędzy. Czy jest coś nie tak z tym rozwiązaniem? Czy są jakieś problemy z różnymi platformami, o których powinienem wiedzieć?

Kyle Cronin
źródło
Właśnie przeprowadziłem test za pomocą przeglądarek i wygląda na to, że IE (wszystkie wersje) nie podoba się atrybutom first-child i last-child. : - /
Kyle Cronin
1
Wygląda na to, że IE 7 i 8 obsługują pierwsze dziecko, ale żadna nie obsługuje ostatniego dziecka (!) Msdn.microsoft.com/en-us/library/cc351024(VS.85).aspx
Mechanical_meat
cellspacingAtrybut jest przestarzałe w HTML5. Wygląda na to, że CSS table { border-collapse: collapse; border-spacing: 0; }jest teraz właściwą drogą.
Stefan van den Akker
36

Jeśli ustawisz border-collapsestyl collapsena w tabeli nadrzędnej, powinieneś być w stanie nadać styl tr: (style są wbudowane do wersji demonstracyjnej)

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

Wynik:

Wyjście HTML

wschód słońca
źródło
8

Ja też się tym bawiłem i wydawało mi się, że to najlepsza opcja:

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

Zwróć uwagę, że zapobiegnie to stosowaniu płynnych / automatycznych szerokości kolumn , ponieważ komórki nie będą już wyrównywać się z tymi w innych wierszach, ale formatowanie obramowania / koloru nadal działa poprawnie. Rozwiązaniem jest nadanie TR i TD określonej szerokości (px lub%).

Oczywiście możesz zrobić selektor, tr.myClassjeśli chcesz zastosować go tylko do niektórych wierszy. Najwyraźniej display: tablenie działa w IE 6/7, ale prawdopodobnie są inne hacki (hasLayout?), Które mogą działać w tych przypadkach. :-(

Simon East
źródło
6
To rozwiązanie jest nieprawidłowe: „display: table” umieszcza cały wiersz w jednej komórce tabeli - tracisz formatowanie w stosunku do innych wierszy tabeli. Próbowałem tego w Firefoksie i Chromium.
Yaakov Belch
Yaakov, myślę, że chodzi o to, że płynne szerokości kolumn nie są już wyrównane z innymi wierszami w tabeli (jak widać na tym skrzypcach: jsfiddle.net/MrKtw ), ale formatowanie obramowania / koloru nadal działa OK. Rozwiązaniem jest nadanie TR i TD określonej szerokości (px lub%).
Simon East,
Simon, żeby pokazać, co mam na myśli, rozwidliłem i zmieniłem twoje skrzypce. Spójrz na to: jsfiddle.net/a6DZV --- Stosuję formatowanie „display: table” tylko do jednego wiersza. Jak widać, powoduje to efektywne przekształcenie tego wiersza w jedną komórkę tabeli. Innymi słowy: Otrzymujesz taki sam wynik, jak zagnieżdżenie jednorzędowych tabel w komórce innej tabeli (i pokazanie obramowania tej wewnętrznej tabeli). Twoje rozwiązanie zapisuje kilka węzłów w DOM, ale nie jest tak kompatybilne.
Yaakov Belch
3

Oto podejście wykorzystujące elementy tbody, które mogą być sposobem na zrobienie tego. Nie możesz ustawić obramowania na tbody (tak samo jak na tr), ale możesz ustawić kolor tła. Jeśli efekt, który chcesz osiągnąć, można uzyskać za pomocą koloru tła na grupach wierszy zamiast obramowania, to zadziała.

<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>
sipwiz
źródło
2

Pogrupuj wiersze za pomocą <tbody>tagu, a następnie zastosuj styl.

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

A css w style.css

.red-outline {
  outline: 1px solid red;
}
csi
źródło
1

Jedynym innym sposobem, jaki mogę sobie wyobrazić, jest zawarcie każdego z wierszy, wokół których potrzebujesz ramki, w zagnieżdżonej tabeli. Ułatwi to obramowanie, ale potencjalnie stworzy inne problemy z układem, będziesz musiał ręcznie ustawić szerokość komórek tabeli itp.

Twoje podejście może być najlepsze, w zależności od innych wymagań dotyczących układu, a sugerowane tutaj podejście jest tylko możliwą alternatywą.

<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>
sipwiz
źródło
Dziękuję za odpowiedź; masz jednak rację co do problemów z układem - wolałbym, aby kolumny były wyrównane bez robienia tego ręcznie. A co z zastosowaniem klasy do tagu <tr> - czy to możliwe?
Kyle Cronin
Jeśli używasz tabeli z „table-layout: fixed” i jawnie ustawisz szerokość każdej kolumny (używając <col> lub po prostu ustawiając szerokość komórek w pierwszym wierszu), kolumny zostaną wyrównane niezależnie od zawartości. Nie musisz nawet zagnieżdżać tabel, trzy oddzielne tabele wystarczyłyby na przykład.
bobince
1

Opierając się na wymaganiu, że chcesz umieścić obramowanie wokół dowolnego bloku komórek MxN, naprawdę nie ma prostszego sposobu na zrobienie tego bez użycia JavaScript. Jeśli twoje komórki są naprawione, możesz użyć pływaków, ale jest to problematyczne z innych powodów. to, co robisz, może być nudne, ale jest w porządku.

Ok, jeśli jesteś zainteresowany rozwiązaniem w Javascript, używając jQuery (moje preferowane podejście), otrzymujesz ten dość przerażający fragment kodu:

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

Z przyjemnością wysłucham sugestii, jak to zrobić ...

cletus
źródło
1
Wygląda na to, że właśnie dodajesz klasy do tagów td? Dlaczego nie można tego zrobić za pomocą jakiegoś skryptu po stronie serwera, wygenerowanego statycznie lub w najgorszym przypadku tylko ręcznie? Wygląda na to, że nadużywam JavaScript.
Thomas
3
Właściwie plakat ZAPYTAŁ SIĘ o rozwiązanie Javascript. Nie możesz powiedzieć, że to nadużycie Javascript, ponieważ nie ma wystarczającej ilości informacji. Na przykład, czy granice są dodawane z powodu kliknięcia, które robi użytkownik? Jeśli tak, rozwiązanie serwerowe jest nieprawidłowe.
cletus
Przepraszamy za brak informacji. Zostanie to wygenerowane po stronie serwera, więc prawdą jest, że mógłbym po prostu dodać klasy ręcznie, ale podoba mi się sposób, w jaki rozwiązanie JS zapewnia prostszy interfejs do tego. Więc chociaż prawdopodobnie nie pójdę z JS, to dobrze jest zobaczyć.
Kyle Cronin
0

sztuczka polega na właściwości konturu dzięki odpowiedzi enigmentu z niewielkimi modyfikacjami

użyj tej klasy

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

następnie w kodzie HTML

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

a rezultatem jest wprowadź opis obrazu tutaj nadzieja, że ​​to ci pomoże

Basheer AL-MOMANI
źródło
-5

Łatwiejszym sposobem jest uczynienie tabeli kontrolką po stronie serwera. Możesz użyć czegoś podobnego do tego:

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
Curtis
źródło
1
OP prosi o łatwiejszy sposób na zrobienie tego
orique
2
Uważaj, OP prosi również o łatwiejszy sposób zrobienia tego w HTML / CSS. Nie widzę nigdzie w jego pytaniu słowa kluczowego VB lub VBA. Proponuję zajrzeć do naszej sekcji pomocy: stackoverflow.com/help/how-to-answer Good Luck.
ForceMagic,