CSS: обрезать ячейки таблицы, но вмещать как можно больше

223

Знакомьтесь, Фред. Он стол

Одна ячейка имеет больше контента и шире, а другая меньше контента и уже

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

В квартире Фреда есть странная привычка менять размер, поэтому он научился скрывать часть своего содержания, чтобы не отталкивать все остальные отряды и не забывать о гостиной миссис Уитфорд:

Ячейки теперь имеют одинаковый размер, но их содержание урезано только у одной, и, похоже, если бы другая ячейка дала, если какой-то пробел, они могли бы поместиться.

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

Это работает, но у Фреда есть ноющее чувство, что если бы его правая клетка (которую он по прозвищу Celldito) оставил бы немного места, его левая клетка не была бы урезана столько же времени. Вы можете сохранить его здравомыслие?


В итоге: как ячейки таблицы могут переполняться равномерно и только тогда, когда все они оставили все свои пустые места?

s4y
источник
95
+1 За характеристику виртуального объекта приятно один сэр :)
Майлз Грей
6
Я подозреваю, что вам придется прибегнуть к JavaScript, чтобы решить эту проблему.
Тридцать
6
Lolz .. +1 для развлекательной ценности :) ... это должно быть динамическим или вы не можете просто установить ширину для каждого столбца?
Война

Ответы:

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
Тьфу. Работает так здорово, но я понятия не имею, почему, что заставляет меня нервничать :(
Шон Роуэн
Спасибо! Не выполняет в точности то, что сказано в вопросе (равномерно обрезает все столбцы), но поведение этого кода - то, что я искал.
Сэм
3
Также обратите внимание, что вы можете исключить <col>s, предварительно добавив ширину <td>стилям: jsfiddle.net/7CURQ/64
Сэм,
2
На самом деле, это, кажется, портит динамический размер столбцов не усеченных столбцов. Кажется, они всегда сокращаются до минимальной ширины.
Сэм
38

Я считаю, что у меня есть не-JavaScript-решение! Лучше поздно чем никогда, правильно? В конце концов, это отличный вопрос, и Google во всем. Я не хотел соглашаться на исправление javascript, потому что я считаю недопустимым небольшое дрожание вещей, перемещающихся после загрузки страницы.

Особенности :

  • Нет JavaScript
  • Нет фиксированного макета
  • Нет трюков взвешивания или процентной ширины
  • Работает с любым количеством столбцов
  • Простая генерация на стороне сервера и обновление на стороне клиента (без необходимости расчета)
  • Кросс-браузер совместимый

Как это устроено : Внутри ячейки таблицы поместите две копии содержимого в два разных элемента внутри относительно расположенного элемента контейнера. Элемент spacer позиционируется статически и поэтому влияет на ширину ячеек таблицы. Позволяя обернуть содержимое ячейки-разделителя, мы можем получить наиболее подходящую ширину искомых ячеек таблицы. Это также позволяет нам использовать абсолютно позиционированный элемент, чтобы ограничить ширину видимого содержимого до ширины относительно позиционированного родителя.

Протестировано и работает в: IE8, IE9, IE10, Chrome, Firefox, Safari, Opera

Результат изображения :

Хорошие пропорциональные ширины Хорошее пропорциональное отсечение

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

Пример 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;
}
Люцифер Сэм
источник
3
Если ваш контент представляет собой очень длинное слово без пробелов, это не работает, но вам просто нужно добавить дефис к содержанию в spacer с помощью & shy; jsfiddle.net/zAeA2/160
Риккардо Казатта
2
это довольно круто! я сделал свой собственный вариант , используя Attr , чтобы избежать дублирования контента: jsfiddle.net/coemL8rf/2
Jayen
@Jayen Nice - Возможно, используйте titleвместо того, data-spacerчтобы навести указатель мыши на мышь :)
Уильям Джордж
@Jayen, я только что попробовал твою, и она не обрезает ячейку с правой стороны, поэтому она не отвечает требованию равномерного переполнения клеток. Я использую Chrome 46.
Сэм
@ Сэм, да, верно. Мой пример показывает только то, что оба типа ячеек могут быть созданы без дублирования контента. я не пытался ответить на вопрос, просто показывал другой путь. если вы измените HTML в моем примере, он работает так, как вы хотите.
Jayen
24

Я столкнулся с той же проблемой несколько дней назад. Кажется, Люцифер Сэм нашел лучшее решение.

