CSS: tronquer les cellules du tableau, mais tenir autant que possible

223

Rencontrez Fred. C'est une table:

Une cellule a plus de contenu et est plus large, l'autre a moins de contenu et est plus étroite

<table border="1" style="width: 100%;">
    <tr>
        <td>This cells has more content</td>
        <td>Less content here</td>
    </tr>
</table>

L'appartement de Fred a une habitude bizarre de changer de taille, alors il a appris à cacher une partie de son contenu afin de ne pas repousser toutes les autres unités et de pousser le salon de Mme Whitford dans l'oubli:

Les cellules ont maintenant la même taille, mais une seule a son contenu tronqué, et il semble que si l'autre cellule a donné un espace, elles pourraient toutes les deux tenir.

<table border="1" style="width: 100%; white-space: nowrap; table-layout: fixed;">
    <tr>
        <td style="overflow: hidden; text-overflow: ellipsis">This cells has more content</td>
        <td style="overflow: hidden; text-overflow: ellipsis">Less content here</td>
    </tr>
</table>

Cela fonctionne, mais Fred a un sentiment persistant que si sa cellule droite (qu'il surnomme Celldito) abandonnait un peu d'espace, sa cellule gauche ne serait pas tronquée autant de fois. Pouvez-vous sauver sa raison?


En résumé: comment les cellules d'un tableau peuvent-elles déborder uniformément, et seulement lorsqu'elles ont toutes abandonné tout leur espace?

s4y
la source
95
+1 Pour la caractérisation d'un objet virtuel, gentiment un monsieur :)
Myles Gray
6
Je suppose que vous devrez recourir à JavaScript pour résoudre ce problème.
thirtydot
6
Lolz .. +1 pour la valeur de divertissement :) ... cela doit-il être dynamique ou ne pouvez-vous pas simplement définir une largeur sur chaque colonne?
Guerre

Réponses:

82
<table border="1" style="width: 100%;">
    <colgroup>
        <col width="100%" />
        <col width="0%" />
    </colgroup>
    <tr>
        <td style="white-space: nowrap; text-overflow:ellipsis; overflow: hidden; max-width:1px;">This cell has more content.This cell has more content.This cell has more content.This cell has more content.This cell has more content.This cell has more content.</td>
        <td style="white-space: nowrap;">Less content here.</td>
    </tr>
</table>

http://jsfiddle.net/7CURQ/

