Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Table] Add input for sticky headers #5885

Closed
andrewseguin opened this issue Jul 19, 2017 · 24 comments · Fixed by #11483
Closed

[Table] Add input for sticky headers #5885

andrewseguin opened this issue Jul 19, 2017 · 24 comments · Fixed by #11483
Assignees
Labels
feature This issue represents a new feature or feature request rather than a bug or bug fix ie11 This issue is specific to Internet Explorer 11 P3 An issue that is relevant to core functions, but does not impede progress. Important, but not urgent

Comments

@andrewseguin
Copy link
Contributor

Add an input to <cdk-table> that makes the table's header stick to the top of the scroll container.

Interim solution: Use styles position: sticky; top: 0 on the header element.

@andrewseguin andrewseguin added the feature This issue represents a new feature or feature request rather than a bug or bug fix label Jul 19, 2017
@andrewseguin andrewseguin self-assigned this Jul 19, 2017
@andrewseguin andrewseguin added the P3 An issue that is relevant to core functions, but does not impede progress. Important, but not urgent label Jul 19, 2017
@CDDelta CDDelta mentioned this issue Aug 7, 2017
@ghost
Copy link

ghost commented Aug 24, 2017

Using sticky position, interim solution has some bugs when you navigate through pages in a table, if you're not at the top of the table when you change the page, header disappear, any solution ?

@jscharett
Copy link

sticky position is not supported in IE. When will we see a cross-browser solution?

@ghost
Copy link

ghost commented Oct 2, 2017

Hello @andrewseguin, any solution to the problem related to the interim solution?

@andrewseguin
Copy link
Contributor Author

You can use position: sticky; top: 0 on the header row for now. Unfortunately this isn't a valid solution for IE but we have an implementation for this that we'd like to introduce soon.

@ghost
Copy link

ghost commented Oct 2, 2017

It's not really working on Firefox too, and in Chrome navigating or changing items per page cause bug.
I know this feature is not urgent but have you an idea of the delivery date of this?

@oliverschenk
Copy link

Support for position: sticky isn't great across browsers.

@andrewseguin
Copy link
Contributor Author

andrewseguin commented Oct 6, 2017

For now, here's a fun solution. Separate your table into two - the first won't show any rows, and the second won't display the header. Make the overflow scroll only on the rows.

If you set the same column IDs, you can re-use and existing column-specific class styles you might have applied (e.g. mat-column-name { min-width: 60px; }) - it will apply to both tables.

Proof-of-concept:
https://plnkr.co/edit/Gc3zVWr1GXqaJdK2S8mQ?p=preview

Just realized this looks great on a mac, which overlays scrollbars rather than pushes content to show them. With this, scrollbars will push the rows left while the header is static, causing mis-alignment.

@rhythmnewt
Copy link

@andrewseguin any suggestions on how to support horizontal + vertical scroll with sticky headers? So far I either get one or the other working properly. Here's the plunkr https://plnkr.co/edit/CXN6rNz3Kb9gDHKCceJ9?p=preview

@jscharett
Copy link

@andrewseguin While this works visually, I believe it has some accessibility issues. A screen reader is likely going to announce 2 tables, of which the second has hidden headers, so its not clear how a screen reader would handle it.

@tamvo94
Copy link

tamvo94 commented Oct 13, 2017

Hi all and @jscharett ,
I write a directive to auto set max height for multiple resolutions from ideal of @andrewseguin . Hope it can help everyone. Thanks.

import { Directive, AfterViewInit, OnDestroy } from "@angular/core";
/**
 * floating table header when user scroll table
 */
@Directive({ selector: "[autFloatingTableHeader]" })
export class FloatingTableHeaderDirective implements AfterViewInit, OnDestroy {
  private tableHasContentElement: HTMLElement;
  private targetElement: HTMLElement;

  ngAfterViewInit(): void {
    this.tableHasContentElement= document.getElementById("list-content") as HTMLElement;
    this.targetElement= document.getElementsByTagName("footer").item(0) as HTMLElement;
    this.resetTableHeight();
    window.addEventListener("resize", this.resetTableHeight.bind(this));
  }

  ngOnDestroy(): void {
    window.removeEventListener("resize");
  }