Но я заметил, что вы должны дублировать контент в элементе spacer. Думаю, это не так плохо, но я хотел бы также применитьtitle всплывающее окно для вырезанного текста. А это значит, что длинный текст появится в моем коде третий раз.

Здесь я предлагаю получить доступ к titleатрибуту из :afterпсевдоэлемента, чтобы сгенерировать прокладку и сохранить HTML в чистоте.

Работает на 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/

Генри Физлер
источник
Не могу согласиться, блестящий!
Михаил
намного лучше, чем другие решения CSS, потому что он работает в обоих порядках, то есть, если ячейка с большим содержанием находится после ячейки с меньшим содержанием.
buggedcom
19

Если Javascript приемлем, я собрал быструю рутину, которую вы могли бы использовать в качестве отправной точки. Он динамически пытается адаптировать ширину ячейки, используя внутреннюю ширину диапазона, в ответ на события изменения размера окна.

В настоящее время предполагается, что каждая ячейка обычно получает 50% ширины строки, и она свернет правую ячейку, чтобы сохранить максимальную ширину левой ячейки, чтобы избежать переполнения. Вы можете реализовать гораздо более сложную логику балансировки ширины, в зависимости от ваших вариантов использования. Надеюсь это поможет:

Разметка для строки, которую я использовал для тестирования:

<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, который подключает событие resize:

$(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
источник
18

Есть гораздо более простое и элегантное решение.

В ячейке таблицы, к которой вы хотите применить усечение, просто добавьте контейнерный контейнер с css table-layout: fixed. Этот контейнер занимает всю ширину ячейки родительской таблицы, поэтому он даже реагирует.

Обязательно примените усечение к элементам в таблице.

Работает с 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>

и CSS:

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

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

вот рабочая скрипка https://jsfiddle.net/d0xhz8tb/

satyavh
источник
Это решение требует 2 дополнительных элемента уровня блока для достижения неструктурного эффекта. Можно установить одну ячейку таблицы в «display: table», что позволяет избавиться от одного из элементов div. jsfiddle.net/rza4hfcv Не уверен, что я должен думать об этом. Но спасибо, что поделились своим решением!
Армин
Были ли у вас проблемы с этим решением? Я думаю об использовании его в профессиональной обстановке.
Армин
@armin, попробуйте продублировать ячейку, которую вы хотите обрезать: вы не можете поместить более одной рядом.
DanielM
Я бы не сказал, что это окончательное решение. Вы теряете одно из основных преимуществ таблицы: размер столбцов изменяется в соответствии с ее содержимым. Если вы настроите каждый столбец таким образом, все они будут иметь одинаковую ширину, независимо от длины содержимого.
ДаниэльМ
@DanielM Вы можете расширить решение, вложив таблицу дальше - как в старые дни размещения таблиц - но теперь только с помощью css.
Армин
11

Проблема заключается в 'table-layout: fixed', которая создает столбцы с равномерно распределенной фиксированной шириной. Но отключение этого css-свойства убьет переполнение текста, потому что таблица станет настолько большой, насколько это возможно (и, следовательно, переполнения не будет).

Извините, но в этом случае Фред не может достать свой пирог и съесть его ... если хозяин не предоставит Celldito меньше места для работы, во-первых, Фред не сможет использовать свой ..

Андре Хавердингс
источник
9

Вы можете попытаться «взвесить» определенные столбцы, например так:

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

Вы также можете попробовать несколько более интересных настроек, например, использовать столбцы с шириной 0% и использовать некоторую комбинацию white-spaceсвойства 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>

Вы поняли идею.

Эллиот Кэмерон
источник
3

Да, я бы сказал, что у тридцатки это не получится, если вы не используете метод js. Вы говорите о сложном наборе условий рендеринга, которые вам придется определить. например, что происходит, когда обе ячейки становятся слишком большими для их квартир, вам нужно будет решить, кто имеет приоритет, или просто дать им процент от площади, и если они переполнены, они обе займут эту область, и только если у одной из них будет пробел, Вы вытягиваете ноги в другой камере, так или иначе нет способа сделать это с помощью CSS. Хотя есть некоторые довольно забавные вещи, которые люди делают с css, о которых я даже не думал. Я действительно сомневаюсь, что вы можете сделать это, хотя.

user648116
источник
3

Как и в случае с ответом на самбле, снова, если Javascript является приемлемым ответом, я специально создал для этого плагин jQuery: https://github.com/marcogrcr/jquery-tableoverflow

Чтобы использовать плагин просто введите

$('selector').tableoverflow();

Полный пример: http://jsfiddle.net/Cw7TD/3/embedded/result/

Редактирование:

  • Исправлена ​​ошибка в jsfiddle для совместимости с IE.
  • Исправление в jsfiddle для лучшей совместимости браузера (Chrome, Firefox, IE8 +).
Marco
источник
3

Используйте хак CSS, кажется, display: table-column;может прийти на помощь:

<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
источник
Отличное решение! Спасибо!
Valeriu92
Выглядело неплохо, пока я не добавил статическую ячейку перед гибкой ячейкой: jsfiddle.net/7u59asyp/5
Сэм,
это единственное, что сработало для меня, хотя и не идеально, поскольку у меня есть 4 столбца с различным ожидаемым размером контента
17
3

Просто добавьте следующие правила к себе td:

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

Пример:

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: если вы хотите установить пользовательскую ширину для другого tdсвойства использования min-width.

Александр Анник
источник
Проблема в том, что по умолчанию столбцы таблицы занимают пространство пропорционально. Если содержимое одного ряда длиннее содержимого другого, оно будет выделять больше ширины. Однако эта техника равномерно делит пространство. Есть ли работа вокруг?
Малик Брахими
2

Этот вопрос всплывает в Google, поэтому в моем случае я использовал фрагмент css по адресу https://css-tricks.com/snippets/css/truncate-string-with-ellipsis/ но его применение к тд не дало желаемый результат.

Мне пришлось добавить тег div вокруг текста в тд, и многоточие наконец заработало.

Сокращенный HTML-код;

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

Сокращенный CSS;

.truncate { width: 300px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
MarcoZen
источник
0

Убедитесь, что "nowrap" решает проблему в определенной степени. Примечание: nowrap не поддерживается в 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
источник
white-space: nowrapимеет тот же эффект, что и nowrapатрибут (и я использую его в примере). Добавление здесь ничего не меняет, насколько я могу судить.
s4y
0

Вы можете установить ширину правой ячейки на минимум необходимой ширины, затем применить overflow-hidden + text-overflow к внутренней части левой ячейки, но Firefox здесь глючит ...

хотя, кажется, flexbox может помочь

4esn0k
источник
0

Я недавно работал над этим. Проверьте этот тест jsFiddle , попробуйте самостоятельно изменить ширину базовой таблицы, чтобы проверить поведение).

Решение состоит в том, чтобы встроить таблицу в другую:

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

Фред теперь доволен расширением Celldito?

И.Г. Паскуаль
источник
Извините за отсутствие ответа! Я не вижу, как это ведет себя по-другому от одной таблицы. Когда я смотрю скрипку в Chrome или Firefox, она выглядит точно так же, как второй скриншот из вопроса. Я что-то упускаю?
s4y
Извините, ссылка была не той, которую я разместил. Это на самом деле этот jsfiddle.net/VSZPV/2 . Измените текст обеих ячеек и ширину основной таблицы для проверки. Надеюсь, это то, что вы ищете ...
IG Pascual
0

Не знаю, поможет ли это кому-нибудь, но я решил похожую проблему, указав конкретные размеры ширины в процентах для каждого столбца. Очевидно, это будет работать лучше всего, если в каждом столбце есть содержимое с шириной, которая не изменяется слишком широко.

ДКО
источник
-1

У меня была та же проблема, но мне нужно было отобразить несколько строк (где происходит text-overflow: ellipsis;сбой). Я решаю это, используя textareaвнутри, TDа затем стиль, чтобы вести себя как ячейка таблицы.

    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
источник
-2

Учитывая, что «table-layout: fixed» является обязательным требованием макета, чтобы при этом создавались равномерно расположенные нерегулируемые столбцы, но что вам нужно делать ячейки с разной шириной в процентах, возможно, установите для «colspan» ваших ячеек кратное число?

Например, используя общую ширину 100 для простых вычислений в процентах и ​​говоря, что вам нужна одна ячейка 80%, а другая 20%, рассмотрите следующее:

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

Конечно, для столбцов 80% и 20% вы можете просто установить colspan ячейки 100% ширины на 5, 80% на 4 и 20% на 1.

Siubear
источник
1
Привет @Siubear. Чем это отличается от указания процента ширины на tds?
s4y
Использование colspan таким способом - ужасная идея. Почему бы не использовать ширину вместо этого?
Перси