CSS: tronca le celle della tabella, ma si adatta il più possibile


223

Incontra Fred. Lui è un tavolo:

Una cella ha più contenuti ed è più ampia, l'altra ha meno contenuti ed è più stretta

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

L'appartamento di Fred ha una strana abitudine di cambiare dimensione, quindi ha imparato a nascondere parte del suo contenuto in modo da non spingere tutte le altre unità e spingere il soggiorno della signora Whitford nell'oblio:

Le celle ora hanno le stesse dimensioni, ma solo una ha il suo contenuto troncato, e sembra che se l'altra cella avesse dato uno spazio bianco, potrebbero adattarsi entrambe.

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

Funziona, ma Fred ha la sensazione fastidiosa che se la sua cella destra (che è soprannominata Celldito) ha lasciato un po 'di spazio, la sua cella sinistra non verrebbe troncata quasi tutto il tempo. Riesci a salvare la sua sanità mentale?


In breve: come possono le celle di una tabella traboccare uniformemente e solo quando hanno rinunciato a tutto il loro spazio bianco?


95
+1 Per la caratterizzazione di un oggetto virtuale, ben un signore :)
Myles Grey

6
Ho il sospetto che dovrai ricorrere a JavaScript per risolvere questo problema.
30

6
Lolz .. +1 per il valore di intrattenimento :) ... questo deve essere dinamico o non puoi semplicemente impostare una larghezza su ogni colonna?
Guerra

Risposte:


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/


9
Ugh. Funziona così bene, ma non ho idea del perché, il che mi rende nervoso :(
Shaun Rowan,

Grazie! Non fa esattamente quello che ha detto la domanda (troncare tutte le colonne in modo uniforme), ma il comportamento di questo codice è quello che stavo cercando.
Sam,

3
Inoltre, tieni presente che puoi eliminare le <col>s anteponendo invece le larghezze agli <td>stili: jsfiddle.net/7CURQ/64
Sam

2
In realtà, ciò sembra rovinare il dimensionamento dinamico delle colonne non troncate. Sembrano essere sempre ridotti alla larghezza minima.
Sam,

38

Credo di avere una soluzione non javascript! Meglio tardi che mai, giusto? Dopo tutto questa è un'ottima domanda e Google è dappertutto. Non volevo accontentarmi di una correzione javascript perché trovo inaccettabile il leggero jitter delle cose che si muovono dopo che la pagina è stata caricata.

Caratteristiche :

  • No JavaScript
  • Nessun layout fisso
  • Nessun trucco o trucchi di larghezza percentuale
  • Funziona con qualsiasi numero di colonne
  • Semplice generazione lato server e aggiornamento lato client (nessun calcolo necessario)
  • Compatibile con più browser

Come funziona : all'interno della cella della tabella posizionare due copie del contenuto in due diversi elementi all'interno di un elemento contenitore relativamente posizionato. L'elemento distanziatore è posizionato staticamente e come tale influenzerà la larghezza delle celle della tabella. Consentendo il contenuto della cella spaziatore da avvolgere, possiamo ottenere la larghezza "best-fit" delle celle della tabella che stiamo cercando. Questo ci consente anche di utilizzare l'elemento posizionato in modo assoluto per limitare la larghezza del contenuto visibile a quella del genitore relativamente posizionato.

Testato e funzionante in: IE8, IE9, IE10, Chrome, Firefox, Safari, Opera

Immagini risultato :

Belle larghezze proporzionali Bel ritaglio proporzionale

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

HTML / CSS di esempio :

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

3
Se il tuo contenuto è una parola molto lunga senza spazi, questo non funziona, ma devi solo aggiungere la sillabazione al concetto in spacer con & shy; jsfiddle.net/zAeA2/160
Riccardo Casatta,

2
è davvero fantastico! ho creato la mia variante usando attr per evitare la duplicazione dei contenuti: jsfiddle.net/coemL8rf/2
Jayen

@Jayen Nice - Forse usa titleinvece di data-spacerottenere una descrizione del mouse sopra :)
William George

@Jayen, ho appena provato il tuo e non sembra troncare la cella sul lato destro, quindi non soddisfa il requisito delle celle che traboccano uniformemente. Sto usando Chrome 46.
Sam,

@Sam sì, è vero. il mio esempio mostra solo che entrambi i tipi di celle possono essere creati senza duplicare il contenuto. non stavo cercando di rispondere alla domanda, semplicemente mostrando un altro modo. se modifichi l'HTML nel mio esempio, funziona come desideri.
Jayen,

24

