Fixed headers remain in place as you scroll horizontally on a single table

Within my system, I have organized two tables: table one and table 2 are stacked on top of each other. I've managed to freeze the column headers so that they are displayed vertically, remaining static as users scroll horizontally. To achieve this effect, I used a sticky attribute in the th element within the CSS code. Both tables are enclosed under one div with the assigned class "scrollHorizontal," which should allow both tables to move together when users scroll horizontally. However, an issue arises where only the column from the first table sticks when scrolling horizontally, while the second table remains unaffected. I am seeking insight into the underlying reason for this behavior.

Screenshot: https://i.stack.imgur.com/xk8dL.png

th {
  padding: 7px;
  position: sticky;
  left: 0px;
  min-width: 250px;
  width: 250px;
  background-color: #f5f7f7;
}

td {
  padding: 7px;
  min-width: 300px;
  width: 300px;
  /* max-width: 300px; */
}

/* Additional CSS classes... */

.scrollHorizontal {
  overflow-x: scroll;
}
<!-- HTML layout containing the tables -->

Answer №1

Check out my proposed solution.

body {
  font: 16px Calibri;
}

.container {
  position: relative;
  overflow: hidden;
  margin-left: 0;
  width: 720px;
}

table {
  border-collapse: separate;
  border-top: 3px solid grey;
}

td,
th {
  margin: 0;
  border: 3px solid grey;
  border-top-width: 0px;
  white-space: nowrap;
}

div {
  width: 600px;
  overflow-x: scroll;
  margin-left: 5em;
  overflow-y: visible;
  padding-bottom: 1px;
}

.headcol {
  position: absolute;
  width: 5em;
  left: 0;
  top: auto;
  border-right: 0px none black;
  border-top-width: 3px;
  /*only relevant for first row*/
  margin-top: -3px;
  /*compensate for top border*/
}

.headcol:before {
  content: 'Row ';
}

.long {
  background: yellow;
  letter-spacing: 1em;
}
<div class="container">
  <div>
    <table>
      <tr>
        <th class="headcol">1</th>
        <td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td>
        <td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td>
      </tr>
      <tr>
        <th class="headcol">2</th>
        <td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td>
        <td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td>
      </tr>
      <tr>
        <th class="headcol">3</th>
        <td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td>
        <td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td>
      </tr>
      <tr>
        <th class="headcol">4</th>
        <td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td>
        <td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td>
      </tr>
      <tr>
        <th class="headcol">5</th>
        <td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td>
        <td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td>
      </tr>
      <tr>
        <th class="headcol">6</th>
        <td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td>
        <td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td>
      </tr>
    </table>
  </div>
  <div>
    <table>
      <tr>
        <th class="headcol">1</th>
        <td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td>
        <td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td>
      </tr>
      <tr>
        <th class="headcol">2</th>
        <td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td>
        <td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td>
      </tr>
      <tr>
        <th class="headcol">3</th>
        <td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td>
        <td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td>
      </tr>
      <tr>
        <th class="headcol">4</th>
        <td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td>
        <td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td>
      </tr>
      <tr>
        <th class="headcol">5</th>
        <td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td>
        <td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td>
      </tr>
      <tr>
        <th class="headcol">6</th>
        <td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td>
        <td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td>
      </tr>
    </table>
  </div>
</div>

Example two: Scrolling once scrolls through two tables simultaneously.

body {
  font: 16px Calibri;
}

.container {
  position: relative;
  overflow: hidden;
  margin-left: 0;
  width: 720px;
}

table {
  border-collapse: separate;
  border-top: 3px solid grey;
}

td,
th {
  margin: 0;
  border: 3px solid grey;
  border-top-width: 0px;
  white-space: nowrap;
}

div {
  width: 600px;
  overflow-x: scroll;
  margin-left: 5em;
  overflow-y: visible;
  padding-bottom: 1px;
}

.headcol {
  position: absolute;
  width: 5em;
  left: 0;
  top: auto;
  border-right: 0px none black;
  border-top-width: 3px;
  /*only relevant for first row*/
  margin-top: -3px;
  /*compensate for top border*/
}

.headcol:before {
  content: 'Row ';
}

.long {
  background: yellow;
  letter-spacing: 1em;
}
<div class="container">
  <div>
    <table>
      <tr>
        <th class="headcol">1</th>
        <td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td>
        <td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td>
      </tr>
      <tr>
        <th class="headcol">2</th>
        <td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td>
        <td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td>
      </tr>
      <tr>
        <th class="headcol">3</th>
        <td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td>
        <td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td>
      </tr>
      <tr>
        <th class="headcol">4</th>
        <td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td>
        <td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td>
      </tr>
      <tr>
        <th class="headcol">5</th>
        <td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td>
        <td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td>
      </tr>
      <tr>
        <th class="headcol">6</th>
        <td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td>
        <td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td>
      </tr>
    </table>

    <table>
      <tr>
        <th class="headcol">1</th>
        <td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td>
        <td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td>
      </tr>
      <tr>
        <th class="headcol">2</th>
        <td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td>
        <td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td>
      </tr>
      <tr>
        <th class="headcol">3</th>
        <td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td>
        <td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td>
      </tr>
      <tr>
        <th class="headcol">4</th>
        <td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td>
        <td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td>
      </tr>
      <tr>
        <th class="headcol">5</th>
        <td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td>
        <td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td>
      </tr>
      <tr>
        <th class="headcol">6</th>
        <td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td>
        <td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td>
      </tr>
    </table>
  </div>
