CSS: Tabellenzellen abschneiden, aber so weit wie möglich anpassen

223

Treffen Sie Fred. Er ist ein Tisch:

Eine Zelle hat mehr Inhalt und ist breiter, die andere hat weniger Inhalt und ist schmaler

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

Freds Wohnung hat die bizarre Angewohnheit, ihre Größe zu ändern, deshalb hat er gelernt, einige seiner Inhalte zu verbergen, um nicht alle anderen Einheiten zu verdrängen und Mrs. Whitfords Wohnzimmer in Vergessenheit zu geraten:

Die Zellen haben jetzt die gleiche Größe, aber nur einer hat den Inhalt abgeschnitten, und es sieht so aus, als ob die andere Zelle, wenn ein Leerzeichen angegeben würde, beide passen könnten.

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

Das funktioniert, aber Fred hat das nörgelnde Gefühl, dass seine linke Zelle, wenn seine rechte Zelle (die er Celldito nennt) etwas Platz aufgibt, die meiste Zeit nicht abgeschnitten wird. Kannst du seine geistige Gesundheit retten?


Zusammenfassend: Wie können die Zellen einer Tabelle gleichmäßig überlaufen, und zwar nur dann, wenn alle ihre Leerzeichen aufgegeben haben?

s4y
quelle
95
+1 Zur Charakterisierung eines virtuellen Objekts, schön ein Herr :)
Myles Gray
6
Ich vermute, Sie müssen auf JavaScript zurückgreifen, um dies zu lösen.
dreißig Punkte
6
Lolz .. +1 für Unterhaltungswert :) ... muss dies dynamisch sein oder können Sie nicht einfach eine Breite für jede Spalte festlegen?
Krieg

Antworten:

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
quelle
9
Pfui. Funktioniert so gut, aber ich habe keine Ahnung warum, was mich nervös macht :(
Shaun Rowan
Vielen Dank! Tut nicht genau das, was in der Frage gesagt wurde (alle Spalten gleichmäßig abschneiden), aber das Verhalten dieses Codes ist das, wonach ich gesucht habe.
Sam
3
Beachten Sie auch, dass Sie das <col>s entfernen können, indem Sie stattdessen die Breiten den <td>Stilen voranstellen
Sam
2
Tatsächlich scheint dies die dynamische Spaltengröße der nicht abgeschnittenen Spalten zu beeinträchtigen. Sie scheinen immer auf die minimale Breite geschrumpft zu sein.
Sam
38

Ich glaube, ich habe eine Nicht-Javascript-Lösung! Besser spät als nie, oder? Immerhin ist dies eine ausgezeichnete Frage und Google ist alles drüber hinweg. Ich wollte mich nicht mit einem Javascript-Fix zufrieden geben, da ich den leichten Jitter der Dinge, die sich nach dem Laden der Seite bewegen, als inakzeptabel empfinde.

Eigenschaften :

  • Kein Javascript
  • Kein festes Layout
  • Keine Gewichtung oder Tricks mit prozentualer Breite
  • Funktioniert mit einer beliebigen Anzahl von Spalten
  • Einfache serverseitige Generierung und clientseitige Aktualisierung (keine Berechnung erforderlich)
  • Browserübergreifend kompatibel

So funktioniert es : Platzieren Sie innerhalb der Tabellenzelle zwei Kopien des Inhalts in zwei verschiedenen Elementen in einem relativ positionierten Containerelement. Das Abstandselement ist statisch positioniert und beeinflusst als solches die Breite der Tabellenzellen. Indem wir zulassen, dass der Inhalt der Abstandszelle umbrochen wird, können wir die "am besten passende" Breite der gesuchten Tabellenzellen erhalten. Dies ermöglicht es uns auch, das absolut positionierte Element zu verwenden, um die Breite des sichtbaren Inhalts auf die des relativ positionierten übergeordneten Elements zu beschränken.

Getestet und funktionsfähig in: IE8, IE9, IE10, Chrome, Firefox, Safari, Opera

Ergebnis Bilder :

Schöne proportionale Breiten Schöner proportionaler Ausschnitt

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

Beispiel für 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;
}
Luzifer Sam
quelle
3
Wenn Ihr Inhalt ein sehr langes Wort ohne Leerzeichen ist, funktioniert dies nicht, aber Sie müssen dem Conent in spacer mit & schüchtern; nur eine Silbentrennung hinzufügen. jsfiddle.net/zAeA2/160
Riccardo Casatta
2
das ist ziemlich genial! Ich habe meine eigene Variante mit attr gemacht, um das Duplizieren von Inhalten zu vermeiden: jsfiddle.net/coemL8rf/2
Jayen
@ Jayen Nice - Vielleicht verwenden, titleanstatt data-spacereinen Tooltip über die Maus zu bekommen :)
William George
@ Jayen, ich habe gerade deine ausprobiert und es scheint die Zelle auf der rechten Seite nicht abzuschneiden, so dass es nicht den Anforderungen entspricht, dass die Zellen gleichmäßig überlaufen. Ich benutze Chrome 46.
Sam
@ Sam ja das stimmt. Mein Beispiel zeigt nur, dass beide Zelltypen ohne Duplizieren von Inhalten erstellt werden können. Ich habe nicht versucht, die Frage zu beantworten, sondern nur einen anderen Weg aufzuzeigen. Wenn Sie den HTML-Code in meinem Beispiel ändern, funktioniert er wie gewünscht.
Jayen
24