Ho affrontato la stessa sfida alcuni giorni fa. Sembra che Lucifero Sam abbia trovato la soluzione migliore.

Ma ho notato che dovresti duplicare il contenuto nell'elemento spacer. Pensavo che non fosse così male, ma vorrei anche applicare il titlepopup per il testo troncato. E significa che il testo lungo verrà visualizzato per la terza volta nel mio codice.

Qui propongo di accedere titleall'attributo dallo :afterpseudo-elemento per generare spacer e mantenere HTML pulito.

Funziona su 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/


Non potrei essere più d'accordo, geniale!
Mikhail,

molto meglio delle altre soluzioni CSS perché funziona in entrambi gli ordini, cioè se più cella di contenuto è dopo la cella di contenuto minore.
Buggedcom,

19

Se Javascript è accettabile, ho messo insieme una rapida routine che potresti usare come punto di partenza. Cerca dinamicamente di adattare le larghezze delle celle usando la larghezza interna di una campata, in risposta agli eventi di ridimensionamento della finestra.

Attualmente si presume che ogni cella ottenga normalmente il 50% della larghezza della riga e comprimerà la cella destra per mantenere la cella sinistra alla sua larghezza massima per evitare il trabocco. È possibile implementare una logica di bilanciamento della larghezza molto più complessa, a seconda dei casi d'uso. Spero che questo ti aiuti:

Markup per la riga che ho usato per i test:

<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 che collega l'evento di ridimensionamento:

$(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);
        }
    });
});

18

C'è una soluzione molto più semplice ed elegante.

All'interno della cella di tabella a cui si desidera applicare il troncamento, è sufficiente includere un div contenitore con layout tabella CSS: fisso. Questo contenitore occupa l'intera larghezza della cella della tabella padre, quindi agisce anche in modo reattivo.

Assicurati di applicare il troncamento agli elementi nella tabella.

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

e css:

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

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

ecco un violino funzionante https://jsfiddle.net/d0xhz8tb/


Questa soluzione richiede 2 elementi aggiuntivi a livello di blocco per ottenere un effetto non strutturale. È possibile impostare una cella di tabella su "display: table", che consente di eliminare uno dei div. jsfiddle.net/rza4hfcv Non sono sicuro, cosa dovrei pensare al riguardo. Ma grazie per aver condiviso la tua soluzione!
Armin,

Hai riscontrato problemi con questa soluzione? Sto pensando di usarlo in un ambiente professionale.
Armin,

@armin, prova a duplicare la cella che vuoi troncare: non puoi mettere più di una fianco a fianco.
DanielM,

Non direi tuttavia che questa è una soluzione finale. Perdi uno dei principali vantaggi di una tabella: il ridimensionamento delle colonne in base al suo contenuto. Se imposti tutte le colonne in questo modo, tutte avranno la stessa larghezza, indipendentemente dalla lunghezza del suo contenuto.
DanielM,

@DanielM Puoi estendere la soluzione annidando ulteriormente la tabella - come nei vecchi giorni di layout della tabella - ma ora solo con CSS.
Armin,

11

Il problema è il "layout di tabella: fisso" che crea colonne a larghezza fissa con spaziatura uniforme. Ma disabilitando questa proprietà css si annulla il overflow del testo perché la tabella diventerà il più grande possibile (e di conseguenza non si nota il overflow).

Mi dispiace, ma in questo caso Fred non può avere la sua torta e mangiarla per ... a meno che il padrone di casa non dia a Celldito meno spazio su cui lavorare in primo luogo, Fred non può usare la sua ..


9

Potresti provare a "ponderare" determinate colonne, in questo modo:

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

Puoi anche provare alcune modifiche più interessanti, come l'utilizzo di colonne con larghezza 0% e l'utilizzo di una combinazione della white-spaceproprietà 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>

Ti viene l'idea.


3

Sì, direi che trenta ce l'ha, non c'è modo di farlo se non si utilizza un metodo js. Stai parlando di un insieme complesso di condizioni di rendering che dovrai definire. ad es. cosa succede quando entrambe le celle stanno diventando troppo grandi per i loro appartamenti dovrai decidere chi ha la priorità o semplicemente dare loro una percentuale dell'area e se sono troppo occupati occuperanno entrambi quell'area e solo se uno ha spazi bianchi allunghi le gambe nell'altra cella, in entrambi i casi non c'è modo di farlo con css. Anche se ci sono alcune cose piuttosto funky che le persone fanno con i CSS a cui non ho pensato. Dubito davvero che tu possa farlo.


3