ladislav
la source
9
Pouah. Fonctionne si bien, mais je ne sais pas pourquoi, ce qui me rend nerveux :(
Shaun Rowan
Merci! Ne fait pas exactement ce que la question a dit (tronquer toutes les colonnes uniformément), mais le comportement de ce code est ce que je cherchais.
Sam
3
Notez également que vous pouvez éliminer les <col>s en ajoutant à la place les largeurs aux <td>styles: jsfiddle.net/7CURQ/64
Sam
2
En fait, cela semble gâcher le dimensionnement dynamique des colonnes des colonnes non tronquées. Ils semblent toujours être réduits à une largeur minimale.
Sam
38

Je crois avoir une solution non javascript! Mieux vaut tard que jamais, n'est-ce pas? Après tout, c'est une excellente question et Google est partout. Je ne voulais pas me contenter d'un correctif javascript car je trouve inacceptable la légère gigue des choses qui se déplacent après le chargement de la page.

Caractéristiques :

  • Pas de javascript
  • Pas de disposition fixe
  • Aucune astuce de pondération ou de pourcentage de largeur
  • Fonctionne avec n'importe quel nombre de colonnes
  • Génération simple côté serveur et mise à jour côté client (aucun calcul nécessaire)
  • Compatible avec plusieurs navigateurs

Fonctionnement : à l'intérieur de la cellule du tableau, placez deux copies du contenu dans deux éléments différents au sein d'un élément conteneur relativement positionné. L'élément d'espacement est positionné de manière statique et, en tant que tel, affectera la largeur des cellules du tableau. En permettant au contenu de la cellule d'espacement de s'enrouler, nous pouvons obtenir la largeur "la mieux adaptée" des cellules du tableau que nous recherchons. Cela nous permet également d'utiliser l'élément en position absolue pour restreindre la largeur du contenu visible à celle du parent relativement positionné.

Testé et fonctionne dans: IE8, IE9, IE10, Chrome, Firefox, Safari, Opera

Images de résultat :

Belles largeurs proportionnelles Belle coupure proportionnelle

JSFiddle : http://jsfiddle.net/zAeA2/

Exemple HTML / CSS :

<td>
    <!--Relative-positioned container-->
    <div class="container">
        <!--Visible-->
        <div class="content"><!--Content here--></div>
        <!--Hidden spacer-->
        <div class="spacer"><!--Content here--></div>
        <!--Keeps the container from collapsing without
            having to specify a height-->
        <span>&nbsp;</span>
     </div>
</td>

.container {
    position: relative;
}
.content {
    position: absolute;
    max-width: 100%;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.spacer {
    height: 0;
    overflow: hidden;
}
Lucifer Sam
la source
3
Si votre contenu est un mot très long sans espaces, cela ne fonctionne pas, mais il vous suffit d'ajouter une césure au contenu dans l'espaceur avec & shy; jsfiddle.net/zAeA2/160
Riccardo Casatta
2
c'est assez génial! j'ai fait ma propre variante en utilisant attr pour éviter la duplication de contenu: jsfiddle.net/coemL8rf/2
Jayen
@Jayen Nice - Peut-être utiliser titleau lieu de data-spacerpour obtenir une info-bulle sur la souris sur :)
William George
@Jayen, je viens d'essayer le vôtre et il ne semble pas tronquer la cellule sur le côté droit, donc il ne répond pas aux exigences des cellules débordant uniformément. J'utilise Chrome 46.
Sam
@ Sam oui c'est vrai. mon exemple montre seulement que les deux types de cellules peuvent être créés sans dupliquer le contenu. je n'essayais pas de répondre à la question, montrant simplement une autre façon. si vous changez le HTML dans mon exemple, cela fonctionne comme vous le souhaitez.
Jayen
24

J'ai été confronté au même défi il y a quelques jours. Il semble que Lucifer Sam ait trouvé la meilleure solution.

Mais j'ai remarqué que vous devez dupliquer le contenu à l'élément d'espacement. Je pensais que ce n'était pas si mal, mais j'aimerais également appliquer une titlefenêtre contextuelle pour le texte coupé. Et cela signifie qu'un texte long apparaîtra pour la troisième fois dans mon code.

Ici, je propose d'accéder à l' titleattribut à partir du :afterpseudo-élément pour générer un espaceur et garder le HTML propre.

Fonctionne sur IE8 +, FF, Chrome, Safari, Opera

<table border="1">
  <tr>
    <td class="ellipsis_cell">
      <div title="This cells has more content">
        <span>This cells has more content</span>
      </div>
    </td>
    <td class="nowrap">Less content here</td>
  </tr>
</table>
.ellipsis_cell > div {
    position: relative;
    overflow: hidden;
    height: 1em;
}

/* visible content */
.ellipsis_cell > div > span {
    display: block;
    position: absolute; 
    max-width: 100%;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    line-height: 1em;
}

/* spacer content */
.ellipsis_cell > div:after {
    content: attr(title);
    overflow: hidden;
    height: 0;
    display: block;
}

http://jsfiddle.net/feesler/HQU5J/

Henry Feesler
la source
Je ne pourrais pas être plus d'accord, génial!
Mikhail
beaucoup mieux que les autres solutions CSS car elle fonctionne dans les deux ordres, c'est-à-dire si la cellule la plus contenue est après la cellule la moins contenue.
buggedcom
19

Si Javascript est acceptable, j'ai mis en place une routine rapide que vous pourriez utiliser comme point de départ. Il essaie dynamiquement d'adapter les largeurs de cellule en utilisant la largeur intérieure d'une plage, en réaction aux événements de redimensionnement de fenêtre.

Actuellement, il suppose que chaque cellule obtient normalement 50% de la largeur de la ligne, et elle réduira la cellule de droite pour garder la cellule de gauche à sa largeur maximale pour éviter de déborder. Vous pouvez implémenter une logique d'équilibrage de largeur beaucoup plus complexe, selon vos cas d'utilisation. J'espère que cela t'aides:

Balisage pour la ligne que j'ai utilisée pour les tests:

<tr class="row">
    <td style="overflow: hidden; text-overflow: ellipsis">
    <span>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</span>
    </td>
    <td style="overflow: hidden; text-overflow: ellipsis">
    <span>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</span>
    </td>
</tr>

JQuery qui connecte l'événement de redimensionnement:

$(window).resize(function() {
    $('.row').each(function() {
        var row_width = $(this).width();
        var cols = $(this).find('td');
        var left = cols[0];
        var lcell_width = $(left).width();
        var lspan_width = $(left).find('span').width();
        var right = cols[1];
        var rcell_width = $(right).width();
        var rspan_width = $(right).find('span').width();

        if (lcell_width < lspan_width) {
            $(left).width(row_width - rcell_width);
        } else if (rcell_width > rspan_width) {
            $(left).width(row_width / 2);
        }
    });
});
échantillon de biais
la source
18

Il existe une solution beaucoup plus simple et élégante.

Dans la cellule de tableau à laquelle vous souhaitez appliquer la troncature, incluez simplement un div de conteneur avec CSS table-layout: fixed. Ce conteneur prend toute la largeur de la cellule du tableau parent, il agit donc même de manière réactive.

Assurez-vous d'appliquer la troncature aux éléments du tableau.

Fonctionne à partir d'IE8 +

<table>
  <tr>
    <td>
     <div class="truncate">
       <h1 class="truncated">I'm getting truncated because I'm way too long to fit</h1>
     </div>
    </td>
    <td class="some-width">
       I'm just text
    </td>
  </tr>
</table>

et css:

    .truncate {
      display: table;
      table-layout: fixed;
      width: 100%;
    }

    h1.truncated {
      overflow-x: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }

voici un violon fonctionnel https://jsfiddle.net/d0xhz8tb/

satyavh
la source
Cette solution nécessite 2 éléments de niveau bloc supplémentaires pour obtenir un effet non structurel. Il est possible de définir une cellule de tableau sur "display: table", ce qui vous permet de vous débarrasser de l'une des divs. jsfiddle.net/rza4hfcv Je ne sais pas trop ce que je devrais en penser. Mais merci de partager votre solution!
armin
Avez-vous rencontré des problèmes avec cette solution? Je pense à l'utiliser dans un cadre professionnel.
armin
@armin, essayez de dupliquer la cellule que vous souhaitez tronquer: vous ne pouvez pas en mettre plus d'un côte à côte.
DanielM
Je ne dirais pas cependant que c'est une solution finale. Vous perdez l'un des principaux avantages d'un tableau: le redimensionnement des colonnes en fonction de son contenu. Si vous configurez chaque colonne comme celle-ci, toutes auront la même largeur, quelle que soit la longueur de son contenu.
DanielM
@DanielM Vous pouvez étendre la solution en imbriquant davantage la table - comme dans les anciens jours de mise en page des tables - mais maintenant uniquement avec css.
armin
11

Le problème est la «disposition de la table: fixe» qui crée des colonnes à largeur fixe et à espacement uniforme. Mais la désactivation de cette propriété css va tuer le débordement de texte parce que la table deviendra aussi grande que possible (et qu'il n'y a pas de dépassement).

Je suis désolé mais dans ce cas, Fred ne peut pas avoir son gâteau et le manger à moins que le propriétaire ne donne à Celldito moins d'espace pour travailler en premier lieu, Fred ne peut pas utiliser son ..

Andre Haverdings
la source
9

Vous pouvez essayer de "pondérer" certaines colonnes, comme ceci:

<table border="1" style="width: 100%;">
    <colgroup>
        <col width="80%" />
        <col width="20%" />
    </colgroup>
    <tr>
        <td>This cell has more content.</td>
        <td>Less content here.</td>
    </tr>
</table>

Vous pouvez également essayer quelques ajustements plus intéressants, comme l'utilisation de colonnes à 0% de largeur et l'utilisation d'une combinaison de la white-spacepropriété CSS.

<table border="1" style="width: 100%;">
    <colgroup>
        <col width="100%" />
        <col width="0%" />
    </colgroup>
    <tr>
        <td>This cell has more content.</td>
        <td style="white-space: nowrap;">Less content here.</td>
    </tr>
</table>

Vous avez eu l'idée.

Elliot Cameron
la source
3

Oui, je dirais que thirtydot l'a, il n'y a aucun moyen de le faire à moins d'utiliser une méthode js. Vous parlez d'un ensemble complexe de conditions de rendu que vous devrez définir. Par exemple, que se passe-t-il lorsque les deux cellules deviennent trop grandes pour leurs appartements, vous devrez décider qui a la priorité ou simplement leur donner un pourcentage de la zone et si elles sont trop remplies, elles occuperont toutes les deux cette zone et seulement si l'une a des espaces blancs vous étirez vos jambes dans l'autre cellule, de toute façon il n'y a aucun moyen de le faire avec css. Bien qu'il y ait des choses assez géniales que les gens font avec CSS auxquelles je n'ai pas pensé. Je doute vraiment que vous puissiez le faire.

user648116
la source
3

Comme la réponse de l'échantillon, encore une fois si Javascript est une réponse acceptable, j'ai créé un plugin jQuery spécifiquement à cet effet: https://github.com/marcogrcr/jquery-tableoverflow

Pour utiliser le plugin, tapez simplement

$('selector').tableoverflow();

Exemple complet: http://jsfiddle.net/Cw7TD/3/embedded/result/

Modifications:

  • Correction dans jsfiddle pour la compatibilité IE.
  • Correction dans jsfiddle pour une meilleure compatibilité du navigateur (Chrome, Firefox, IE8 +).
Marco
la source
3

Utilisez un peu de hack CSS, il semble que cela display: table-column;puisse venir à la rescousse:

<div class="myTable">
    <div class="flexibleCell">A very long piece of content in first cell, long enough that it would normally wrap into multiple lines.</div>
    <div class="staticCell">Less content</div>
</div>

.myTable {
    display: table;
    width: 100%;
}

.myTable:before {
    display: table-column;
    width: 100%;
    content: '';
}

.flexibleCell {
    display: table-cell;
    max-width:1px;
    white-space: nowrap;
    text-overflow:ellipsis;
    overflow: hidden;
}

.staticCell {
    white-space: nowrap;
}

JSFiddle: http://jsfiddle.net/blai/7u59asyp/

blai
la source
Excellente solution! Merci!
Valeriu92
Ça avait l'air bien jusqu'à ce que j'ajoute
Sam
c'est le seul qui a fonctionné pour moi, mais pas tout à fait, puisque j'ai 4 colonnes avec différentes tailles contenu attendu
downhand
3

Ajoutez simplement les règles suivantes à votre td:

overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
// These ones do the trick
width: 100%;
max-width: 0;

Exemple:

table {
  width: 100%
}

td {
  white-space: nowrap;
}

.td-truncate {
  overflow: hidden;
  text-overflow: ellipsis;
  width: 100%;
  max-width: 0;
}
<table border="1">
  <tr>
    <td>content</td>
    <td class="td-truncate">long contenttttttt ttttttttt ttttttttttttttttttttttt tttttttttttttttttttttt ttt tttt ttttt ttttttt tttttttttttt ttttttttttttttttttttttttt</td>
    <td>other content</td>
  </tr>
</table>

PS: si vous souhaitez définir une largeur personnalisée sur une autre tdpropriété use min-width.

Alexandre Annic
la source
Le problème est que, par défaut, les colonnes de table consomment de l'espace proportionnellement. Si le contenu d'une ligne est plus long que celui d'une autre, il allouera davantage de largeur. Cependant, cette technique divise également l'espace. Y at-il un travail autour?
Malik Brahimi
2

Cette question apparaît en haut dans Google, donc dans mon cas, j'ai utilisé l'extrait css de https://css-tricks.com/snippets/css/truncate-string-with-ellipsis/ mais l'appliquer au td n'a PAS donné le résultat souhaité.

J'ai dû ajouter une balise div autour du texte dans le td et les points de suspension ont finalement fonctionné.

Code HTML abrégé;

<table style="width:100%">
 <tr>
    <td><div class='truncate'>Some Long Text Here</div></td>
 </tr>
</table>

CSS abrégé;

.truncate { width: 300px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
MarcoZen
la source
0

Vérifiez si "nowrap" résout le problème dans une certaine mesure. Remarque: nowrap n'est pas pris en charge en HTML5

<table border="1" style="width: 100%; white-space: nowrap; table-layout: fixed;">
<tr>
    <td style="overflow: hidden; text-overflow: ellipsis;" nowrap >This cells has more content  </td>
    <td style="overflow: hidden; text-overflow: ellipsis;" nowrap >Less content here has more content</td>
</tr>

amlan
la source
white-space: nowrapa le même effet que l' nowrapattribut (et je l'utilise dans l'exemple). L'ajouter ici ne change rien, pour autant que je sache.
s4y
0

vous pouvez définir la largeur de la cellule de droite au minimum de la largeur requise, puis appliquer le débordement caché + le débordement de texte à l'intérieur de la cellule de gauche, mais Firefox est bogué ici ...

bien que, semble-t-il, flexbox peut aider

4esn0k
la source
0

J'ai récemment travaillé dessus. Découvrez ce test jsFiddle , essayez-le vous-même en modifiant la largeur de la table de base pour vérifier le comportement).

La solution consiste à incorporer une table dans une autre:

<table style="width: 200px;border:0;border-collapse:collapse">
    <tbody>
        <tr>
            <td style="width: 100%;">
                <table style="width: 100%;border:0;border-collapse:collapse">
                    <tbody>
                        <tr>
                            <td>
                                <div style="position: relative;overflow:hidden">
                                    <p>&nbsp;</p>
                                    <p style="overflow:hidden;text-overflow: ellipsis;position: absolute; top: 0pt; left: 0pt;width:100%">This cells has more content</p>
                                </div>
                            </td>
                        </tr>
                    </tbody>
                </table>
            </td>
            <td style="white-space:nowrap">Less content here</td>
        </tr>
    </tbody>
</table>

Fred est-il maintenant satisfait de l'expansion de Celldito?

IG Pascual
la source
Désolé pour le manque de réponse! Je ne vois pas comment cela se comporte différemment d'une seule table. Lorsque je vois le violon dans Chrome ou Firefox, il ressemble exactement à la deuxième capture d'écran de la question. Suis-je en train de manquer quelque chose?
s4y
Désolé, le lien n'était pas celui que j'ai publié. C'est en fait celui-ci jsfiddle.net/VSZPV/2 . Modifiez le texte des deux cellules et la largeur du tableau principal à tester. J'espère que c'est ce que vous cherchez ...
IG Pascual
0

Je ne sais pas si cela aidera quelqu'un, mais j'ai résolu un problème similaire en spécifiant des tailles de largeur spécifiques en pourcentage pour chaque colonne. Évidemment, cela fonctionnerait mieux si chaque colonne a un contenu dont la largeur ne varie pas trop.

DKO
la source
-1

J'ai eu le même problème, mais j'avais besoin d'afficher plusieurs lignes (où text-overflow: ellipsis;échoue). Je le résous en utilisant un textareaintérieur TDet je le stylise pour qu'il se comporte comme une cellule de tableau.

    textarea {
        margin: 0;
        padding: 0;
        width: 100%;
        border: none;
        resize: none;

        /* Remove blinking cursor (text caret) */
        color: transparent;
        display: inline-block;
        text-shadow: 0 0 0 black; /* text color is set to transparent so use text shadow to draw the text */
        &:focus {
            outline: none;
        }
    }
Nicero
la source
-2

Étant donné que `` table-layout: fixed '' est l'exigence de mise en page essentielle, que cela crée des colonnes non ajustables régulièrement espacées, mais que vous devez créer des cellules de différentes largeurs en pourcentage, peut-être définir le `` colspan '' de vos cellules sur un multiple?

Par exemple, en utilisant une largeur totale de 100 pour des calculs de pourcentage faciles et en disant que vous avez besoin d'une cellule de 80% et d'une autre de 20%, considérez:

<TABLE width=100% style="table-layout:fixed;white-space:nowrap;overflow:hidden;">
     <tr>
          <td colspan=100>
               text across entire width of table
          </td>
     <tr>
          <td colspan=80>
               text in lefthand bigger cell
          </td>
          <td colspan=20>
               text in righthand smaller cell
          </td>
</TABLE>

Bien sûr, pour les colonnes de 80% et 20%, vous pouvez simplement définir le colspan de cellule de largeur 100% sur 5, le 80% sur 4 et le 20% sur 1.

Siubear
la source
1
Salut @Siubear. En quoi est-ce différent de spécifier un pourcentage de largeur sur le tds?
s4y
Utiliser colspan de cette manière est une horrible idée. Pourquoi ne pas utiliser plutôt la largeur?
Percy