Header of table remains fixed as user scrolls through data, allowing for easy reference. The left

Above, I have utilized some code from another answer here to display a table. However, I am now contemplating the possibility of customizing it so that the first column remains fixed for horizontal scrolling.

Currently, I'm employing the following as a template:

html

<table>
    <thead>
        <tr>
            <th>Column 1</th>
            <th>Column 2</th>
            <th>Column 3</th>
            <th>Column 4</th>
            <th>Column 5</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>Row 1</td>
            <td>Row 1</td>
            <td>Row 1</td>
            <td>Row 1</td>
            <td>Row 1</td>
        </tr>
        ... // Other rows follow
    </tbody>
</table>

css

html {
    font-family: verdana;
    font-size: 10pt;
    line-height: 25px;
}
... // CSS Styling follows

jquery

$('table').on('scroll', function () {
    $("table > *").width($("table").width() + $("table").scrollLeft());
});

Link to Example

However, my goal is to ensure that the left column remains fixed when scrolling horizontally without going off-screen. I've experimented with setting its position to fixed and absolute but this caused all columns to expose and run off the screen, negating the purpose of vertical scrolling.

Answer №1

After searching extensively for a CSS-only solution without much success, I decided to create a jQuery alternative:

http://jsfiddle.net/m9v1326t/

In this solution, the position of the first column's left property is adjusted based on the scroll position.

var $stickyHeader = $('table thead tr th:first-child');
var $stickyCells = $('table tbody tr td:first-child');

$('table').on('scroll', function () {
  $stickyHeader.css('left', ($(this).scrollLeft()+'px'));
  $stickyCells.css('left', ($(this).scrollLeft()+'px'));
});

To ensure this works correctly, additional styles were included, such as:

table thead tr th:first-child,
table tbody tr td:first-child{
  position:relative;
  ...

The position:relative property is crucial for the modified left attribute to function properly.

You may have to adjust a few more styles for a cleaner appearance of the sticky column (the dashed border helps in revealing underlying cells while scrolling), but this should set you in the right direction.

Please let me know if this meets your requirements.

Answer №2

<!DOCTYPE html>
<html>
<!-- taken from https://bobbysmith.dev -->
<head>
<meta charset="utf-8" />
<title>Single Fixed Table Layout</title>
<style type="text/css">
body, 
html {
    margin: 0px;
    padding: 0px;
    font-family: Arial, Helvetica, sans-serif;
    font-size: 13px;
    background-color: #333;
    width: 100%;
    height: 100%;
}
* {
    margin: 0px;
    padding: 0px;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
}
#container {
    position: absolute;
    left: 50px;
    top: 40px;
    background: cyan;
}
#layersDiv, 
#layers-table, 
#container {
    width: 700px;
}
#viewport {
    overflow-x: scroll;
    overflow-y: hidden;
    width: 483px; /* 500 minus 17px scrollbar width */;
    margin-left: 200px;
}
#headerL,
...
       </td>                                                                                                                                       
     </tr>
        <tr id="lastrow" class="nodrag">
          <td class="layer lastrow"></td>
          <td>last row to pad for scrollbar below</td>
        </tr>
      </table></answer3>
