GrübelDübel
GrübelDübel

Reputation: 165

Table row is higher than specified with CSS (only iPhone)

My goal is to fix the first column of a table and make the rest of the table scrollable horizontal.

See jsfiddle for reference: https://jsfiddle.net/e1thx7sj/4/ (scrolling omitted)

My main steps to reach this aim are:

  1. Create a copy of the existing table (jquery clone)
  2. Insert this copy next to the existing table
  3. From the copy, remove all table cells except of the first one in each row.
  4. Lay this single column copy with z-index and absolute positioning over the first column of the main table.

This is the code:

var $table = $('.table');
// clone the table and insert it with an additional class
var $fixedColumn = $table.clone().insertBefore($table).addClass('fixed-column');
// remove all cells except of the first column cells
$fixedColumn.find('thead tr:first-child th:not(:first-child)').remove();
$fixedColumn.find('thead tr:not(:first-child) th').remove();
$fixedColumn.find('td:not(:first-child)').remove();

So far so good. But the heights of the rows in the "fixed column" don't fit to the row heights of the main table. It looks like this:

enter image description here

So I wrote a JS funtion (setRowHeightsEqualToBaseTable in jsfiddle) to adpat the row heights.

function setRowHeightsEqualToBaseTable() {
   $fixedColumn.find('tr').each(function(i, elem) {
      var $row = $(this);
      var $fixedColumn = $row.parents('table');
      var $baseTable = $fixedColumn.siblings('table:not(.fixed-column)');
      var cellHeight = $baseTable.find('tr:eq(' + i + ')'[0].getBoundingClientRect().height;
      $row.outerHeight(cellHeight);
   });
}

This works perfectly. But not on iPhone Chrome / iPhone Safari.

Even if the css height attribute is set correctly (36px), the browser calculates another value for the height (56px).

I guess it has something to do with the line-height as this (20px) is the difference between the heights. But I can't figure out why there is this difference.

Upvotes: 2

Views: 336

Answers (1)

G-Cyrillus
G-Cyrillus

Reputation: 106038

Instead remove() to hide your cells, you should use css() (visibility or opacity) , so not only structure but column's & row's size remains identical.

some z-index have to be set and reset to keep content of your cells reacting to mouse events.

For a better interaction with the style, it might also be wised to set that clone one level higher (to deal with overflow:hidden and then overflow:scroll).

example

// get the table
var $table = $('.table');
// clone the table and insert it with an additional class
var $fixedColumn = $table.clone().insertBefore($table).addClass('fixed-column');
// remove all cells except of the first column cells
$fixedColumn.find('thead tr:first-child th:not(:first-child)').css('visibility', 'hidden');
$fixedColumn.find('thead tr:not(:first-child) th').css('visibility', 'hidden');
$fixedColumn.find('td:not(:first-child)').css('visibility', 'hidden');


setRowHeightsEqualToBaseTable();

/**
 * Each tr in the fixed column should have the same height as the underlying table row.
 */
function setRowHeightsEqualToBaseTable() {
  $fixedColumn.find('tr').each(function(i, elem) {
    var $row = $(this);
    var $fixedColumn = $row.parents('table');
    var $baseTable = $fixedColumn.siblings('table:not(.fixed-column)');
    var cellHeight = $baseTable.find('tr:eq(' + i + ')')[0].getBoundingClientRect().height;
    $row.outerHeight(cellHeight);
  });
}

/**
 * On resize of the window the heights of table row may change - update view
 */
$(window).on('resize', function() {
  setRowHeightsEqualToBaseTable();
});
.table-wrapper {
  width:100%;
  position: relative;
  overflow:hidden;
}
.table-parent {
  width:100%;
  overflow:auto;
}
.fixed-column {
  position: absolute;
  left: 0;
  }

.fixed-column th, .fixed-column td {
  background-color: white;
  border-right: 1px solid gray;
}

.table {
    border: none;
    border-collapse: separate;
    display: table;
    border-spacing: 0;
    margin-bottom: 0;
    max-width: 150%;
    width: 150%;
    background-color: transparent;
}

.table > thead > tr > th.first-col {
  width: 130px !important;
  min-width: 130px !important;
  max-width: 130px !important;
}

.table tbody tr td {
  border-left: 1px solid gray;
  border-top: 1px solid gray;
}
.table tbody tr td:first-child {
  border-left: none;
}
.table-parent > .table tr :first-child ~ *,
.table-wrapper .fixed-column tr :first-child {
  background:white;
  position:relative;
  z-index:2
}
.table-wrapper .fixed-column tr :first-child {
  z-index:3
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="table-wrapper">
  <div class="table-parent">
    <table class="table">
      <thead>
        <tr>
          <th rowspan="2" class="first-col">Device Name,<br/>Product Brand</th>
          <th rowspan="2">Lorem ipsum,<br/>Lorem ipsum</th>
          <th rowspan="2" style="width: 100px;">Lorem ipsum</th>
          <th colspan="4">Lorem ipsum</th>
          <th rowspan="2" style="width: 70px;">Lorem ipsum</th>
          <th rowspan="2" style="width: 40px;">Lorem ipsum</th>
        </tr>
        <tr>
          <th style="width: 65px;">V</th>
          <th style="width: 65px;">V</th>
          <th style="width: 65px;">V</th>
          <th style="width: 65px;">V</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td><a href="#">A link</a></td>
          <td>Lorem ipsum</td>
          <td>Lorem ipsum</td>
          <td>Lorem ipsum</td>
          <td>Lorem ipsum</td>
          <td>Lorem ipsum</td>
          <td>Lorem ipsum</td>
          <td>Lorem ipsum</td>
          <td>Lorem ipsum</td>
        </tr>
        <tr>
          <td><a href="#">A link</a></td>
          <td>Lorem ipsum</td>
          <td>Lorem ipsum</td>
          <td>Lorem ipsum</td>
          <td>Lorem ipsum</td>
          <td>Lorem ipsum</td>
          <td>Lorem ipsum</td>
          <td>Lorem ipsum</td>
          <td>Lorem ipsum</td>
        </tr>
        <tr>
          <td><a href="#">A link</a></td>
          <td>Lorem ipsum</td>
          <td>Lorem ipsum</td>
          <td>Lorem ipsum</td>
          <td>Lorem ipsum</td>
          <td>Lorem ipsum</td>
          <td>Lorem ipsum</td>
          <td>Lorem ipsum</td>
          <td>Lorem ipsum</td>
        </tr>
        <tr>
          <td><a href="#">A link</a></td>
          <td>Lorem ipsum</td>
          <td>Lorem ipsum</td>
          <td>Lorem ipsum</td>
          <td>Lorem ipsum</td>
          <td>Lorem ipsum</td>
          <td>Lorem ipsum</td>
          <td>Lorem ipsum</td>
          <td>Lorem ipsum</td>
        </tr>
      </tbody>
    </table>
  </div>
</div>

https://jsfiddle.net/e1thx7sj/7/

Upvotes: 1

Related Questions