61

I have some html tables where the textual data is too large to fit. So, it expands the cell vertically to accommodate for this. So now rows that have the overflow are twice as tall as rows with smaller amounts of data. This is unacceptable. How can I force table to have the same row height of 1em?

Here is some markup that reproduces the problem. Table should only be the height of one line, with the overflowing text hidden.

<!DOCTYPE html>

<html>
  <head>
    <title>Test</title>
    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
    <style type="text/css">
      table { width:250px; }
      table tr { height:1em; overflow:hidden; }
    </style>
  </head>
  <body>
    <table border="1">
      <tr>
        <td>This is a test.</td>
        <td>Do you see what I mean?</td>
        <td>I hate this overflow.</td>
      </tr>
    </table>
  </body>
</html>
Eric Leschinski
  • 146,994
  • 96
  • 417
  • 335
Josh Stodola
  • 81,538
  • 47
  • 180
  • 227
  • Any particular reason you're using a `` rather than doing it with divs/spans+CSS? The 2nd method is more of a pain to get right but offers greater flexibility. I'm not sure it's possible to do what you want using a regular table.
    – Matt Ball Oct 12 '09 at 14:56
  • 80
    I am using a `table` because I am displaying tabular data! – Josh Stodola Oct 12 '09 at 16:31

7 Answers7

105

Need to specify two attributes, table-layout:fixed on table and white-space:nowrap; on the cells. You also need to move the overflow:hidden; to the cells too

table { width:250px;table-layout:fixed; }
table tr { height:1em;  }
td { overflow:hidden;white-space:nowrap;  } 

Here's a Demo . Tested in Firefox 3.5.3 and IE 7

Russ Cam
  • 124,184
  • 33
  • 204
  • 266
  • Only downside (it seems), is that the table cell widths are identical. Any way to get around this? – Josh Stodola Oct 12 '09 at 15:53
  • Not as far as I know - I believe an assumption is made on the browsers part that since no individual cell widths are defined, to split the table width evenly amongst the number of cells. The only possible way to get around this that I can think of would be to calculate a width for each cell based on the number of characters each contains (out of the total number of characters for all cells), either server or client-side (the former probably being the more performant choice). Does this sound overkill? – Russ Cam Oct 12 '09 at 16:01
  • out of total characters in all cells on the row in question is what I meant in my last comment :) – Russ Cam Oct 12 '09 at 16:03
  • Yes I believe that would be overkill. I wish I could get this to work without `table-layout:fixed`, that would be ideal. – Josh Stodola Oct 12 '09 at 16:32
  • @Josh - Removing `table-layout:fixed` stops the overflowing text from being hidden, but as a result, the table width will grow. How would the browser know what width to make each cell (without specified widths for each)? Am I misunderstanding your requirement? – Russ Cam Oct 12 '09 at 16:37
  • Had a similar problem and also needed table to be `display: block` – mahemoff Nov 13 '12 at 13:13
  • I want to limit the maximum height of rows. It doesn't appear that table-layout:fixed and a fixed height on the table and white-space:pre on the cells accomplishes that. (Leaving aside that a fixed height for the whole table is unacceptable anyway.) Is that possible without wrapping cell content in a block level element with overflow:hidden? – enigment Oct 06 '16 at 19:08
24

In general, if you are using white-space: nowrap; it is probably because you know which columns are going to contain content which wraps (or stretches the cell). For those columns, I generally wrap the cell's contents in a span with a specific class attribute and apply a specific width.

Example:

HTML:

<td><span class="description">My really long description</span></td>

CSS:

span.description {
    display: inline-block;
    overflow: hidden;
    white-space: nowrap;
    width: 150px;
}
Troy Alford
  • 26,660
  • 10
  • 64
  • 82