    private resetTableHeight(): void {
      setTimeout(() => {
        if(this.targetElement&& this.tableHasContentElement) {
          let distance = this.targetElement.getBoundingClientRect().top - this.tableHasContentElement.getBoundingClientRect().top;
          this.tableHasContentElement.style.maxHeight = `${Math.round(distance)}px`;
        }
      }, 0);
    };
}

@andrewseguin andrewseguin added the ie11 This issue is specific to Internet Explorer 11 label Oct 19, 2017
@Maximaximum
Copy link

Support for sticky headers would be a really great feature! Really waiting for it :)

@FJBDev
Copy link

FJBDev commented Dec 14, 2017

I would love this feature as well !!!

@simeyla
Copy link

simeyla commented Jan 6, 2018

I had to do position: sticky; top: -0.5px; background: white; for iOS retina (maybe Android too).
It was showing a single device pixel gap above the header which showed the data underneath as you scroll.

@pantonis
Copy link

@simeyla can you share code? Where did you add position: sticky; top: -0.5px; background: white;

@simeyla
Copy link

simeyla commented Jan 18, 2018

@pantonis I did this in my styles.css

You may need to look at the styles on the parent container if this doesn't work (eg. display or flex settings) - but this works quite nicely for me until there's an official update.

/* Table header row */
mat-header-row {
    /*https://github.com/angular/material2/issues/5885*/
    position: sticky;
    top: -.5px;
    background: white;
    z-index: 100;
}

@andrewseguin
Copy link
Contributor Author

@simeyla Can you share how you reproduced the issue? I'm seeing this show up on Chrome dev tools when I enter responsive mode, but I can't seem to get a real world example on my Android phone and mac laptop

@andrewseguin
Copy link
Contributor Author

Got it reproduced using this example https://stackblitz.com/edit/angular-s1t3nz?file=app/app.component.ts

Seeing it on mobile chrome with desktop view showed an issue: https://angular-s1t3nz.stackblitz.io/

@simeyla
Copy link

simeyla commented Jan 30, 2018

@andrewseguin What I posted was working quite well for me, so I was happy with this and wasn't really reporting an issue. But I'm only testing in latest Chrome at this time. If by issue you mean why did I have to use half a pixel it was on my iPad and showing through underneath the header as I scrolled.

@erickyi2006
Copy link

@simeyla , beautiful. works like a charm . thumbs up

my css now has these two elements

mat-table {
    height: calc(100vh - 30px);
    overflow: auto;
}

mat-header-row {
    position: sticky;
    top: -.5px;
    z-index: 100;
}

@kal93
Copy link

kal93 commented Apr 25, 2018

@andrewseguin any update on sticky for mat header row.

I tried the stickybits which works across browsers but doesn't seem to work for column headers.
Here's the Stackblitz .

@andrewseguin
Copy link
Contributor Author

@kal93 Currently working on it right now. We're going the route of using position: sticky. It leaves IE out of the race but it's much more efficient than us coming up with a custom solution that would be less efficient than letting the browser handle it.

Here's a stackblitz that I'm using to play with the idea: https://stackblitz.com/edit/angular-vttjfe?file=app%2Fhello.component.html

@kamalSaiDd
Copy link

@pantonis I did this in my styles.css

You may need to look at the styles on the parent container if this doesn't work (eg. display or flex settings) - but this works quite nicely for me until there's an official update.

/* Table header row */
mat-header-row {
    /*https://github.com/angular/material2/issues/5885*/
    position: sticky;
    top: -.5px;
    background: white;
    z-index: 100;
}

Thanks much.
It worked like gem

@ryansperzel1
Copy link

ryansperzel1 commented Apr 4, 2019

For now, here's a fun solution. Separate your table into two - the first won't show any rows, and the second won't display the header. Make the overflow scroll only on the rows.

@andrewseguin Creative, but filtering and sorting becomes an issue with this solution. This issue was opened in Jul 2017 - has there been any progress on scrolling just the body of the table? Looking for something exactly like the complex example here: https://v0.material-ui.com/#/components/table

@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Sep 10, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
feature This issue represents a new feature or feature request rather than a bug or bug fix ie11 This issue is specific to Internet Explorer 11 P3 An issue that is relevant to core functions, but does not impede progress. Important, but not urgent
Projects
None yet
Development

Successfully merging a pull request may close this issue.