Freezing Columns and Rows for a Spacious Scrollable Table

After extensive effort, I have been diligently striving to create a solution that allows a table's column headers to scroll with the body horizontally and the first column to scroll with the rows vertically. While I've come across solutions that are close, they either rely on CoffeeScript and Pug or fail when there is more than one table on the page. The behavior demonstrated in this fiddle example from software_christian is exactly what I'm aiming for but unfortunately, I can't seem to replicate it in my development environment using tools like fiddle or codepen.io. Other solutions I've encountered appear to be overly complex.

In addition, the current code I'm utilizing works fine when the page is viewed on my monitor, but encounters issues when displayed on my Mac screen. I'm seeking assistance in devising a straightforward dynamic solution leveraging JQuery, JS, CSS, and HTML to resolve this predicament while adhering to the standard HTML structure of a table.

Ideal HTML Format: (Ideally, I would like a table to remain standard (not scroll) unless I give it a unique class such as "scroll-table")

The following snippets showcase the progress I've made thus far.

$(document).ready(function() {
  $('.scroll-table tbody').scroll(function(e) { //detect a scroll event on the tbody
  
    $(this).siblings('thead').css("left", -$(this).scrollLeft());  scrolling
    $(this).siblings().children().children().css("left", $(this).scrollLeft());
    $(this).children().children().css("left", $(this).scrollLeft());
  });
});
.scroll-table {
  position: relative;
  background-color: #aaa;
  overflow: hidden;
  border-collapse: collapse;
}

.scroll-table thead {
  position: relative;
  display: block; 
  width: auto;
  overflow: visible;
}

.scroll-table thead th {
  background-color: #99a;
  min-width: 154px;
  border: 1px solid #222;
  word-break: break-word;
}

.scroll-table thead th:nth-child(1) {
  position: relative;
  display: table-cell; 
  background-color: #88b;
  min-width: 154px;
  max-width: 154px;
}

.scroll-table tbody {
  position: relative;
  display: block; 
  width: auto;
  height: 239px;
  overflow: scroll;
}

.scroll-table tbody td {
  background-color: #bbc;
  min-width: 154px;
  border: 1px solid #222;
}

