Pajken
Pajken

Reputation: 519

Fix columns in horizontal scrolling

I am currently trying to fix my first column in a table when the user scrolls in the X-axis. I am using this structure:

<div class="table-wrapper">
    <table id="consumption-data" class="data">
        <thead class="header">
            <tr>
                <th>Month</th>
                <th>Item 1</th>
            </tr>
        </thead>
        <tbody class="results">
            <tr>
                <th>Jan</th>
                <td>3163</td>
            </tr>
            <tr>
                <th>Feb</th>
                <td>3163.7</td>         
            </tr>
            <tr>
                <th>Mar</th>
                <td>3163.7</td>
            </tr>
            <tr>
                <th>Apr</th>
                <td>3163.7</td>    
            </tr>
            <tr>    
                <th>May</th>
                <td>3163.7</td>
            </tr>
            <tr>
                <th>Jun</th>
                <td>3163.7</td>
            </tr>

            <tr>
                <th>...</th>
                <td>...</td>
            </tr>
        </tbody>
    </table>
</div>

The number of items will be picked by the user, i.e. it could be 90 items in the table. This will require scrolling in the X-axis. The question I have got though is:

How do I fix the position of the th tags inside the tbody (and the th:first-child in the thead)?

I have been looking at some other threads, however they do not really explain how I achieve the fixed columns which makes it hard for me to understand what the codes does and what I am supposed to do.

I have also checked on solutions where people split up the header-column in another table. This wont be possible for me because I will export the data to other systems later on.

My css:

.table-wrapper { 
    overflow-x:scroll;
    overflow-y:visible;
}

This fixes the scroll, now comes the work with:

tbody th, 
thead th:first-child {}

Anyone got any ideas?

EDIT: Here is a jsFiddle: https://jsfiddle.net/DJqPf/5/

Upvotes: 28

Views: 114152

Answers (4)

user27188028
user27188028

Reputation: 1

* {
  box-sizing: border-box;
  padding: 0;
  margin: 0;
  border: 0;
  outline: 0;
}

body {
  padding: 40px;
  color: #44546a;
  font-family: Lato, Helvetica, sans-serif;
  font-size: 0;
}