<exanswer2><div class="answer" i="34581614" l="3.0" c="1451844403" a="dXNlcjMwMjc5NA==" ai="30261114">
<pre><code><!DOCTYPE html>
<html>
<!-- taken from https://bobbysmith.dev -->
<head>
<meta charset="utf-8" />
<title>Single Fixed Table Layout</title>
<style type="text/css">
body, 
html {
    margin: 0px;
    padding: 0px;
    font-family: Arial, Helvetica, sans-serif;
    font-size: 13px;
  background-color: #333;
    width: 100%;
    height: 100%;
}
* {
    margin: 0px;
    padding: 0px;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
}
#container {
    position: absolute;
    left: 50px;
    top: 40px;
    background: cyan;
}
#layersDiv, 
#layers-table, 
#container {
    width: 700px;
}
#viewport {
    overflow-x: scroll;
    overflow-y: hidden;
    width: 483px; /* 500 minus 17px scrollbar width */;
    margin-left: 200px;
}
#headerL, #headerR {
    position: absolute;
    height: 25px;
    z-index: 200;
}
#headerL {
    width: 200px;
    background: #f2f5f7;
}
#headerR {
    left: 200px;
    width: 483px; /* 500 minus 17px scrollbar width */;
    overflow-x: hidden;
    background: #f2f5f7;
    overflow: hidden;
}
#layersDiv {
    position: absolute;
    left: 0px;
    top: 0px;
    overflow-x: hidden;
    overflow-y: scroll;
}
#layersDiv, 
#layers-table, 
#viewport, 
#container {
    border-collapse: collapse;
    border-style: hidden;
    height: 180px;
    background: white;
}
#layers-table .layer {
    position: absolute;
    left: 0px;
    width: 200px;
    height: 25px;
}
#layers-table td {
    height: 25px;
    text-align: left;
    border-top: 1px solid Gainsboro;
    border-right: 1px solid Silver;
}
#layers-table {
    margin-top: 25px;
}
.lastrow {
    min-height: 50px;
}
/* timeline ruler*/
#ruler {
    position: relative;
    top: 0;
    left: 0;
    width: 1000px;
    height: 25px;
    background: #f2f5f7;
    border-bottom: #ccc 1px solid;
}
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js" 
type="text/javascript"></script>
<script type="text/javascript"
$(document).ready(function() {
  var ie = !!window.navigator.userAgent.match(/MSIE|Trident|Edge/); //IE screw ups

$("#layersDiv").on('scroll',function(e) { //trick to the single table layout
  if (ie) { $("#viewport").css('overflow-x','hidden'); } //hide horizontal in IE since IE does know how to reflow paint updates.
  var y = $("#layersDiv").scrollTop();
  var h = $("#layersDiv").height();
  $("#viewport").height(h+y);
});
/*IE fires mouseup (or not, depending on which version) when clicking scrollbar. Got to use mouseout*/
$('#layersDiv').on('mouseout',function(e) { if (ie) { $("#viewport").css('overflow-x','scroll'); } });

$('#viewport').on('scroll',function(e) { //need to update ruler position
  $('#headerR').scrollLeft($("#viewport").scrollLeft());
});

$('#layers-table tr:not(:last-child)').on('mousedown',function(e) {
  $('#layers-table td').css( 'background-color','white' );
  $(this).children('td').css( 'background-color','#d8eaf7' );
});

function drawRuler(){
  var canvas = $('#ruler')[0], tick=0, innerTicks=0, count=0; spacing = 10.0,y=0;
  canvas.width=$('#ruler').width(); canvas.height=$('#ruler').height();
  var context= canvas.getContext('2d');
  context.fillStyle = "#808080"; context.strokeStyle="#ccc";
  context.lineWidth = 1; context.font = "11px Arial";
  for(var i=0; i<canvas.width; i++){
    if(innerTicks==3){y=5;tick=25;innerTicks=0}else{y=20;tick=24;innerTicks++}
    var topPos = (i*spacing);
    var x = Math.floor(topPos)+.5;
    context.beginPath();
    context.moveTo(x,y);
    context.lineTo(x,tick);
    if (tick===25) {count++;context.fillText(count+'s',x,15);}
    context.stroke();
  };
}
drawRuler();
}); //end ready
</script>
</head>

<body>

<div id="container">
  <div id="headerL">I don't move </div>
  <div id="headerR">
    <canvas id="ruler">
    </canvas></div>
  <div id="layersDiv">
    <div id="viewport">
      <table id="layers-table">
        <tr id="1">
          <td class="layer">Track 1 </td>
          <td>Audio 1</td>
        </tr>
        <tr id="2">
          <td class="layer">Track 2 </td>
          <td>Audio 2</td>
        </tr>
        <tr id="3">
          <td class="layer">Track 3 </td>
          <td>Audio 3</td>
        </tr>
        <tr id="4">
          <td class="layer">Track 4 </td>
          <td>Audio 4</td>
        </tr>
        <tr id="5">
          <td class="layer">Track 5 </td>
          <td>Audio 5</td>
        </tr>
        <tr id="6">
          <td class="layer">Track 6 </td>
          <td>Audio 6</td>
        </tr>
        <tr id="7">
          <td class="layer">Track 7 </td>
          <td>Audio 7</td>
        </tr>
        <tr id="8">
          <td class="layer">Track 8 </td>
          <td>Audio 8</td>
        </tr>
        <tr id="lastrow" class="nodrag">
          <td class="layer lastrow"></td>
          <td>last row to pad for scrollbar below</td>
        </tr>
      </table>
    </div>
  </div>
</div>

</body>

</html>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

if jade is being inconsistent

I am currently using expressjs in my app and have the following setup: app.get('/profile',index.profile); app.get('/',index.home); Within layout.jade, I have the following code: ... if typeof(username)!=='undefined' ...

Having trouble displaying HTML content in jQuery autocomplete for MVC4

