CSS: Obetnij komórki tabeli, ale zmieści się tak bardzo, jak to możliwe

223

Poznaj Freda. On jest stołem:

Jedna komórka ma więcej treści i jest szersza, druga ma mniej treści i jest węższa

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

Mieszkanie Freda ma dziwaczny zwyczaj zmieniania rozmiaru, więc nauczył się ukrywać część swoich treści, aby nie przepychać wszystkich innych jednostek i nie pchać salonu pani Whitford w zapomnienie:

Komórki mają teraz ten sam rozmiar, ale tylko jedna ma obciętą zawartość i wygląda na to, że jeśli druga komórka dała, jeśli jakieś białe spacje, oba mogłyby się zmieścić.

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

To działa, ale Fred ma dokuczliwe wrażenie, że gdyby jego prawa komórka (którą nazywa się Celldito) poświęciła trochę miejsca, jego lewa komórka nie byłaby skracana przez tak długi czas. Czy możesz ocalić jego zdrowie psychiczne?


Podsumowując: Jak komórki tabeli mogą się przepełniać równomiernie i tylko wtedy, gdy wszystkie z nich zrezygnowały z białych znaków?

s4y
źródło
95
+1 Za scharakteryzowanie wirtualnego obiektu, ładnie jeden pan :)
Myles Gray
6
Podejrzewam, że będziesz musiał skorzystać z JavaScript, aby rozwiązać ten problem.
thirtydot
6
Lolz .. +1 za wartość rozrywkową :) ... czy to musi być dynamiczne, czy nie możesz po prostu ustawić szerokości dla każdej kolumny?
Wojna

Odpowiedzi:

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
źródło
9
Ugh. Działa tak świetnie, ale nie mam pojęcia dlaczego, co mnie denerwuje :(
Shaun Rowan
Dzięki! Nie robi dokładnie tego, co powiedziało pytanie (równomiernie obcina wszystkie kolumny), ale szukałem zachowania tego kodu.
Sam
3
Zauważ też, że możesz wyeliminować <col>s, przygotowując szerokości do <td>stylów: jsfiddle.net/7CURQ/64
Sam.
2
W rzeczywistości wydaje się, że psuje to dynamiczny rozmiar kolumn nieciętych kolumn. Wydają się zawsze zmniejszone do minimalnej szerokości.
Sam
38

Wierzę, że mam rozwiązanie inne niż javascript! Lepiej późno niż wcale, prawda? W końcu jest to doskonałe pytanie, a Google ma już dość. Nie chciałem zadowolić się poprawką javascript, ponieważ uważam, że drżenie rzeczy poruszających się po załadowaniu strony jest niedopuszczalne.

Funkcje :

  • Bez javascript
  • Brak stałego układu
  • Bez sztuczek ważenia lub procentowej szerokości
  • Działa z dowolną liczbą kolumn
  • Proste generowanie po stronie serwera i aktualizacja po stronie klienta (nie są wymagane żadne obliczenia)
  • Kompatybilny z wieloma przeglądarkami

Jak to działa : W komórce tabeli umieść dwie kopie treści w dwóch różnych elementach we względnie pozycjonowanym elemencie kontenera. Element dystansowy jest ustawiony statycznie i jako taki wpłynie na szerokość komórek tabeli. Umożliwiając zawijanie zawartości komórki rozdzielającej, możemy uzyskać szerokość „najlepiej dopasowanego” komórek tabeli, których szukamy. To pozwala nam również użyć elementu pozycjonowanego absolutnie, aby ograniczyć szerokość widocznej treści do szerokości elementu pozycjonowanego względnie.

Testowane i działające w: IE8, IE9, IE10, Chrome, Firefox, Safari, Opera

Obrazy wynikowe :

Ładne proporcjonalne szerokości Ładne proporcjonalne obcinanie

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

Przykładowy 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;
}
Lucyfer Sam
źródło
3
Jeśli treść jest bardzo długim słowem bez spacji, to nie działa, ale wystarczy dodać dzielenie wyrazów do treści w przerywniku za pomocą & nieśmiały; jsfiddle.net/zAeA2/160
Riccardo Casatta
2
to jest całkiem niesamowite! stworzyłem własny wariant, używając attr, aby uniknąć powielania treści: jsfiddle.net/coemL8rf/2
Jayen
@Jayen Nice - Być może użyj titlezamiast, data-spaceraby uzyskać etykietkę po najechaniu myszką :)
William George
@Jayen, właśnie wypróbowałem twój i nie wydaje się on obcinać komórki po prawej stronie, więc nie spełnia wymagań równomiernego przepełnienia komórek. Używam Chrome 46.
Sam
@Sam tak, właśnie tak. mój przykład pokazuje tylko, że oba typy komórek można tworzyć bez powielania treści. nie próbowałem odpowiedzieć na pytanie, po prostu pokazując inny sposób. jeśli zmienisz HTML w moim przykładzie, działa on tak, jak chcesz.
Jayen,
24

