0

I have an HTML 5 table with three rows and four columns (two attribute/value pairs per row) on a responsive page (Bootstrap).

In desktop view (or with little content), I would like the table not to fill the entire width available, just enough to show the data. Columns should have individual widths, just enough to show their content. In other words, I want white space to the right of the table, when possible.

In mobile view (or with lots of content), I would like the cell contents to truncate (e.g. using text-overflow: ellipsis;), not to wrap. If possible, I want the attribute columns to truncate first, to a pre-set minimum. It's OK without that prioritization if it can't be solved elegantly.

Desired outcome:

enter image description here

I have browsed Stack Overflow etc. for several hours, and most solutions I find (e.g. 1, 2, 3) demands the width of the table to be set, often to 100%, which is undesirable for my purposes. I have seen people mentioning putting div elements inside td elements, but without examples, and I haven't been able to figure it out on my own.

I don't have to solve this using table, so other solutions are welcome.

Community
  • 1
  • 1
bjornte
  • 749
  • 1
  • 9
  • 31

2 Answers2

1

OK, I found a solution. Fiddle here.

Strategy:

Use a hidden table to glean the desired cell widths of the visible table.

Tactic:

In addition to the table that the user shall see, a hidden "shadow" table, with identical content, must be created directly above the visible table.

The shadow table must allow the content to wrap inside the cells (this is default table behavior).

When the page has loaded and at every window resize, show() the shadow table, measure the width of every td in the top row, then hide() the shadow table. Then copy the width values to the corresponding td elements in the visible table, which must have Chris Coyier's truncate applied.

Works in all browsers I've tested, including mobile.

Bonus tips:

  • Use ­ to wrap long words if necessary, and   to stop words from wrapping. This can be applied only in the shadow table.
  • Use 1px more cell padding in the shadow table due to a bug in Internet Explorer - otherwise, IE's visible table sometimes becomes slightly wider than the shadow table.

JavaScript (requiring jQuery):

<script type="text/javascript">

function loadEvents() {
  initFluidTables();
}

// Resize fluid table(s)
function resizeFluidTables() {

  // Show source cells
  $( ".fluid-table-invisible-source" ).show(0);

  var fluidTableCellWidth = [];

  // Measure (normally invisible) source cells
  $( ".fluid-table-invisible-source td" ).each(function( index, value ) {
    fluidTableCellWidth[index] = $( this ).width();
  });

  // Resize (always visible) target cells. Adding 1 pixel due to apparent bug in Firefox.
  $( ".fluid-table-visible-target td>i" ).each(function( index, value ) {
    $( this ).css({'width': fluidTableCellWidth[index]+1 });
  });

  // Re-hide source cells
  $( ".fluid-table-invisible-source" ).hide();

}

// Create table(s) to be fluid
function initFluidTables() {

  // Create a container. Not really necessary, but keeps DOM tidier.
  $(".fluid-table").wrap( "<div></div>" );

  // This looks like a mess. What it does, is that .fluid-table duplicates itself, and each sibling gets a different class.
  $(".fluid-table").each(function() {
    $( this ).clone().appendTo( $( this ).addClass( "fluid-table-invisible-source" ).parent() ).addClass( "fluid-table-visible-target" );
  });

  // Add truncating element inside target cells
  $(".fluid-table-visible-target td").wrapInner( "<i></i>");

  // Truncate table contents at first drawing of the DOM and every time the window resizes
  resizeFluidTables();
  $( window ).resize(function() {
    resizeFluidTables();
  });
}
</script>

CSS:

.fluid-table td { padding-right: 5px; }

.fluid-table td:nth-child(odd) { color: #aaa; }

.fluid-table-visible-target td>i {
  font-style: inherit;
  white-space: nowrap;
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* source slighly more padded than target due to IE bug */

.fluid-table-invisible-source td:nth-child(even) {
  padding-right: 10px;
}

.fluid-table-visible-target td:nth-child(even) {
  padding-right: 9px;
}

Sample table:

Note use of &shy; and &nbsp; to indicate where you (do not) want the text to truncate.

<table class="fluid-table">
  <tr>
    <td>Avail&shy;able <i>until</i>:</td><td>No&nbsp;expiry date</td><td>Avail&shy;ability:</td><td>Worldwide</td><td></td>
  </tr><tr>
    <td>Year:</td><td>2016</td><td>Length:</td><td>29&nbsp;minutes</td><td></td>
  </tr><tr>
    <td>First broad&shy;cast:</td><td>Feb&nbsp;2</td><td>Last broad&shy;cast:</td><td>Feb&nbsp;3</td><td></td>
  </tr>
</table>
bjornte
  • 749
  • 1
  • 9
  • 31
0

Try putting a div inside the td and use Chris Coyier's truncate. Also, set the width of the truncate container to 100% to truncate based on the available space rather than a fixed width.

bjornte
  • 749
  • 1
  • 9
  • 31
AJ Meyghani
  • 4,389
  • 1
  • 31
  • 35
  • Hi Amin, thank you for your feedback. I tested this as well as a host of other solutions. Your suggestion, at least in my tests, does not work because the `table` won't shrink horizontally once there are `div` elements with `width:100%` inside it. Chris Coyier's truncate is useful though. I found another solution that includes his CCS and will submit it as an answer. – bjornte Jun 03 '15 at 07:53