Bordure autour de lignes spécifiques dans un tableau?


120

J'essaie de concevoir du HTML / CSS qui peut mettre une bordure autour de lignes spécifiques dans un tableau. Oui, je sais que je ne suis pas vraiment censé utiliser des tableaux pour la mise en page mais je ne connais pas encore assez de CSS pour le remplacer complètement.

Quoi qu'il en soit, j'ai une table avec plusieurs lignes et colonnes, certaines fusionnées avec rowspan et colspan, et j'aimerais mettre une simple bordure autour de certaines parties de la table. Actuellement, j'utilise 4 classes CSS distinctes (haut, bas, gauche, droite) que j'attache aux <td>cellules situées respectivement en haut, en bas, à gauche et à droite du tableau.

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

Existe-t-il un moyen plus simple de faire ce que je veux? J'ai essayé d'appliquer le haut et le bas à un <tr>mais cela n'a pas fonctionné. (ps Je suis nouveau dans CSS, donc il y a probablement une solution vraiment basique à cela que j'ai manquée.)

Remarque: j'ai besoin d'avoir plusieurs sections bordées. L'idée de base est d'avoir plusieurs clusters bordés contenant chacun plusieurs lignes.


9
Hors sujet mais je voulais juste dire, les tableaux sont parfaitement appropriés et recommandés lors de l'affichage de données tabulaires ...
md1337

Réponses:


114

Et pourquoi pas tr {outline: thin solid black;}? Fonctionne pour moi sur des éléments tr ou tbody, et semble être compatible avec la plupart des navigateurs, y compris IE 8+ mais pas avant.


Je demandais de mettre une seule bordure autour de plusieurs lignes dans un tableau, en la divisant essentiellement visuellement en plusieurs sections, mais dans le même tableau afin que les éléments de différentes sections s'alignent.
Kyle Cronin

3
Compris, j'avais besoin de ça aussi. Entourez l'ensemble de lignes sur lequel vous voulez une bordure dans leur propre corps, et le css ci-dessus créera une bordure autour de l'ensemble d'entre eux - c'est-à-dire une bordure supérieure sur la ligne supérieure, une bordure inférieure sur la ligne inférieure et gauche et les bordures droites sur toutes les lignes du corps. Les bordures ne sont pas réellement "sur" ces lignes, elles sont sur le contour du corps lui-même, essayant juste de décrire l'effet.
énigment

Oh, je vois, plusieurs tbodys - cela fonctionne, et c'est quelque chose que je n'avais pas envisagé. Vote positif :)
Kyle Cronin

Je suggérerais d'utiliser la propriété css nth-child () plutôt que de définir tbodys à moins que vous n'ayez vraiment des données assez dynamiques. En utilisant nth-child (), nth-last-child () et not (), vous pouvez sélectionner les lignes / cellules de votre choix (à condition de connaître les index relatifs des éléments du tableau). Par exemple, vous pouvez sélectionner toutes les lignes sauf les deux du haut et celle du bas avec tr: not (: nth-child (-n + 2)): not (: nth-last-child (1))
BT

1
Notez que le contour n'a pas la possibilité de délimiter des côtés spécifiques d'un élément. Il n'y a pas de "contour-top" par exemple. Ceci est une solution limitée
BT

53

Merci à tous ceux qui ont répondu! J'ai essayé toutes les solutions présentées ici et j'ai fait plus de recherches sur Internet pour d'autres solutions possibles, et je pense en avoir trouvé une qui est prometteuse:

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>

Production:

entrez la description de l'image ici

Au lieu d'avoir à ajouter les top, bottom, leftet des rightclasses à tous <td>, tout ce que je dois faire est d' ajouter top rowau sommet <tr>, bottom rowau fond <tr>, et rowà tous <tr>entre les deux. Y a-t-il un problème avec cette solution? Y a-t-il des problèmes multiplateformes dont je devrais être conscient?


Je viens de lancer un test sur les captures d'écran et il semble qu'IE (toutes les versions) n'aime pas les attributs first-child et last-child. : - /
Kyle Cronin

1
On dirait IE 7 & 8 soutien de premier enfant, mais aucun soutien dernier enfant (!) Msdn.microsoft.com/en-us/library/cc351024(VS.85).aspx
mechanical_meat

L' cellspacingattribut est obsolète en HTML5. On dirait que CSS table { border-collapse: collapse; border-spacing: 0; }est la voie à suivre maintenant.
Stefan van den Akker

36

Si vous définissez le border-collapsestyle sur collapsesur la table parent, vous devriez être en mesure de styliser le tr: (les styles sont en ligne pour la démonstration)

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

Production:

Sortie HTML


8

Je jouais juste avec ça aussi, et cela semblait être la meilleure option pour moi:

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

Notez que cela empêchera l'utilisation de largeurs de colonne fluides / automatiques , car les cellules ne s'aligneront plus avec celles des autres lignes, mais le formatage des bordures / couleurs fonctionne toujours correctement. La solution consiste à donner au TR et aux TD une largeur spécifiée (soit px ou%).

Bien sûr, vous pouvez faire le sélecteur tr.myClasssi vous ne souhaitez l'appliquer qu'à certaines lignes. Apparemment, display: tablecela ne fonctionne pas pour IE 6/7, mais il y a probablement d'autres hacks (hasLayout?) Qui pourraient fonctionner pour ceux-là. :-(