Ich war vor ein paar Tagen vor der gleichen Herausforderung. Es scheint , Lucifer Sam gefunden , die beste Lösung.

Mir ist jedoch aufgefallen, dass Sie den Inhalt im Abstandselement duplizieren sollten. Ich dachte, es ist nicht so schlimm, aber ich möchte auch titlePopup für abgeschnittenen Text anwenden . Und es bedeutet, dass Langtext zum dritten Mal in meinem Code erscheint.

Hier schlage ich vor, auf titleAttribute von :afterPseudoelementen zuzugreifen , um Spacer zu generieren und HTML sauber zu halten.

Funktioniert mit 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
quelle
Konnte nicht mehr zustimmen, genial!
Mikhail
viel besser als die anderen CSS-Lösungen, da es in beiden Reihenfolgen funktioniert, dh wenn die Zelle mit mehr Inhalten hinter der Zelle mit weniger Inhalten steht.
Buggedcom
19

Wenn Javascript akzeptabel ist, habe ich eine schnelle Routine zusammengestellt, die Sie als Ausgangspunkt verwenden können. Es wird dynamisch versucht, die Zellenbreiten unter Verwendung der inneren Breite eines Bereichs anzupassen, um auf Ereignisse mit Fenstergrößenänderung zu reagieren.

Derzeit wird davon ausgegangen, dass jede Zelle normalerweise 50% der Zeilenbreite erhält, und die rechte Zelle wird reduziert, um die linke Zelle auf ihrer maximalen Breite zu halten und ein Überlaufen zu vermeiden. Abhängig von Ihren Anwendungsfällen können Sie eine viel komplexere Logik für den Breitenausgleich implementieren. Hoffe das hilft:

Markup für die Zeile, die ich zum Testen verwendet habe:

<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, das das Größenänderungsereignis verbindet:

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

Es gibt eine viel einfachere und elegantere Lösung.

Fügen Sie in die Tabellenzelle, auf die Sie die Kürzung anwenden möchten, einfach ein Container-Div mit CSS-Tabellenlayout ein: fest. Dieser Container nimmt die gesamte Breite der übergeordneten Tabellenzelle ein und reagiert sogar.

Stellen Sie sicher, dass die Elemente in der Tabelle abgeschnitten werden.

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

und css:

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

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

Hier ist eine funktionierende Geige https://jsfiddle.net/d0xhz8tb/