user645077
  • 241
  • 2
  • 2
  • Better approach than setting the whole table fixed. – Matija Grcic Nov 26 '12 at 13:05
  • 4
    This doesn't work with percentage width, such as responsive designs. Ideally, I'd want to set this column to 100% width and have the overflow adjust accordingly as the page is resized. Any hints towards resolving this? – Seaux Nov 27 '13 at 15:33
  • Wow, old thread, but hey - in my use case, I also want the markup not to reside within the innerHtml of the TD element - because I have javascript that allows users to download the tabular data. Again, it's tabular data - not marked-up content - within the table (in my case). – youcantryreachingme Jul 12 '21 at 23:11
10

In most modern browsers, you can now specify:

<table>
 <colgroup>
  <col width="100px" />
  <col width="200px" />
  <col width="145px" />
 </colgroup>
 <thead>
  <tr>
   <th>My 100px header</th>
   <th>My 200px header</th>
   <th>My 145px header</th>
  </tr>
 </thead>
 <tbody>
  <td>100px is all you get - anything more hides due to overflow.</td>
  <td>200px is all you get - anything more hides due to overflow.</td>
  <td>100px is all you get - anything more hides due to overflow.</td>
 </tbody>
</table>

Then if you apply the styles from the posts above, as follows:

table {
    table-layout: fixed; /* This enforces the "col" widths. */
}
table th, table td {
    overflow: hidden;
    white-space: nowrap;
}

The result gives you nicely hidden overflow throughout the table. Works in latest Chrome, Safari, Firefox and IE. I haven't tested in IE prior to 9 - but my guess is that it will work back as far as 7, and you might even get lucky enough to see 5.5 or 6 support. ;)

Troy Alford
  • 26,660
  • 10
  • 64
  • 82
2

Only downside (it seems), is that the table cell widths are identical. Any way to get around this? – Josh Stodola Oct 12 at 15:53

Just define width of the table and width for each table cell

something like

table {border-collapse:collapse; table-layout:fixed; width:900px;}
th {background: yellow; }
td {overflow:hidden;white-space:nowrap; }
.cells1{width:300px;}
.cells2{width:500px;}
.cells3{width:200px;}

It works like a charm :o)

Popara
  • 4,280
  • 2
  • 19
  • 19
  • 1
    But the width will fluctuate based on how much data is to be displayed within it. It's not like I am using monospaced fonts here!! – Josh Stodola Nov 05 '09 at 15:34
2

Here´s something I tried. Basically, I put the "flexible" content (the td which contains lines that are too long) in a div container that´s one line high, with hidden overflow. Then I let the text wrap into the invisible. You get breaks at wordbreaks though, not just a smooth cut-off.

table {
    width: 100%;
}

.hideend {
    white-space: normal;
    overflow: hidden;
    max-height: 1.2em;
    min-width: 50px;
}
.showall {
    white-space:nowrap;
}

<table>
    <tr>
        <td><div class="showall">Show all</div></td>
        <td>
            <div class="hideend">Be a bit flexible about hiding stuff in a long sentence</div>
        </td>
        <td>
            <div class="showall">Show all this too</div>
        </td>
    </tr>
</table>
  • I should add that the advantage here is that I do not need to set any absolute widths of columns. The design is fluid. – John Liungman Feb 27 '14 at 09:00
  • The problem here is, how do you know which cell to assign which class to? Unless you manually type every page you'll ever need, Web 1.0-style, this isn't a catch-all solution. – Wolfie Inu Oct 28 '15 at 09:35
0

If javascript is accepted as an answer, I made a jQuery plugin to address this issue (for more information about the issue see CSS: Truncate table cells, but fit as much as possible).

To use the plugin just type

$('selector').tableoverflow();

Plugin: https://github.com/marcogrcr/jquery-tableoverflow

Full example: http://jsfiddle.net/Cw7TD/3/embedded/result/

Community
  • 1
  • 1
Marco
  • 5,555
  • 2
  • 17
  • 23
0

wrap the table in a div with class="container"

div.container {
    width: 100%;
    overflow-x: auto;
}

then

#table_id tr td {
   white-space:nowrap;
}

result

overflow effect

Dan Alboteanu
  • 9,404
  • 1
  • 52
  • 40