Tips for properly formatting a fixed table header

I'm currently facing an issue with the sticky header style in my data table. I have created a simple Angular component along with a specific directive:

sticky.directive.ts

@Directive({
    selector: '[sticky]'
})
export class StickyDirective {

    constructor(private _element: ElementRef, private _window: WindowRef) {
        console.log('debug')
    }

    @HostListener('window:scroll', ['$event'])
    handleScrollEvent(e) {
        if (this._window.nativeWindow.pageYOffset > 100) {
            this._element.nativeElement.classList.add('stick');
        } else {
            this._element.nativeElement.classList.remove('stick');
        }
    }
}

The main purpose of this directive is to apply a stick class when the user scrolls below the header. This ensures that the table header remains visible even while scrolling through a long table. The CSS for the stick class is as follows:

.stick {
    position: fixed;
    top: 55px;
} 

In my some.component.html, I utilize the directive on the thead element like so:

<table class=" table table-bordered ">
 <thead sticky>
   <tr>
    <th width="40%">Name
    </th>
    <th width="10%">Priority
    </th>
    <th width="25%">Date created
    </th>
    <th width="25%">Date modified
    </th>   </tr>   </thead>   <tbody>   <tr *ngFor="let r of entitiesFiltered">
    <td>
      <div class="table-cell-flex">
        <div class="cell-content">
          {{r.name}}
        </div>
      </div>
    </td>
    <td>
      <div class="table-cell-flex">
        <div class="cell-content">
          {{r.priority}}
        </div>
      </div>
    </td>
...

While the functionality works as expected, with the header staying in place during scroll, there is an issue with the header and columns width changing. Here is how it looks:

https://i.stack.imgur.com/IPYNA.png


Question:

I am seeking advice on how to style my table so that the fixed header does not alter the form/shape of the table. Is this achievable?

Answer №1

To dynamically set the width of columns using JavaScript and then fixing them to the header with a fixed or absolute position, you can also achieve it using HTML and the following code snippet:

<div class="table-wrapper content">
  <!-- wrapper for the table -->
  <table>
    <!-- column headers -->
    <thead>
      <tr>
        <th>Header 1</th>
        <th>Header 2</th>
        <th>Header 3</th>
      </tr>
    </thead>
  </table>
</div>
<div class="table-body-wrapper" style="position: relative; overflow: visible;">
  <!-- element containing custom scrollbar -->
  <table>
    <!-- body content -->
    <tbody>
      <!-- data inserted dynamically by JavaScript function -->
      <tr>
        <td>Row 1, Column 1</td>
        <td>Row 1, Column 2</td>
        <td>Row 1, Column 3</td>
      </tr>
      <tr>
        <td>Row 2, Column 1</td>
        <td>Row 2, Column 2</td>
        <td>Row 2, Column 3</td>
      </tr>
      <tr>
        <td>Row 3, Column 1</td>
        <td>Row 3, Column 2</td>
        <td>Row 3, Column 3</td>
      </tr>
      <tr>
        <td>Row 4, Column 1</td>
        <td>Row 4, Column 2</td>
        <td>Row 4, Column 3</td>
      </tr>
      <tr>
        <td>Row 5, Column 1</td>
        <td>Row 5, Column 2</td>
        <td>Row 5, Column 3</td>
      </tr>
    </tbody>
  </table>
</div>

Answer №2

I encountered a similar issue and devised a workaround to tackle it. To rectify the problem, I came up with a simple hack where I defined the fixed width of columns in the sticky header and replicated the sticky header below the table to maintain the width of column names' content.

My resolution leverages Bootstrap 4 and Angular 6.


example.component.html:

<table class="table">
  <thead>
  <tr>
    <th #tableColumn1>Column 1</th>
    <th #tableColumn2>Column 2</th>
    <th #tableColumn3>Column 3</th>
  </tr>
  </thead>
  <tbody>
  <tr *ngFor="let message of messages">
    <td>{{ message.title }}</td>
    <td>{{ message.author }}</td>
    <td>{{ message.created_at }}</td>
  </tr>
  </tbody>
</table>

<table class="table" [class.d-none]="!showFixedTableHeader">
  <thead>
  <tr [class.sticky]="showFixedTableHeader">
    <th [width]="tableColumn1.offsetWidth">Column 1</th>
    <th [width]="tableColumn2.offsetWidth">Column 2</th>
    <th [width]="tableColumn3.offsetWidth">Column 3</th>
  </tr>
  </thead>
</table>


example.component.ts

import {Component, HostListener} from '@angular/core';

@Component({
  templateUrl: './example.component.html',
  styleUrls: ['./example.component.css']
})
export class ExampleComponent {

  showFixedTableHeader: boolean = false;

  @HostListener('window:scroll')
  onScroll() {
    const pageTopOffset = window.pageYOffset;

    if (pageTopOffset > 285) {
      this.showFixedTableHeader = true;
    } else {
      this.showFixedTableHeader = false;
    }
  }

  @HostListener('window:resize')
  onResize() {
    // Do nothing.
    // It will automatically trigger to update the bound properties in template.
  }
}


example.component.css

tr.sticky {
  top: 60px;
  position: fixed;
  z-index: 99;
}

Answer №3

It seems that removing the angular directive may be a better approach as it's interfering with the existing styles, particularly when applying the "stick" class.