Satyavh
quelle
Diese Lösung erfordert 2 zusätzliche Elemente auf Blockebene, um einen nicht strukturellen Effekt zu erzielen. Es ist möglich, eine Tabellenzelle auf "display: table" zu setzen, wodurch Sie einen der divs entfernen können. jsfiddle.net/rza4hfcv Ich bin mir nicht sicher, was ich darüber denken soll. Aber danke, dass Sie Ihre Lösung geteilt haben!
Armin
Haben Sie Probleme mit dieser Lösung gehabt? Ich denke darüber nach, es in einem professionellen Umfeld einzusetzen.
Armin
@armin, versuchen Sie, die Zelle zu duplizieren, die Sie abschneiden möchten: Sie können nicht mehr als eine Seite nebeneinander platzieren.
DanielM
Ich würde jedoch nicht sagen, dass dies eine endgültige Lösung ist. Sie verlieren einen der Hauptvorteile einer Tabelle: Die Größe der Spalten ändert sich entsprechend ihrem Inhalt. Wenn Sie jede Spalte so einrichten, haben alle die gleiche Breite, unabhängig von der Länge ihres Inhalts.
DanielM
@DanielM Sie können die Lösung erweitern, indem Sie die Tabelle weiter verschachteln - wie in den alten Tagen des Tabellenlayouts - aber jetzt nur noch mit CSS.
Armin
11

Das Problem ist das 'Tabellenlayout: fest', das Spalten mit gleichmäßigem Abstand und fester Breite erzeugt. Durch Deaktivieren dieser CSS-Eigenschaft wird jedoch der Textüberlauf beendet, da die Tabelle so groß wie möglich wird (und dann ein Überlauf festgestellt wird).

Es tut mir leid, aber in diesem Fall kann Fred seinen Kuchen nicht haben und ihn essen. Wenn der Vermieter Celldito nicht weniger Platz zum Arbeiten gibt, kann Fred seinen nicht verwenden.

Andre Haverdings
quelle
9

Sie könnten versuchen, bestimmte Spalten wie folgt zu "gewichten":

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

Sie können auch einige interessantere Optimierungen ausprobieren, z. B. Spalten mit einer Breite von 0% und eine Kombination der white-spaceCSS-Eigenschaft.

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

Du hast die Idee.

Elliot Cameron
quelle
3

Ja, ich würde sagen, dreißig Punkte haben es, es gibt keine Möglichkeit, es zu tun, wenn Sie nicht eine js-Methode verwenden. Sie sprechen von einem komplexen Satz von Renderbedingungen, die Sie definieren müssen. Beispiel: Was passiert, wenn beide Zellen zu groß für ihre Wohnungen werden? Sie müssen entscheiden, wer Priorität hat, oder ihnen einfach einen Prozentsatz der Fläche geben. Wenn sie überfüllt sind, nehmen beide diese Fläche ein und nur, wenn eine Leerzeichen hat Sie strecken Ihre Beine in der anderen Zelle, so oder so gibt es keine Möglichkeit, dies mit CSS zu tun. Obwohl es einige ziemlich funky Dinge gibt, die Leute mit CSS machen, an die ich nicht gedacht habe. Ich bezweifle wirklich, dass Sie dies tun können.

user648116
quelle
3

Wie bei der Antwort von samplebias habe ich auch hier, wenn Javascript eine akzeptable Antwort ist, ein jQuery-Plugin speziell für diesen Zweck erstellt: https://github.com/marcogrcr/jquery-tableoverflow

Um das Plugin zu verwenden, geben Sie einfach ein

$('selector').tableoverflow();

Vollständiges Beispiel: http://jsfiddle.net/Cw7TD/3/embedded/result/

Bearbeitungen:

  • Fix in jsfiddle für IE-Kompatibilität.
  • Fix in jsfiddle für eine bessere Browserkompatibilität (Chrome, Firefox, IE8 +).
Marco
quelle
3

Verwenden Sie einen CSS-Hack, es scheint, dass die display: table-column;Dose zur Rettung kommen kann:

<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
quelle
Tolle Lösung! Vielen Dank!
Valeriu92
Sah ziemlich gut aus, bis ich eine statische Zelle vor einer flexiblen Zelle hinzufügte
Sam
Dies ist die einzige, die für mich funktioniert hat, wenn auch nicht perfekt, da ich 4 Spalten mit unterschiedlicher erwarteter Inhaltsgröße habe
Downhand
3

Fügen Sie einfach die folgenden Regeln hinzu td:

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

Beispiel:

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: Wenn Sie eine benutzerdefinierte Breite für eine andere tdVerwendungseigenschaft festlegen möchten min-width.