Kilka dni temu stanąłem przed tym samym wyzwaniem. Wygląda na to, że Lucyfer Sam znalazł najlepsze rozwiązanie.

Zauważyłem jednak, że powinieneś zduplikować zawartość elementu spacer. Myślałem, że nie jest tak źle, ale chciałbym również zastosować titlewyskakujące okienko do przyciętego tekstu. A to oznacza, że ​​długi tekst pojawi się po raz trzeci w moim kodzie.

Tutaj proponuję uzyskać dostęp do titleatrybutu z :afterpseudoelementu, aby wygenerować spacer i utrzymać HTML w czystości.

Działa na 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
źródło
Nie mogę zgodzić się więcej, genialnie!
Michaił
znacznie lepiej niż inne rozwiązania css, ponieważ działa w obu rzędach, tj. jeśli więcej komórek treści znajduje się za komórką mniej treści.
buggedcom
19

Jeśli JavaScript jest akceptowalny, przygotowałem szybką procedurę, którą możesz wykorzystać jako punkt wyjścia. Dynamicznie próbuje dostosować szerokość komórki za pomocą wewnętrznej szerokości przęsła w reakcji na zdarzenia zmiany rozmiaru okna.

Obecnie zakłada się, że każda komórka zwykle uzyskuje 50% szerokości wiersza i zwinie prawą komórkę, aby utrzymać lewą komórkę na maksymalnej szerokości, aby uniknąć przepełnienia. Można zaimplementować znacznie bardziej złożoną logikę równoważenia szerokości, w zależności od przypadków użycia. Mam nadzieję że to pomoże:

Znaczniki dla wiersza, którego użyłem do testowania:

<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, które łączy zdarzenie zmiany rozmiaru:

$(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
źródło
18

Istnieje o wiele łatwiejsze i bardziej eleganckie rozwiązanie.

W komórce tabeli, którą chcesz zastosować obcinanie, po prostu dołącz div kontenera z układem tabeli css: naprawiono. Ten kontener zajmuje całą szerokość komórki tabeli nadrzędnej, więc działa nawet responsywnie.

Pamiętaj, aby zastosować obcinanie elementów w tabeli.

Działa z 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>

i css:

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

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

oto działający Fiddle https://jsfiddle.net/d0xhz8tb/

satyavh
źródło
To rozwiązanie wymaga 2 dodatkowych elementów na poziomie bloku, aby osiągnąć efekt niestrukturalny. Możliwe jest ustawienie jednej komórki tabeli na „display: table”, co pozwala pozbyć się jednego z div. jsfiddle.net/rza4hfcv Nie jestem pewien, co powinienem o tym pomyśleć. Ale dziękuję za udostępnienie swojego rozwiązania!
armin
Czy wystąpiły jakieś problemy z tym rozwiązaniem? Myślę o użyciu go w profesjonalnym otoczeniu.
armin
@armin, spróbuj powielić komórkę, którą chcesz obciąć: nie możesz umieścić więcej niż jednej strony obok siebie.
DanielM
Nie powiedziałbym jednak, że to ostateczne rozwiązanie. Tracisz jedną z głównych zalet tabeli: zmiana rozmiaru kolumn zgodnie z ich zawartością. Jeśli skonfigurujesz każdą kolumnę w ten sposób, wszystkie będą miały tę samą szerokość, bez względu na długość jej zawartości.
DanielM
@DanielM Możesz rozszerzyć rozwiązanie poprzez dalsze zagnieżdżanie tabeli - jak w starych dniach układania tabeli - ale teraz tylko za pomocą css.
armin
11

Problemem jest „układ tabeli: naprawiony”, który tworzy kolumny o równej szerokości i stałej szerokości. Ale wyłączenie tej właściwości css zabije przepełnienie tekstu, ponieważ tabela stanie się tak duża, jak to możliwe (i wtedy nie ma przepełnienia).

Przykro mi, ale w tym przypadku Fred nie może dostać swojego ciasta i zjeść go ... dopóki właściciel nie zapewni Celldito mniej miejsca do pracy, Fred nie może użyć swojego ...

Andre Haverdings
źródło
9

Możesz spróbować „zważyć” niektóre kolumny, takie jak to:

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

Możesz także wypróbować bardziej interesujące poprawki, takie jak użycie kolumn o szerokości 0% i użycie kombinacji white-spacewłaściwości 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>

Masz pomysł.

Elliot Cameron
źródło
3

Tak, powiedziałbym, że thirtydot ma to, nie da się tego zrobić, chyba że użyjesz metody js. Mówisz o złożonym zestawie warunków renderowania, które będziesz musiał zdefiniować. np. co się stanie, gdy obie komórki stają się zbyt duże dla swoich mieszkań, będziesz musiał zdecydować, kto ma priorytet, lub po prostu dać im procent powierzchni, a jeśli są one przepełnione, oboje zajmą ten obszar i tylko jeśli jedna ma białe znaki, rozciągasz nogi w drugiej komórce, tak czy inaczej, nie ma możliwości zrobienia tego za pomocą css. Chociaż są pewne fajne rzeczy, które ludzie robią z css, o których nie myślałem. Naprawdę wątpię, żebyś mógł to zrobić.

użytkownik648116
źródło
3

Użyj hack css, wydaje się, że display: table-column;może przyjść na ratunek:

<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
źródło
Świetne rozwiązanie! Dzięki!
Valeriu92,
Wyglądał całkiem nieźle, dopóki nie dodałem komórki statycznej przed komórką elastyczną: jsfiddle.net/7u59asyp/5
Sam
to jest jedyna, która działała dla mnie, choć nie idealnie, ponieważ mam 4 kolumny o różnych oczekiwanych rozmiarach treści
dołu
3

Wystarczy dodać następujące reguły do td:

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

Przykład:

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: Jeśli chcesz ustawić niestandardową szerokość na inną tdwłaściwość use min-width.

Alexandre Annic
źródło
Problem polega na tym, że kolumny tabeli domyślnie zajmują miejsce proporcjonalnie. Jeśli zawartość jednego wiersza jest dłuższa niż w drugim, przydzieli większą szerokość. Jednak ta technika równomiernie dzieli przestrzeń. Czy jest w pobliżu praca?
Malik Brahimi,
2

To pytanie pojawia się na górze w Google, więc w moim przypadku użyłem fragmentu css z https://css-tricks.com/snippets/css/truncate-string-with-ellipsis/, ale zastosowanie go do td NIE dało pożądany wynik.

Musiałem dodać znacznik div wokół tekstu w td i elipsa w końcu zadziałała.

Skrócony kod HTML;

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

Skrót CSS;

.truncate { width: 300px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
MarcoZen
źródło
0

Sprawdź, czy „nowrap” rozwiązuje problem do pewnego stopnia. Uwaga: nowrap nie jest obsługiwany w 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
źródło
white-space: nowrapma taki sam efekt jak nowrapatrybut (i używam go w tym przykładzie). Dodanie go tutaj niczego nie zmienia, o ile wiem.
s4y
0

możesz ustawić szerokość prawej komórki na minimalną wymaganą szerokość, a następnie zastosować przelew ukryty + przelew tekstowy do wnętrza lewej komórki, ale Firefox jest tutaj wadliwy ...

choć wydaje się, że Flexbox może pomóc

4esn0k
źródło
0

Ostatnio nad tym pracuję. Sprawdź ten test jsFiddle , spróbuj sam, zmieniając szerokość tabeli podstawowej, aby sprawdzić zachowanie).

Rozwiązaniem jest osadzenie tabeli w innym:

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

Czy Fred jest teraz zadowolony z rozszerzenia Celldito?

IG Pascual
źródło
Przepraszam za brak odpowiedzi! Nie widzę, jak to działa inaczej od pojedynczego stołu. Kiedy przeglądam skrzypce w Chrome lub Firefox, wygląda dokładnie tak, jak drugi zrzut ekranu z pytania. Czy coś brakuje?
s4y
Przepraszamy, link nie był tym, który opublikowałem. To właściwie ten jsfiddle.net/VSZPV/2 . Zmień tekst obu komórek i szerokość głównej tabeli do przetestowania. Mam nadzieję, że to, czego szukasz ...
IG Pascual,
0

Nie wiem, czy to pomoże komukolwiek, ale rozwiązałem podobny problem, określając określone rozmiary szerokości w procentach dla każdej kolumny. Oczywiście działałoby to najlepiej, gdyby każda kolumna zawierała treść o szerokości, która nie różni się zbytnio.

DKO
źródło
-1

Miałem ten sam problem, ale musiałem wyświetlić wiele wierszy (w przypadku text-overflow: ellipsis;niepowodzenia). Rozwiązuję go za pomocą textareawewnętrznej a, TDa następnie projektuję go tak, aby zachowywał się jak komórka tabeli.

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

Biorąc pod uwagę, że „układ tabeli: ustalony” jest niezbędnym wymogiem układu, że tworzy to równomiernie rozmieszczone nieregulowane kolumny, ale że musisz tworzyć komórki o różnych wartościach procentowych, być może ustawisz „colspan” swoich komórek na wielokrotność?

Na przykład, używając całkowitej szerokości 100 do łatwych obliczeń procentowych i mówiąc, że potrzebujesz jednej komórki 80%, a drugiej 20%, rozważ:

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

Oczywiście, w przypadku kolumn 80% i 20%, możesz po prostu ustawić zakres szerokości komórki 100% na 5, 80% na 4, a 20% na 1.

Siubear
źródło
1
Cześć @Siubear. Czym różni się to od określenia procentowej szerokości na tds?
s4y
Używanie colspan w taki sposób to okropny pomysł. Dlaczego zamiast tego nie użyć szerokości?
Percy