An alternative solution could involve adjusting the table head's position and increasing its z-index to prevent the body from being visible during scrolling.

Check out this CodePen example for reference:

thead{
      position:fixed;
      z-index:2;
      ...
     }

tbody{
      position:absolute;
      z-index:1;
      ...
     }

CodePen Example

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

Getting an Angular TypeError after upgrading to version 9? It seems that the property 'selectors' cannot be read from null

After upgrading my Angular app from v7 to v8 and then v8 to v9, I encountered an issue. My app works perfectly locally when I run ng serve, but when I build for production using ng build --prod and deploy the app, I get an error in the application's c ...

The text element does not line up with the icons

As I'm working on creating my first account page header, I've run into an issue with some of the icons not aligning perfectly with the text. While advanced developers may find this task simple, as a beginner, I could really use some advice on how ...

Having trouble with submitting an HTML form using JavaScript and PHP

My webpage has an HTML form that sends data to a PHP file for processing. One issue I'm facing is with a dynamically generated combo box that works fine when the page loads, but the selected value is not being passed when the form is submitted. The J ...

Is it possible to keep content visible in Bootstrap tab by adding CSS?

Having an issue with the "formbox" class that is causing unexpected behavior when applied to a form. When removed, everything works as expected. I've tried narrowing down the issue by removing each CSS rule individually and testing it out but haven&ap ...

Images Centerfold Team

I am facing a challenge in creating a group of images for an album. There seems to be a significant gap on the right side, which cannot be resolved without using padding. However, adding padding only works for my current PC resolution and creates a larger ...

Display identical elements from an array and shuffle them every 300 seconds

I created this code snippet that currently displays 5 random rows of data from an array each time it is executed. My goal is to modify the code so that it selects and displays the same 5 random values from the array for a duration of 5 minutes before rand ...

Using TypeScript, pass an image as a prop in a Styled Component

I am facing an issue with the code below that is supposed to display the "NoBillsLaptopPNG.src" image on the screen, but for some reason, the image is not showing up. The images are being imported correctly, so I'm unsure why the image is not appeari ...

"Utilizing the Ionic side menu to activate a function in the view.ts file

In my app, there is a menu located in the main app.component.html <ion-app> <ion-split-pane contentId="main-content"> <ion-menu contentId="main-content" type="overlay"> <ion-content> ...

How to target the following sibling element (not a child) with CSS

I am working with the following HTML structure: <div class="col-sm-12"> <input id="my_id"> <div class="col-sm-1 col-3-box" style="position:absolute; margin-left:340px;"> </div> </div> How can I target and change ...

Is it possible to change the style of the current page in PHP using the ?page href method?

Currently, I am facing an issue with styling in my code. Specifically, I want to style the page numbers that are currently open or active. For example, if a page is open, I would like its corresponding number to be displayed in a different color or style. ...

Tips for properly aligning an image within an owl carousel

Currently, I am attempting to center a small image within the owl carousel. While I have managed to center it when it's active and in the center, I'm encountering issues when the item no longer carries the "center" class. You can access Owlcarou ...

Sharing assets across different Angular applications is a powerful way to improve code

I am currently developing a series of small applications that will utilize common modules and shared assets. For guidance on how to structure the projects, refer to this answer: The organization of my project folders is as follows: -root --projects ---ap ...

Optimal Strategies for Handling CORS in Angular 2+ and Node/Express Servers

Currently, I am in the process of implementing user authentication with Express/Node and testing cookies from an Angular frontend. Upon logging in, the cookies are properly displayed in the network tab but not in the application tab. I understand that usi ...

What impact does changing the Device Language have on a heading?

At the top of an html page, I have the word "Color" in a heading. If a user's device is set to British English, I would like the text to automatically switch to "Colour". What is the best way to accomplish this with minimal Javascript? ...

Make sure the static variable is set up prior to injecting the provider

In our Angular6 application, we utilize a globalcontextServiceFactory to initialize the application before rendering views. This process involves subscribing to get configuration from a back-end endpoint and then using forkJoin to retrieve environment app ...

A fixed header list using CSS with a single scroll bar

I am looking to create a scrollable list with a fixed header, where the scroll bar extends the full height of the parent but only scrolls through the nav items (keeping the logo in place). My current setup involves: <div className="home-page-nav"> ...

Issues arise in TypeScript 5.1.3 with lodash due to type errors involving excessively deep type instantiation, which may potentially be infinite

Recently, I made updates to my Ionic/Angular project and now it is running Angular version 16.1.3 along with TypeScript version 5.1.3. In addition to this, my project also includes the following dependencies: "lodash-es": "^4.17.21", ...

Discover the power of utilizing JavaScript to sort through table rows by filtering them based on the selections of multiple checkbox

How can I create interdependent logic for checkbox sections in a form to filter based on all selections? I am looking for help with my code snippet that showcases checkboxes controlling the visibility of table rows: $(document).ready(function() { $(" ...

Ways to monitor a variable for changes and automatically update the value in related components

I feel like I may not be following best practices, so I'm hoping for some guidance. Within a provider, there is a variable that I have defined. @Injectable() export class SharedService { public mynumberservice:any=0; In both the MainComponent an ...

Using Jquery to store input values from within <td> elements in an array

I'm trying to capture user input from a dynamically changing table with 2 columns. How can I retrieve the data from each column separately? The size of the table is adjusted by a slider that controls the number of rows. Below is the structure of my ta ...