Alexandre Annic
quelle
Das Problem dabei ist, dass Tabellenspalten standardmäßig proportional Speicherplatz belegen. Wenn der Inhalt einer Zeile länger als der einer anderen ist, wird mehr Breite zugewiesen. Diese Technik teilt den Raum jedoch gleichmäßig auf. Gibt es eine Lösung?
Malik Brahimi
2

Diese Frage taucht bei Google ganz oben auf. In meinem Fall habe ich das CSS-Snippet von https://css-tricks.com/snippets/css/truncate-string-with-ellipsis/ verwendet, aber das Anwenden auf das td hat NICHT ergeben das gewünschte Ergebnis.

Ich musste ein div-Tag um den Text im td hinzufügen und die Auslassungspunkte funktionierten schließlich.

Abgekürzter HTML-Code;

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

Abgekürztes CSS;

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

Überprüfen Sie, ob "nowrap" das Problem bis zu einem gewissen Grad löst. Hinweis: nowrap wird in HTML5 nicht unterstützt

<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
quelle
white-space: nowraphat den gleichen Effekt wie das nowrapAttribut (und ich verwende es im Beispiel). Das Hinzufügen hier ändert nichts, soweit ich das beurteilen kann.
s4y
0

Sie können die Breite der rechten Zelle auf das Minimum der erforderlichen Breite einstellen und dann Überlauf-versteckt + Text-Überlauf auf die Innenseite der linken Zelle anwenden, aber Firefox ist hier fehlerhaft ...

obwohl, scheint, Flexbox kann helfen

4esn0k
quelle
0

Ich habe kürzlich daran gearbeitet. Schauen Sie sich diesen jsFiddle-Test an und versuchen Sie es selbst , indem Sie die Breite der Basistabelle ändern, um das Verhalten zu überprüfen.

Die Lösung besteht darin, eine Tabelle in eine andere einzubetten:

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

Ist Fred jetzt mit Cellditos Expansion zufrieden?

IG Pascual
quelle
Entschuldigung für die fehlende Antwort! Ich kann nicht sehen, wie sich das anders verhält als eine einzelne Tabelle. Wenn ich die Geige in Chrome oder Firefox betrachte, sieht sie genauso aus wie der zweite Screenshot aus der Frage. Vermisse ich etwas
s4y
Entschuldigung, der Link war nicht der, den ich gepostet habe. Es ist eigentlich dieses jsfiddle.net/VSZPV/2 . Ändern Sie den Text beider Zellen und die Breite der zu testenden Haupttabelle. Ich hoffe, es ist das, wonach Sie gesucht haben ...
IG Pascual
0

Ich weiß nicht, ob dies jemandem helfen wird, aber ich habe ein ähnliches Problem gelöst, indem ich für jede Spalte bestimmte Breitengrößen in Prozent angegeben habe. Dies funktioniert natürlich am besten, wenn jede Spalte Inhalte mit einer Breite aufweist, die nicht zu stark variiert.

DKO
quelle
-1

Ich hatte das gleiche Problem, musste aber mehrere Zeilen anzeigen (wo text-overflow: ellipsis;fehlschlägt). Ich löse es mit einem textareainside a TDund gestalte es dann so, dass es sich wie eine Tabellenzelle verhält.

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

Angesichts der Tatsache, dass "Tabellenlayout: fest" die wesentliche Layoutanforderung ist, dass dadurch gleichmäßig verteilte, nicht anpassbare Spalten erstellt werden, Sie jedoch Zellen mit unterschiedlichen prozentualen Breiten erstellen müssen, setzen Sie möglicherweise die "Spalte" Ihrer Zellen auf ein Vielfaches?

Wenn Sie beispielsweise eine Gesamtbreite von 100 für einfache Prozentberechnungen verwenden und sagen, dass Sie eine Zelle mit 80% und eine andere mit 20% benötigen, sollten Sie Folgendes berücksichtigen:

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

Natürlich können Sie für Spalten mit 80% und 20% einfach den Zellen-Colspan mit 100% Breite auf 5, 80% auf 4 und 20% auf 1 setzen.

Siubear
quelle
1
Hey @Siubear. Wie unterscheidet sich das von der Angabe einer prozentualen Breite auf dem tds?
s4y
Colspan so zu benutzen ist eine schreckliche Idee. Warum nicht stattdessen width verwenden?
Percy