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

Is there a way to easily access the last element of an array in an Angular2 template without the need to iterate through the entire

I'm not trying to figure out how to access looping variables like i, first, last. Instead, my question is about how to retrieve and set variables as template variables. My current approach doesn't seem to be working... <div #lastElement="arr ...

Having trouble configuring AJAX and PHP to work together

Here's the situation I'm dealing with: I have HTML, JS, and PHP files. In the PHP file, there is an associative array containing default values to populate form elements in the HTML file. I'm trying to use AJAX to retrieve data from the PHP ...

Bootswatch alternative for Bootstrap CSS without utilizing Google Fonts

Currently, I am in the process of developing a webpage and utilizing Bootswatch for styling. However, there are times when I need to work offline and host locally. The issue I am facing is that Bootswatch cannot be used offline due to the fact that it util ...

The margin persists despite the usage of the * selector and !important declaration

I'm currently working on a website built upon this template: https://github.com/issaafalkattan/React-Landing-Page-Template My issue arises when trying to remove margins in multiple sections. For instance, I want to eliminate the 'orange' ar ...

using javascript to retrieve php variables

After creating a webpage, setting up Apache2 on an Ubuntu server to access it over the internet, and installing PHP5 and MySQL, I encountered issues with accessing database information on my page through a .php file. Despite having a file named test.php th ...

What is the best method to adjust the width of the <option> tag within the <select> tag using CSS?

<!DOCTYPE html> <html> <head> <title>Page Title</title> <!-- Latest compiled and minified CSS --> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="s ...

Ensure all vertically stacked boxes maintain the same height using Flexbox technology

My design includes a series of links styled as larger boxes, with varying content and height. Using flexbox to ensure equal heights on each row is straightforward. I'm utilizing the Bootstrap grid layout, but when the boxes stack vertically (one per r ...

Sending values from buttons to different Django templates/views

Initially, the user provides a CSV file. (Template File:) <form method="post" action="{% url 'rowcol' %}" enctype="multipart/form-data"> {% csrf_token %} <input type="file" name="file" accept=".csv"> <button type="sub ...

Monitor the incoming POST request

Is there a way to monitor incoming post requests in a form? I have the following form: <form method='post'> <input type='text' name'test' /> <input type='submit' name'submit' /> </for ...

The Jquery .remove() function will only take effect after the second click

I am currently working on implementing a notifications feature using bootstrap popover. The issue I am facing is that after a user clicks on a notification, it should be removed. However, for some reason, it requires two clicks to actually remove the notif ...

Is there a way to close the MatBottomSheet by going back in the browser?

I'm currently utilizing https://material.angular.io/components/bottom-sheet/overview. I've encountered an issue where, when the bottom sheet is open and a user clicks on the back button in their browser, they are redirected away from the page tha ...

Click to load additional data until the list has reached its full length

<ng-container *ngFor="let item of itemList | slice:0:3"> <mat-checkbox>{{item}}</mat-checkbox> </ng-container> <div> <button id="loadMore">Load More</button> </div> I wo ...

MySQL unable to access information entered into form

After creating a new log in / register template using CSS3 and HTML, I now have a more visually appealing form compared to the basic one I had before. To achieve this look, I referenced the following tutorial: http://www.script-tutorials.com/css 3-modal-po ...

What causes certain divs to protrude when the parent div has overflow:hidden property enabled?

Issue: I am facing difficulty aligning all elements within one div without any overflow issues. Even with the parent div set to overflow:hidden, some child divs are protruding out of the container. How can I resolve this problem? Example: http://jsfiddle. ...

When I include scroll-snap-type: y; in the body tag, the scroll-snapping feature does not function properly

Hey there! I've been trying to implement scroll-snapping on my project but unfortunately, I couldn't get it to work. I tested it out on both Chrome and Firefox, but no luck so far. Here's the code snippet I've been working with, would a ...

Effortlessly Transform HTML into Plain Text Using jQuery

If I wanted to create a feature on my website where users can input text into a text area and then convert it to HTML by clicking a button, how could I achieve that? I'm looking for functionality similar to what Wordpress offers, where users can enter ...

Encountered a problem while attempting to build with ng build --prod. No issues when using ng serve or excluding

My project was working smoothly with ng build --prod until I decided to update the TypeScript version from 2.72 to 2.92 in my package.json file. Now, after the update, an error message pops up: ERROR in Cannot read property 'Symbol(Symbol.iterator ...

The custom CSS styling is triggered only when the page is resized in Bootstrap

Currently, I am utilizing bootstrap alongside my custom CSS. The issue I am facing is that some of the styling from my custom CSS only takes effect after resizing my browser window to a smaller size. My custom CSS seems to be applied when the website adapt ...

Insert HTML content into an iframe with a callback function

We are receiving information from the backend server and need to transfer it to an iframe. In order to accurately set the height of the iframe to match the content, we must wait for the content to be loaded into the iframe. However, this process may not ha ...

Display a single submenu on mouseover using Javascript

Hello there, I have been working on creating a small menu using only Javascript, but I am facing an issue where the onmouseover event is displaying all submenus instead of just one. Below is the section of code that is supposed to change style.display to ...