6
Cette solution est incorrecte: "display: table" met la ligne entière dans une cellule du tableau --- vous perdez la mise en forme par rapport aux autres lignes du tableau. J'ai essayé ceci dans Firefox et Chromium.
Yaakov Belch

Yaakov, je pense que ce à quoi vous faites référence est que les largeurs de colonne fluides ne s'alignent plus avec les autres lignes du tableau (comme on le voit dans ce violon: jsfiddle.net/MrKtw ) mais le formatage des bordures / couleurs fonctionne toujours bien. La solution consiste à donner au TR et aux TD une largeur spécifiée (soit px ou%).
Simon East

Simon, pour montrer ce que je veux dire, j'ai bifurqué et changé votre violon. Regardez ceci: jsfiddle.net/a6DZV --- J'applique le formatage "display: table" à une seule ligne. Comme vous le voyez, cela transforme efficacement cette ligne en une cellule du tableau. En d'autres termes: vous obtenez le même résultat que l'imbrication de tableaux à une ligne dans une cellule d'un autre tableau (et en affichant la bordure de ce tableau intérieur). Votre solution enregistre quelques nœuds dans le DOM mais n'est pas aussi compatible.
Yaakov Belch

3

Voici une approche utilisant des éléments du corps qui pourrait être le moyen de le faire. Vous ne pouvez pas définir la bordure sur un tbody (comme vous ne pouvez pas sur un tr) mais vous pouvez définir la couleur d'arrière-plan. Si l'effet que vous souhaitez obtenir peut être obtenu avec une couleur d'arrière-plan sur les groupes de lignes au lieu d'une bordure, cela fonctionnera.

<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

Regroupez les lignes à l'aide de l' <tbody>étiquette, puis appliquez le style

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

Et le css dans style.css

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

1

La seule autre façon dont je peux penser pour le faire est de placer chacune des lignes autour desquelles vous avez besoin d'une bordure dans une table imbriquée. Cela rendra la bordure plus facile à faire mais créera potentiellement d'autres problèmes de mise en page, vous devrez définir manuellement la largeur des cellules du tableau, etc.

Votre approche peut être la meilleure en fonction de vos autres exigences de mise en page et l'approche suggérée ici n'est qu'une alternative possible.

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

Merci pour votre réponse; vous avez raison sur les problèmes de mise en page - je préférerais que les colonnes s'alignent sans le faire à la main. Qu'en est-il de l'application d'une classe à une balise <tr> - est-ce possible?
Kyle Cronin

Si vous utilisez un tableau avec «table-layout: fixed» et définissez explicitement la largeur de chaque colonne (en utilisant <col> ou en définissant simplement la largeur des cellules dans la première ligne), les colonnes s'aligneront quel que soit le contenu. Vous n'avez même pas besoin d'imbriquer les tables, trois tables séparées feraient bien l'exemple.
bobince

1

En fonction de votre exigence que vous vouliez placer une bordure autour d'un bloc arbitraire de cellules MxN, il n'y a vraiment pas de moyen plus simple de le faire sans utiliser Javascript. Si vos cellules sont fixes, vous pouvez utiliser des flotteurs, mais cela pose problème pour d'autres raisons. ce que vous faites peut être fastidieux mais ça va.

Ok, si vous êtes intéressé par une solution Javascript, en utilisant jQuery (mon approche préférée), vous vous retrouvez avec ce morceau de code assez effrayant:

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

J'accepterai volontiers des suggestions sur des moyens plus simples de le faire ...


1
On dirait que vous ajoutez simplement des classes aux balises td? Pourquoi cela ne pourrait-il pas être fait avec un script côté serveur, généré statiquement ou dans le pire des cas simplement à la main? Cela me semble être un abus de JavaScript.
Thomas

3
En fait, l'affiche A DEMANDÉ une solution Javascript. Vous ne pouvez pas dire qu'il s'agit d'un abus de Javascript car il n'y a pas assez d'informations. Par exemple, les bordures sont-elles ajoutées parce que l'utilisateur clique dessus? Si tel est le cas, une solution de serveur est incorrecte.
cletus

Désolé pour le manque d'informations. Cela sera généré côté serveur, il est donc vrai que je pourrais simplement ajouter les classes manuellement, mais j'aime la façon dont la solution JS fournit une interface plus simple pour le faire. Donc, même si je n'irai probablement pas avec le JS, c'est une bonne solution à voir.
Kyle Cronin

0

l'astuce est avec la propriété de contour grâce à la réponse d' énigment avec peu de modification

utiliser cette classe

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

puis dans le HTML

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

et le résultat est entrez la description de l'image ici que cela vous aidera


-5

Un moyen plus simple consiste à faire de la table un contrôle côté serveur. Vous pouvez utiliser quelque chose de similaire à ceci:

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 demande un moyen plus simple de le faire
orique

2
Attention, OP demande également un moyen plus simple de le faire en HTML / CSS. Je ne vois nulle part dans sa question le mot clé VB ou VBA. Je vous suggère de jeter un œil à notre section d'aide: stackoverflow.com/help/how-to-answer Bonne chance.
ForceMagic
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.