Come la risposta di esempio, anche se Javascript è una risposta accettabile, ho creato un plug-in jQuery appositamente per questo scopo: https://github.com/marcogrcr/jquery-tableoverflow

Per usare il plugin basta digitare

$('selector').tableoverflow();

Esempio completo: http://jsfiddle.net/Cw7TD/3/embedded/result/

modifiche:

  • Risolto il problema con jsfiddle per la compatibilità con IE.
  • Risolto il problema con jsfiddle per una migliore compatibilità del browser (Chrome, Firefox, IE8 +).

3

Usa alcuni hack CSS, sembra che display: table-column;possa venire in soccorso:

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


Ottima soluzione! Grazie!
Valeriu92,

Sembrava abbastanza buono finché non ho aggiunto una cella statica prima di una cella flessibile: jsfiddle.net/7u59asyp/5
Sam

questo è l'unico che ha funzionato per me, anche se non perfettamente, dal momento che ho 4 colonne con dimensioni dei contenuti previste variabili
downhand

3

Aggiungi semplicemente le seguenti regole al tuo td :

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

Esempio:

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: se vuoi impostare una larghezza personalizzata su un'altra tdproprietà usa min-width.


Il problema è che, per impostazione predefinita, le colonne della tabella consumano spazio in modo proporzionale. Se il contenuto di una riga è più lungo di quello di un'altra, assegnerà più larghezza. Tuttavia, questa tecnica divide uniformemente lo spazio. C'è un lavoro in giro?
Malik Brahimi,

2

Questa domanda appare in primo piano in Google, quindi nel mio caso ho usato lo snippet css da https://css-tricks.com/snippets/css/truncate-string-with-ellipsis/ ma applicandolo al td NON ho dato il risultato desiderato.

Ho dovuto aggiungere un tag div attorno al testo nella td e le ellissi alla fine hanno funzionato.

Codice HTML abbreviato;

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

CSS abbreviato;

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

0

Controlla se "nowrap" risolve il problema in una certa misura. Nota: nowrap non è supportato in 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>


white-space: nowrapha lo stesso effetto nowrapdell'attributo (e lo sto usando nell'esempio). Aggiungerlo qui non cambia nulla, per quanto posso dire.
s4y

0

puoi impostare la larghezza della cella destra al minimo della larghezza richiesta, quindi applicare overflow-hidden + text-overflow all'interno della cella sinistra, ma Firefox è difettoso qui ...

anche se, sembra, la flexbox può aiutare


0

Di recente ci ho lavorato. Dai un'occhiata a questo test jsFiddle , provalo tu stesso modificando la larghezza della tabella di base per verificare il comportamento).

La soluzione è incorporare una tabella in un'altra:

<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 è ora felice con l'espansione di Celldito?


Ci scusiamo per la mancanza di risposta! Non riesco a vedere come si comporta diversamente da una singola tabella. Quando visualizzo il violino in Chrome o Firefox, sembra esattamente come il secondo screenshot della domanda. Mi sto perdendo qualcosa?
s4y,

Siamo spiacenti, il link non era quello che ho pubblicato. In realtà è questo jsfiddle.net/VSZPV/2 . Modifica il testo di entrambe le celle e la larghezza della tabella principale da testare. Spero sia quello che cercavi ...
IG Pascual,

0

Non so se questo aiuterà qualcuno, ma ho risolto un problema simile specificando dimensioni di larghezza specifiche in percentuale per ogni colonna. Ovviamente, questo funzionerebbe meglio se ogni colonna avesse un contenuto con larghezza che non varia troppo ampiamente.


-1

Ho avuto lo stesso problema, ma avevo bisogno di visualizzare più righe (dove text-overflow: ellipsis;fallisce). Lo risolvo usando un textareainterno a TDe quindi lo stile per comportarsi come una cella di tabella.

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

-2

Dato che "layout di tabella: fisso" è il requisito di layout essenziale, che questo crea colonne non regolabili uniformemente distanziate, ma che è necessario creare celle con diverse larghezze percentuali, forse impostare il "colspan" delle celle su un multiplo?

Ad esempio, utilizzando una larghezza totale di 100 per semplici calcoli percentuali e affermando che è necessaria una cella dell'80% e un'altra del 20%, considerare:

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

Ovviamente, per le colonne dell'80% e del 20%, è possibile impostare solo la colonna di celle di larghezza 100% su 5, l'80% su 4 e il 20% su 1.


1
Ehi @Siubear. In che modo differisce dallo specificare una larghezza percentuale sulla tds?
s4y,

Usare colspan in questo modo è un'idea orribile. Perché non usare invece la larghezza?
Percy,
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.