</div>

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

A window that pops up in Angular 2

I'm in the process of developing a popup window that requests login details when a button is clicked. Here's what my app.component looks like: import { Component } from '@angular/core'; @Component({ selector: 'my-app', ...

Updating the value of a key in an object is not functioning as expected

There is a single object defined as requestObject: any = { "type": 'type1', "start": 0, "size": 10, "keywords": ['abcd','efgh'], filters: [], } Next, attempting to change the value for keyword, I updat ...

div layout; sidebar movements occur after appending div to the header

Having trouble mastering layouts, I am attempting to create a full-width header that includes a left sidebar and a right sidebar. The body is split into 5 sections: full width, left and right sidebars, center content with 3 columns, and the footer mirrorin ...

Maintaining the order of subscribers during asynchronous operations can be achieved by implementing proper synchronization

In my Angular setup, there is a component that tracks changes in its route parameters. Whenever the params change, it extracts the ID and triggers a function to fetch the corresponding record using a promise. Once the promise resolves, the component update ...

Options for authentication with Spring Boot and Angular version 2 or 4

As I prepare to integrate user authentication in my app, I realize this is my first time working on an Angular + Spring project. I am interested in learning about the various options available for authentication. While I don't need a step-by-step guid ...

How was the background design accomplished on this particular website using CSS?

I've noticed that the background on this website scrolls and changes at various points. It transitions from blue to green with clouds moving. I'm curious about what term is used to describe this type of background effect (I don't think it&ap ...

What are the steps to resolve routing issues within an Angular component integrated into an ASP.NET Core web application?

When it comes to routing in Angular, I have been following the Angular tutorial from documentation. My example application integrates Angular components with an ASP.NET Core 2.2 web app, and these components are displayed within .cshtml views. I use Angul ...

Include the array in the 'content' property of the CSS using Jquery

I need help formatting data in CSS. The code I have is as follows: if (ext){ switch (ext.toLowerCase()) { case 'doc': pos = 'doc'; break; case 'bmp': pos = 'bmp'; break; ...

Transferring information to an Ionic 5 custom element label

In my ionic 5 app, I have a side menu and tabs. Each page can have different contents for the side menu and the tabs. Instead of duplicating the ion-menu in each page, I created a header component (and one for the tabs) as follows: HEADER COMPONENT: <i ...

My navigation bar is giving me a bit of trouble, as there are two separate issues that seem to be interconnected

Looking for some help with my navigation bar layout. You can also check out the code on fiddle http://jsfiddle.net/SgtRx/ (should have done this earlier, sorry). I'm a beginner when it comes to coding, so please bear with me if I make any mistakes. ...

What are the steps involved in changing a dropdown menu?

My current bootstrap dropdown list has been causing some issues, specifically with the 'Log out' link not working properly. The 'Logout' button seems to be functioning correctly, but for some reason the other one is not. Can someone ple ...

Every time a new message is sent or received, I am automatically brought back to the top of the screen on the

I'm currently working on integrating a chat feature into my Angular Firestore and Firebase app. Everything seems to be functioning well, except for one issue - whenever a new message is sent or received, the screen automatically scrolls up and gets st ...

how to adjust the width of table columns dynamically using ng-repeat and AngularJS

Working on a user interface that contains a table where the column widths adjust according to percentage data. I'm using ng-repeat to populate the table, but need help setting unique widths for each piece of data received. Here's some of my Angul ...

Seeking a more deliberate option instead of using $(window).load, one that is not as quick as $(document)

Currently, my goal is to utilize JavaScript to conceal my preloader once the DOM and key elements have been loaded. The issue lies in the fact that various iframes on my page can significantly slow down this process. It seems that using jQuery's $(do ...

JavaScript / html Error: function body missing closing curly brace

I encountered an error that I'm struggling to resolve: "SyntaxError: missing } after function body". Despite not having a function named 'body', I have attempted changing every instance of 'body' in my script. However, ...

Creating dynamic links with Jquery

Here is a piece of Jquery code that needs to be adjusted: var previewImage = $('#prev'); var newLink = $('<a/>').attr('href', name); previewImage.append(newLink); The current HTML output is <img src=" " id="prev"/& ...

Book Roulette: Your Next Random Read

I created a code for a random quote generator and now I want to create something similar, but with images this time. I am looking to add a feature on my page where it can recommend a book by displaying its cover image when a button is clicked. For the pre ...

Tips on utilizing commas as text input within an HTML input array

Is there a way to pass a comma in an input field to the server using input arrays? The server currently receives comma-separated input values from an array of inputs, which causes it to consider any commas within the input as separators. For example: HTM ...

Troubleshooting a pair of distinct software programs: Angular and a web API

I am currently working on two separate applications, one developed in Angular and the other in web API. There is a function in my Angular application that calls a method in .NET Core. I would like to know if it is possible to debug the Angular function and ...

What is the best way to activate multiple variable states (same state) in Angular animations?

I have already checked out the explanation for angular2-height-animation-same-state-transition, but it did not provide the help I needed. I am currently working on creating a carousel similar to the ones you see on eBay or Amazon sites, specifically in th ...