.scroll-table tbody tr td:nth-child(1) {  
  position: relative;
  display: block; 
  height: auto;
  background-color: #99a;
  min-width: 154px;
  max-width: 154px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<table class="scroll-table">
    <thead>
        <tr>
            <th>Name</th>
            <th>Town</th>
            <th>County</th>
            <th>Age</th>
            <th>Profession</th>
            <th>Anual Income</th>
            <th>Matital Status</th>
            <th>Children</th>
            <th>Annual Income</th>
            <th>Marital Status</th>
            <th>Cranes</th>
            <th>Bends</th>
        </tr>
    </thead>
    <tbody>
        <tr>
           <!-- Table data goes here -->
        </tr>
    </</table>
Note: Snippet doesn't seem to be working here. Seems like I can only replicate the behavior I'm seeing on my own machine & monitor :( Thank you much!

Answer №1

After starting from scratch, I managed to create a solution that can be applied to multiple tables on a single page with just one class added to the main table container. Check out the code below:

JS -

$(document).ready(function() {
        var wrapper = document.getElementsByClassName('scroll-table-1');

        for (var i = 0; i < wrapper.length; i++) {
            wrapper[i].addEventListener('scroll', function (e) {

                var table = this.closest('table');
                var headerRow = table.querySelector('thead');                        
                var firstCol = table.querySelectorAll('tbody tr td:first-child');
                var topLeftCorner = table.querySelector('thead th:first-child');

                headerRow.setAttribute('style','top:' + this.scrollTop + 'px');
                topLeftCorner.setAttribute('style','left:' + this.scrollLeft + 'px');

                firstCol.forEach((n) => {
                    n.setAttribute('style','left:' + this.scrollLeft + 'px');
                });
            });
        };
    });

CSS:

.scroll-table-1 {
      position: relative;
      display: block; 
      width: auto;
      height: 350px;
      overflow: scroll;
    }

    .scroll-table-1 thead {
      position: relative;
      display: block; 
      width: auto;
      overflow: visible;
    }

    .scroll-table-1 tbody td {
      background-color: #bbc;
      min-width: 154px;
      border: 1px solid #222;
      display: table-cell;
    }

    .scroll-table-1 tbody tr td:nth-child(1) {  
      position: relative;
      display: table-cell; 
      background-color: #99a;
      min-width: 154px;
      max-width: 154px;
      z-index: 10;
    }

    .scroll-table-1 thead th {
      background-color: #99a;
      min-width: 154px;
      border: 1px solid #222;
      word-break: break-word;
      z-index: 15;
    }

    .scroll-table-1 thead th:nth-child(1) {
      position: relative;
      display: table-cell; 
      background-color: #88b;
      min-width: 154px;
      max-width: 154px;
      z-index: 100;
    }

Interestingly, the scrolling works smoothly on my monitor but becomes jittery when I move the window to my mac screen. This behavior puzzles me, but as long as it's functional, I'm content. If anyone can shed light on why this happens, I would appreciate it greatly.

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

Make sure the div is always positioned above everything, including any built-in pop-up windows

When working with two forms, one for user input and the other as a pop-up window to display results, users sometimes close the pop-up window prematurely if they think there is a network issue causing a delay in data execution. To prevent this, I am consi ...

There are multiple sets of radio buttons within nested ng-repeats, but only the final group displays the selected value

I am having an issue with updating a form that contains multiple radio buttons based on data retrieved from an API. The challenge is that only the last set of radio buttons displays the value correctly. Below is the code snippet I am using (angular bracket ...

Struggling with making JSON.parse() function properly in a Discord Bot

I have a separate JSON file connected like this const Players = require('./Database/Players.json'); and a parser that handles the code client.on('message', message => { if (message.content.toLowerCase() ==='smack activate ...

Lazy loading AngularJS UI router named views is an efficient way to improve performance

AngularJS UI router named views loading based on user access rather than loading at the time of state route access. Example: $stateProvider .state("login", { url: "/login", templateUrl: getTemplateUrl("login/Index") }) ...

Utilizing API to Save Images Directly from the Client Side

I am currently in the process of redesigning a website, specifically the Blog section which includes a featured image. I have been researching the best method for saving these images. After following a tutorial that utilized the file.mv() function from ei ...

Vue automatically clears the INPUT field when disabling it

Have you ever noticed why Vue resets a text input field when it's set to disabled? This behavior is not observed with plain Javascript and also doesn't affect textarea fields. var app = new Vue({ el: '.container', data: { disab ...

When I use `console.log` with `req.body` in Node, the password is

Currently, I am utilizing NodeJs on the backend to console.log(req.body) data from a form that gathers usernames and passwords from users. I have noticed that this method exposes the collected username and password information. Should I be concerned abou ...

The object does not have a property named 'fetch' and therefore cannot be read

Struggling to integrate a REST datasource into my Apollo Server. I've created a class that extends RESTDataSource for handling API requests. However, when attempting to call the login method from my GraphQL resolver code, an error is being thrown. An ...

Enhance the php query limit using javascript when loading additional content

Hey there, currently working on implementing a reverse infinite scroll feature for a private messaging module. Everything seems to be functioning well, except for one issue I'm facing - struggling to update the query limit. I set the maximum and lim ...

The local copy of Jquery.min.js is failing to trigger the window load function

Recently, I encountered an issue with the focus of tabs while working with jQuery. Initially, everything was fine when I included: <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.0/jquery.min.js"></script> in my JSP file. The wi ...

Tips for relocating anchor elements to less desirable locations

My website has an issue with anchor elements appearing too frequently and not in the desired location. I need someone to help fix this so there are only two anchors displayed. After checking my code, it seems like there are not more than the specified num ...

What is the best way to vertically align an InputLabel within a MUI Grid item?

I'm trying to vertically center the InputLabel inside a MUI Grid item. Here's what I've attempted: import { FormControl, Grid, Input, InputLabel, TextField } from "@mui/material"; export default function App() ...

Enhancing the Appearance of MUI Date Calendar

I'm in the process of creating a calendar similar to mui's <DateCalendar />, and I want to customize the header from 'S M T W T F S' to 'Sun Mon...' as well as adjust the position of the arrows. Before: https://i.sstat ...

Having trouble with the alignment of CSS menu in Safari?

Can someone please assist me with a strange issue I am experiencing on my website? The menu appears misaligned when using Safari, and it's been driving me crazy. I've tried troubleshooting for hours without success. Here is a link to the site: I ...

Step-by-step guide on achieving 100% height for the <main> element in a Material UI drawer demo

I have a question regarding the Material UI drawer. In my project, I am trying to change the background color of the main tag. However, the main tag's height is restricted to the content inside. Check out this link for reference Setting the height t ...

Could the issue with jQuery selector potentially be connected to AngularJS?

Integrating a third-party web page into an Android webview in our app presents the challenge of automating the login process. Since the app has access to the login credentials for the third-party site, I'd like to execute some Javascript for this purp ...

Ensure that the jQuery Knob is set to submit any modifications only after the final adjustment

Utilizing jQuery Knob by anthonyterrien, I have configured the step to be 20. My goal is to transmit the knob's value to the server. The issue arises when the change function is triggered every time the user adjusts the knob using either a right or le ...

Sending Data from Browser to Node.js using Ajax

I've been struggling to send an AJAX post request to my Node server built with Express for a while now. Despite reading various solutions on similar issues, I couldn't figure out which files to edit. Initially, I attempted using `http.createServe ...

What should I do when dealing with multiple submit buttons in NextJS?

How can I differentiate between two submit buttons in a form component created in Next.js? I'm struggling to determine which button was pressed and need help resolving this issue. import React from "react"; const LoginPage = () => { as ...

Ways to resolve the issue with TypeError: CSS2Properties lacking an index property setter for '0'

I'm currently working on application development using ReactJs and Material UI. When I try to open the application in Mozilla Firefox, an error message pops up saying "TypeError: CSS2Properties doesn't have an indexed property setter for ' ...