.label {
  overflow: hidden;
  width: 100%;
  font-size: 14px;
  font-weight: 400;
  line-height: 1.3;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.date {
  color: #8497b0;
  font-size: 12px;
  font-weight: 400;
}

.score-value {
  position: relative;
  width: 65px;
  margin: 0 auto;
  font-size: 16px;
  text-align: right;

  &::after {
    content: '';
    position: absolute;
    top: 50%;
    right: -16px;
    display: block;
    width: 8px;
    height: 8px;
    margin-top: -4px;
    border-radius: 50%;
  }

  &--very-bad::after {
    background: #ff6633;
  }

  &--bad::after {
    background: #ffb433;
  }

  &--normal::after {
    background: #ffe133;
  }

  &--good::after {
    background: #8ae55c;
  }

  &--very-good::after {
    background: #47b247;
  }
}

.wrapper {
  border: 1px solid #e6eaf0;
}

table {
  border-collapse: collapse;
}

.table-scores {
  table-layout: fixed;
  width: 180px;
  display: inline-block;
  background: #f9fafc;
  border-right: 1px solid #e6eaf0;
  vertical-align: top;

  td,
  th {
    max-width: 179px;
  }

  th {
    background: #eff1f4;
    text-align: left;
  }
}

.table-data-wrapper {
  display: inline-block;
  overflow-x: scroll;
  vertical-align: top;
  width: calc(100% - 180px);

  table {
    border-left: 0;
  }

 /* to hide the head of the table - uncomment
 table {
 padding-top: 71px;
 }

 thead {
 display: block;
 visibility: hidden;
 } */

  td,
  th {
    width: calc((100vw - 2 * 40px - 180px) / 5);

    @media (min-width: 900px) {
      min-width: calc((100vw - 2 * 40px - 180px) / 5);
      max-width: calc((100vw - 2 * 40px - 180px) / 5);
    }

    @media (max-width: 1023px) {
      min-width: calc((100vw - 2 * 40px - 180px) / 3);
      max-width: calc((100vw - 2 * 40px - 180px) / 3);
    }

    &:not(:last-child) {
      border-right: 1px solid #e6eaf0;
    }
  }
}

th {
  height: 72px;
}

th,
td {
  padding: 0 16px;
}

thead {
  background: #f9fafc;
}

td {
  height: 48px;
}

thead tr,
tbody tr:not(:last-child) {
  border-bottom: 1px solid #e6eaf0;
}
<link href="https://fonts.googleapis.com/css?family=Lato:300,300i,400,400i,700,700i,900,900i&amp;subset=latin-ext"
    rel="stylesheet">

<div class="wrapper">
    <table class="table-scores">
        <thead>
            <tr>
                <th>
                    <div class="label">PRO Scores</div>
                </th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>
                    <div class="label">Pain</div>
                </td>
            </tr>
            <tr>
                <td>
                    <div class="label">Symptoms</div>
                </td>
            </tr>
            <tr>
                <td>
                    <div class="label">Quality of Life</div>
                </td>
            </tr>
            <tr>
                <td>
                    <div class="label">Activity of Daily Living</div>
                </td>
            </tr>
            <tr>
                <td>
                    <div class="label">Activity of Daily Living Activity of Daily Living</div>
                </td>
            </tr>
        </tbody>
    </table>
    <div class="table-data-wrapper">
        <table class="table-data">
            <thead>
                <tr>
                    <th>
                        <div class="label">13. Neuro-QOL: Upper Extremity Function (Fine Motor, ADL)</div>
                        <div class="date">09/05/2017, 06:42 AM PDT</div>
                    </th>
                    <th>
                        <div class="label">09. Neuro-QOL: Anxiety</div>
                        <div class="date">09/01/2017, 07:34 AM PDT</div>
                    </th>
                    <th>
                        <div class="label">SpinePostOpBack_WallaWalla_V4</div>
                        <div class="date">09/01/2017, 05:24 AM PDT</div>
                    </th>
                    <th>
                        <div class="label">BrainTumorFACTBr</div>
                        <div class="date">08/10/2017, 11:59 AM PDT</div>
                    </th>
                    <th>
                        <div class="label">SpinePreOp_V4_</div>
                        <div class="date">08/10/2017, 10:54 AM PDT</div>
                    </th>
                    <th>
                        <div class="label">Post-Op HOOS Survey</div>
                        <div class="date">07/26/2017, 07:32 AM PDT</div>
                    </th>
                    <th>
                        <div class="label">Post-Op KOOS Survey</div>
                        <div class="date">01/25/2017, 11:22 PM PST</div>
                    </th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td>
                        <div class="score-value score-value--very-bad">45</div>
                    </td>
                    <td>
                        <div class="score-value score-value--bad">45.3</div>
                    </td>
                    <td>
                        <div class="score-value score-value--normal">-45</div>
                    </td>
                    <td>
                        <div class="score-value score-value--very-bad">45.345</div>
                    </td>
                    <td>
                        <div class="score-value score-value--very-good">-245.45</div>
                    </td>
                    <td>
                        <div class="score-value score-value--good">-45.221</div>
                    </td>
                    <td>
                        <div class="score-value">-</div>
                    </td>
                </tr>
                <tr>
                    <td>
                        <div class="score-value score-value--bad">45.3</div>
                    </td>
                    <td>
                        <div class="score-value score-value--good">-45.221</div>
                    </td>
                    <td>
                        <div class="score-value">-</div>
                    </td>
                    <td>
                        <div class="score-value score-value--very-good">-45</div>
                    </td>
                    <td>
                        <div class="score-value score-value--normal">45.345</div>
                    </td>
                    <td>
                        <div class="score-value score-value--bad">45</div>
                    </td>
                    <td>
                        <div class="score-value score-value--very-good">-245.45</div>
                    </td>
                </tr>
                <tr>
                    <td>
                        <div class="score-value score-value--very-bad">-45</div>
                    </td>
                    <td>
                        <div class="score-value score-value--very-bad">45.345</div>
                    </td>
                    <td>
                        <div class="score-value score-value--good">45</div>
                    </td>
                    <td>
                        <div class="score-value score-value--very-bad">45.3</div>
                    </td>
                    <td>
                        <div class="score-value">-</div>
                    </td>
                    <td>
                        <div class="score-value score-value--very-bad">-245.45</div>
                    </td>
                    <td>
                        <div class="score-value score-value--normal">-45.221</div>
                    </td>
                </tr>
                <tr>
                    <td>
                        <div class="score-value score-value--very-bad">-45</div>
                    </td>
                    <td>
                        <div class="score-value score-value--very-bad">45.345</div>
                    </td>
                    <td>
                        <div class="score-value score-value--good">45</div>
                    </td>
                    <td>
                        <div class="score-value score-value--very-bad">45.3</div>
                    </td>
                    <td>
                        <div class="score-value">-</div>
                    </td>
                    <td>
                        <div class="score-value score-value--very-bad">-245.45</div>
                    </td>
                    <td>
                        <div class="score-value score-value--normal">-45.221</div>
                    </td>
                </tr>
                <tr>
                    <td>
                        <div class="score-value score-value--very-bad">-45</div>
                    </td>
                    <td>
                        <div class="score-value score-value--very-bad">45.345</div>
                    </td>
                    <td>
                        <div class="score-value score-value--good">45</div>
                    </td>
                    <td>
                        <div class="score-value score-value--very-bad">45.3</div>
                    </td>
                    <td>
                        <div class="score-value">-</div>
                    </td>
                    <td>
                        <div class="score-value score-value--very-bad">-245.45</div>
                    </td>
                    <td>
                        <div class="score-value score-value--normal">-45.221</div>
                    </td>
                </tr>
            </tbody>
        </table>
    </div>
</div>

Upvotes: 0

rafaelcastrocouto
rafaelcastrocouto

Reputation: 12161

SOLVED

https://jsfiddle.net/DJqPf/7/

.table-wrapper { 
    overflow-x:scroll;
    overflow-y:visible;
    width:250px;
    margin-left: 120px;
}
td, th {
    padding: 5px 20px;
    width: 100px;
}
th:first-child {
    position: fixed;
    left: 5px
}

UPDATE

$(function () {  
  $('.table-wrapper tr').each(function () {
    var tr = $(this),
        h = 0;
    tr.children().each(function () {
      var td = $(this),
          tdh = td.height();
      if (tdh > h) h = tdh;
    });
    tr.css({height: h + 'px'});
  });
});
body {
    position: relative;
}
.table-wrapper { 
    overflow-x:scroll;
    overflow-y:visible;
    width:200px;
    margin-left: 120px;
}


td, th {
    padding: 5px 20px;
    width: 100px;
}
tbody tr {
  
}
th:first-child {
    position: absolute;
    left: 5px
}
<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery-2.2.3.min.js"></script>
  <meta charset="utf-8">
  <title>JS Bin</title>
</head>
<body>
<div>
    <h1>SOME RANDOM TEXT</h1>
</div>
<div class="table-wrapper">
    <table id="consumption-data" class="data">
        <thead class="header">
            <tr>
                <th>Month</th>
                <th>Item 1</th>
                <th>Item 2</th>
                <th>Item 3</th>
                <th>Item 4</th>
            </tr>
        </thead>
        <tbody class="results">
            <tr>
                <th>Jan is an awesome month</th>
                <td>3163</td>
                <td>3163</td>
                <td>3163</td>
                <td>3163</td>
            </tr>
            <tr>
                <th>Feb</th>
                <td>3163</td>
                <td>3163</td>
                <td>3163</td>
                <td>3163</td>
            </tr>
            <tr>
                <th>Mar</th>
                <td>3163</td>
                <td>3163</td>
                <td>3163</td>
                <td>3163</td>
            </tr>
            <tr>
                <th>Apr</th>
                <td>3163</td>
                <td>3163</td>
                <td>3163</td>
                <td>3163</td>  
            </tr>
            <tr>    
                <th>May</th>
                <td>3163</td>
                <td>3163</td>
                <td>3163</td>
                <td>3163</td>
            </tr>
            <tr>
                <th>Jun</th>
                <td>3163</td>
                <td>3163</td>
                <td>3163</td>
                <td>3163</td>
            </tr>

            <tr>
                <th>...</th>
                <td>...</td>
                <td>...</td>
                <td>...</td>
                <td>...</td>
            </tr>
        </tbody>
    </table>
</div>

<div>
</div>
</body>
</html>

Upvotes: 48

Adrian P.
Adrian P.

Reputation: 5228

Demo: http://www.jqueryscript.net/demo/jQuery-Plugin-For-Fixed-Table-Header-Footer-Columns-TableHeadFixer/

HTML

<h2>TableHeadFixer Fix Left Column</h2>

<div id="parent">
    <table id="fixTable" class="table">
        <thead>
            <tr>
                <th>Ano</th>
                <th>Jan</th>
                <th>Fev</th>
                <th>Mar</th>
                <th>Abr</th>
                <th>Maio</th>
                <th>Total</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>2012</td>
                <td>110.00</td>
                <td>110.00</td>
                <td>110.00</td>
                <td>110.00</td>
                <td>110.00</td>
                <td>550.00</td>
            </tr>
            <tr>
                <td>2012</td>
                <td>110.00</td>
                <td>110.00</td>
                <td>110.00</td>
                <td>110.00</td>
                <td>110.00</td>
                <td>550.00</td>
            </tr>
            <tr>
                <td>2012</td>
                <td>110.00</td>
                <td>110.00</td>
                <td>110.00</td>
                <td>110.00</td>
                <td>110.00</td>
                <td>550.00</td>
            </tr>
            <tr>
                <td>2012</td>
                <td>110.00</td>
                <td>110.00</td>
                <td>110.00</td>
                <td>110.00</td>
                <td>110.00</td>
                <td>550.00</td>
            </tr>
            <tr>
                <td>2012</td>
                <td>110.00</td>
                <td>110.00</td>
                <td>110.00</td>
                <td>110.00</td>
                <td>110.00</td>
                <td>550.00</td>
            </tr>
        </tbody>
    </table>
</div>

JS

    $(document).ready(function() {
        $("#fixTable").tableHeadFixer({"head" : false, "right" : 1}); 
    });

CSS

    #parent {
        height: 300px;
    }

    #fixTable {
        width: 1800px !important;
    }

https://jsfiddle.net/5gfuqqc4/

Upvotes: 2

Sergey Kharchishin
Sergey Kharchishin

Reputation: 484

Solved using JavaScript + jQuery! I just need similar solution to my project but current solution with HTML and CSS is not ok for me because there is issue with column height + I need more then one column to be fixed. So I create simple javascript solution using jQuery

You can try it here https://jsfiddle.net/kindrosker/ffwqvntj/

All you need is setup home many columsn will be fixed in data-count-fixed-columns parameter

<table class="table" data-count-fixed-columns="2" cellpadding="0" cellspacing="0">

and run js function

app_handle_listing_horisontal_scroll($('#table-listing'))

Upvotes: 5

Related Questions