Encountering an issue with the error message "unable to get property of renderItem". Jquery Code $("#term").autocomplete({ // minLength: 1, // require atleast 2 characters to use source: function (req, resp) { // retrieving JSON object from Sear ...

Tips for updating ng-repeat when the modal is closed?

Scenario: I've got a page (angular) containing a repeater. <tr ng-repeat="row in results.leads"> <td>{{row.SubmittedByName}}</td> Inside the repeater, there's a button in a column that triggers a modal to modify the data o ...

IE Form SubmissionThe process of submitting a form in

My attempt to prevent form submission in IE 8 using jQuery 1.8.2 by using e.preventDefault(); is not working as expected. $(document).ready(function () { $("form").submit(function (e) { e.preventDefault(); $.ajax({ .... ...

What is the method to store anchor text in a Session variable?

I'm currently working on a project where I've linked multiple pdf files in the master page. When clicking the anchor, the page redirects to the specified location and displays the pdf in an iframe. Now, I want the text within the anchor tag to be ...

Teaching sessions along with the implementation of functions

I've created a set of input fields with the class replaceInput. The idea is to have a simple function that clears the value when the user focuses on the field, and then returns it to 'X' if the field is empty on focus out. My query is, coul ...

Checking the Value of the Second Child Element Using jQuery

I am struggling with a DIV structure that looks like this: <div class="metafield_table"> <div class="metafield"></div> <div class="metafield"></div> <div class="metafield"> ...

Click on the image to resize the div accordingly

I have a scenario where I need to achieve the following functionality: Two divs are present, with an image inside the first div. When the image is clicked, the left div should resize, and the content on the right side should expand to show full page cont ...

Extract the HTML content from a file stored on the computer

Currently, I am utilizing Google App Engine alongside Python. My goal is to retrieve the tree structure of an HTML file located within the same project as my Python script. Despite attempting numerous approaches, such as using absolute URLs (for example ht ...

An issue with jQuery and LESS causing stylesheets to update only once

Struggling with updating a custom CSS href - everything works perfectly the first time, but subsequent updates do not reflect any changes on the page. Even though I can see the href updating in Chrome debugger and there are no errors being thrown by LESS, ...

Please confirm the modal by adding a textarea with a newline in SweetAlert2

Every time I attempt to add a line break in the textarea input field, the modal pops up. I have tried adding these lines of code as well, but nothing seems to be working: allowEnterKey: false, focusConfirm: false, Does anyone have any advice for solving ...

The "read more" button seems to be malfunctioning

I've been working on integrating a gallery of images into my posts. My goal is to display 4 images initially, followed by a "load more" button that, when clicked, will reveal another set of 4 images, and so on. I have already created the HTML, CSS, an ...

Accordion symbol for adding or subtracting

Looking for a way to change the Toggle text in my angular 7 application accordion to images or content displaying a + sign for collapse and - for expand. I need to achieve this using CSS in my SCSS stylesheet so that I can later change the color of the sig ...

Managing elements within another element in Angular

I am currently exploring the use of Component Based Architecture (CBA) within Angular. Here is the situation I am dealing with: I have implemented three components each with unique selectors. Now, in a 4th component, I am attempting to import these compon ...

What is the process for integrating three.js code manually into an iframe?

I recently posted a question on Stack Overflow inquiring about how to input code into an iframe without using a file or URL. While I was successful with simple cases like <h1>Hello World</h1>, my ultimate goal is to integrate three.js into thes ...

Is there a way to maintain attributes when using jQuery's .replaceWith() function?

As a beginner in jQuery, I find myself following patterns without truly understanding them in a Trac template. Please excuse my ignorance. In Trac 1.0.1 (and possibly other versions), there is a preview feature that utilizes jQuery.replaceWith() to insert ...

search a database field by querying HTML form input

Looking for assistance with creating a query to input a code in an HTML form, search it against a database field, and display the corresponding database fields on a new page. I have already set up the database and established a working PHP script to connec ...

What is the equivalent function for jQT.goTo?

I need help transitioning a jqtouch app to jquery mobile. I am unsure about the proper way to convert this code. showMainMenu: function() { Inventory.loadDealers(); Inventory.enableMenu(false); jQT.goTo('#mainmenu'); ...

Hacking through external script injections into the browser

Curious about how certain software or programs are able to inject html,css,js into a web browser without the need for installing any extensions. Every time I open Chrome or Firefox, I'm bombarded with ads on popular sites like Google homepage, Faceboo ...

Performing a jQuery ajax POST request triggers an automatic subsequent GET request to the exact same URL

I am currently working on a project using jQuery (version 1.4.2) with a Django backend and developing on Firefox (version 3.5.15) running on Debian. I have implemented $.ajax() to send data to the server, which then returns the data back to the browser. Ho ...