Skip to content

USWDS - Table component: add ability to make headers sticky as user scrolls #5074

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

Closed
wants to merge 4 commits into from

Conversation

etanb
Copy link
Contributor

@etanb etanb commented Dec 20, 2022

Summary

For very long tables, it's difficult to remember what the header content was. This change allows a developer to have the the table header content follow a user on scroll.

Breaking change

This is not a breaking change.

Related issue

N/A

Preview link

FixedHeaderTable.mp4

Solution

  1. Added an optional class called usa-table--sticky-header that invokes the following CSS rule:
thead {
    th {
      position: sticky;
      top: 0;
    }
  }

(NOTE: you can not position: sticky; a <thead> element so the preferred solution is to just target the <th> data.)

Testing and review

  1. There's a Storybook story called Sticky Header where you can review the results

@etanb etanb marked this pull request as ready for review December 20, 2022 20:11
@amyleadem
Copy link
Contributor

amyleadem commented Jan 27, 2023

@etanb Thank you for this submission! I like the possibilities this variant offers.

I've added some notes on a few items I discovered. Would you be able to take a look and resolve these items?

  1. I noticed that there is a small amount of content that is visible between the sticky header and the browser edge. I believe it is related to the border added to the th element. The sticky positioning should account for this border. One possible avenue to pursue is using border-collapse: separate on the table element.

    image
  2. I added usa-table--sticky-header to the other table variants and achieved mixed results. For example, when added to the usa-table--borderless variant, the header had a transparent background:

    image Can you fix how `usa-table--sticky-header` interacts with the other table variants?
  3. How might this interact with other sticky components?

  4. It might improve the Storybook experience to add sticky as a boolean control for each table variant, like we do with scrollable (Reference). What do you think?

Please let me know if you have any questions or comments!

@amyleadem amyleadem added the Needs: Discussion We need to discuss an approach to this issue label Jan 27, 2023
@amyleadem
Copy link
Contributor

@etanb I have added the Needs: Discussion label to this PR so that the team can discuss any risks or accessibility implications that might pop up with a feature like this. Before doing more work, let's pause and make sure this is a good fit for the system. We'll cycle back when we have an answer.

@mejiaj
Copy link
Contributor

mejiaj commented Apr 7, 2023

Thanks for the contribution @etanb! No issues found on mobile and browser support looks pretty good.

image

https://caniuse.com/css-sticky

Are you able to address Amy's comments? If you're unable to that's okay. We can create another issue for the comments and create a separate feature branch for all this work. What do you think @amyleadem?

@mejiaj mejiaj removed the Needs: Discussion We need to discuss an approach to this issue label Apr 14, 2023
@etanb
Copy link
Contributor Author

etanb commented Apr 17, 2023

Hi all, I'm just rebuilding my local now and will have an update soon! Will try and incorporate all of @amyleadem requests.

@etanb
Copy link
Contributor Author

etanb commented Apr 18, 2023

My latest commit #630eadc6913a3efa5a08e90049074add4a8f11a6 adds usage for all the other USWDS stylings except for stackable and scrollable.


Two remaining issues / items for y'all/us to decide on:

  1. stickyheader doesn't work on scrollable because overflow-y: hidden; is applied to the <div> container. Is that something we want to remedy or should scrollable and stickyheader be mutually exclusive?

  2. stickeyheader works great in all instances EXCEPT when the header is colspan="2" or greater. Here are examples of what it looks like:

Screenshot 2023-04-17 at 7 07 02 PM

You can see that the row that are doubled up get squashed together since all <th> tags have top: -1px;. Solutions to this are:
a) wrap the entire <thead> in some sort of <div> so that we can sticky the entire element. not sure what ramifications this has to the <table>.
b) set a fixed height for the <th> elements so that we can know how much to offset each row by.
c) use Javascript to fix the header to the top of the <table>.
d) make a note that stickeyheader and non-single line headers are incompatible.

Let me know what y'all think! cc @amyleadem @mejiaj

Copy link
Contributor

@mejiaj mejiaj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@etanb thanks for updating!

  1. I think it's worth trying to find workarounds. Especially ones with minimal impact on the markup.
  2. Option D for colspan greater than 1 seems good to me, but I'd like the team to weigh in.

@etanb
Copy link
Contributor Author

etanb commented Apr 21, 2023

Unfortunately, after digging deeper, having a horizontal scroll + a sticky header for a table has been a known issue for a while (2017!) and there's still an open issue on W3C CSS repo: w3c/csswg-drafts#865

The only workaround I see is removing overflow-x: hidden; from here:

and removing overflow-y: hidden; from here:

Example of it working:

scrollAndSticky.mp4

However, that's a lot of modifications to get this feature working. Let me know what y'all think and what is worthwhile!

@DorianCoding
Copy link

DorianCoding commented Apr 24, 2023

Unfortunately, after digging deeper, having a horizontal scroll + a sticky header for a table has been a known issue for a while (2017!) and there's still an open issue on W3C CSS repo: w3c/csswg-drafts#865

The only workaround I see is removing overflow-x: hidden; from here:

and removing overflow-y: hidden; from here:

Example of it working:

scrollAndSticky.mp4

However, that's a lot of modifications to get this feature working. Let me know what y'all think and what is worthwhile!

Yes it is a really old issue and I hope one day it could be fixed.

We need a feature that allows overflow on height or width. But both overflows works and no one too. If we remove hidden overflow the table expands the viewport. It would be grate that setting an overflow hidden does not remove the sticky attribute so text outside the table stays on the view. It is especially good for mobile when the user can scroll inside the table without scrolling the whole page.

@etanb
Copy link
Contributor Author

etanb commented Apr 26, 2023

Ok, not sure what next steps are here are @DorianCoding @amyleadem @mejiaj . My gut instinct here is to just make stickyHeader and scrollable mutually exclusive.

@DorianCoding
Copy link

Ok, not sure what next steps are here are @DorianCoding @amyleadem @mejiaj . My gut instinct here is to just make stickyHeader and scrollable mutually exclusive.

It already works when setting both width and height or none using overflow visible.
But when setting overflow auto or hidden it does not work anymore so it is impossible to set the width but not the height for instance.

@etanb
Copy link
Contributor Author

etanb commented May 24, 2023

If we have a fixed table height, you can have BOTH side scrolling + sticky header.

@amyleadem
Copy link
Contributor

amyleadem commented May 30, 2023

@etanb
Apologies for the delayed response on this review and thank you for all your work on this. It's getting closer! I’ve added a few comments below with findings and suggestions for possible improvements.

I know some time has passed, so please let us know if your availability has changed and you need any help finishing this out.

I have tested the following items:

  • Works as expected with default variant
  • Works as expected on headers with multiple rows
    • After doing a bit of digging, it looks like we actually can add position:sticky to the thead element instead of th. Support for sticky positioning on thead is now available in most browsers (Reference: caniuse - position sticky). I tested applying sticky positioning to the thead elementin USWDS in this PR, and results can be seen in this preview link. Everything appears to be working as expected.
    • Benefits of applying sticky to thead:
      • We can have sticky headers with multiple rows!
    • Costs of applying sticky to thead:
      • In Chrome, the background content is visible behind where the cell borders should be when using this technique. One possible path to resolve this is to use border-collapse: separate, but this would create a need to rework how our borders are applied to table cells in order to maintain current appearance. There are some examples of a possible alternative border pattern in this test PR. The style rules would need refinement, but I hope it conveys the intention.
  • Works as expected with borderless variant
    • The table header background color changes when stickyheader is turned on. By default the background is set to transparent, but when stickyheader is turned on, it sets background color to $theme-table-header-background-color.
      One solution to this could be to create a setting for $theme-table-background-color that can be used to both set table background color and define the background color of the borderless table header.
  • Works as expected with striped variant
  • Works as expected with sortable variant
    • Sticky headers do not currently work on the sortable variant because .usa-table th[data-sortable] overrides sticky positioning with position: relative. This should be resolved if we move sticky positioning to the thead element (See note above).
    • Additionally, it would be helpful to be able to easily test sticky headers on this variant as well. Here are a couple of items that would help with that:
      • It would be great if we had the {{stickyheader ? 'usa-table--sticky-header' : ''}} check that you added in usa-table.twig in usa-table--sortable.twig
      • Additionally, could you add a JSON file for sortable tables with entries for stickyheader and scrollable?
      • Right now usa-table--sortable.twig has the usa-table-container--scrollable wrapper hard-coded in. Could you make this optional like we do in usa-table.twig
  • Works as expected on scrollable and stacked variants
    • Note: I confirmed that it is a known problem that sticky positioning does not work with overflow:hidden ancestors. I could not find a semantic, non-JS workaround for this. I think it is fine if scrollable tables and sticky header are mutually exclusive for now - we can investigate options to repair this in a follow-up issue.
  • Test on Chrome, Firefox, Safari, iOS
  • Test at varying breakpoints

Other considerations

  • Improve Storybook controls: It would be helpful if there were controls in Storybook that allowed us to toggle stickyheader and multiple header rows for each table variant.
  • Customizable top offset: It would be good if there was a theme setting that allowed users to customize the top offset in case their site has additional elements that stick to the top (like a header). Could you add a $theme-table-sticky-top-offset setting?

cc: @mejiaj @mahoneycm

@etanb
Copy link
Contributor Author

etanb commented May 31, 2023

Thanks for the extensive checklist @amyleadem. We're currently implementing on our variation of this feature on our site, and as said previously, using a fixed height (we do max-height: 80vh) will allow sidescrolling + sticky header. Is this worth considering for y'all?

@amyleadem
Copy link
Contributor

amyleadem commented Jun 1, 2023

Thanks for the extensive checklist @amyleadem. We're currently implementing on our variation of this feature on our site, and as said previously, using a fixed height (we do max-height: 80vh) will allow sidescrolling + sticky header. Is this worth considering for y'all?

@etanb Thanks for the suggestion. I will take a look and discuss with the team.

@amyleadem amyleadem added the Needs: Discussion We need to discuss an approach to this issue label Jun 30, 2023
Copy link
Contributor

@amyleadem amyleadem left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @etanb,
Wanted to check in to see if you will be able to get to the items in the checklist in this comment.

I know a part of the conversation was left hanging on my part. Thanks for your patience with that. For now, lets move forward without including sticky tables on scrollable headers. We can always address that concern as a follow-on enhancement.

Just let us know if your availability has changed and you need us to finish this out.

@amyleadem amyleadem added Needs: Author Response 🔴 We're waiting for more information from a participant and removed Needs: Discussion We need to discuss an approach to this issue labels Jul 19, 2023
@amyleadem
Copy link
Contributor

amyleadem commented Aug 2, 2023

Hello @etanb,
I wanted to let you know that I am going to pick up this work and will finish it over in PR #5420. To reduce confusion about where the current work lives, I am closing out this PR. Thank you for sharing this work and please reach out if you have any questions!

@amyleadem amyleadem closed this Aug 2, 2023
@etanb
Copy link
Contributor Author

etanb commented Aug 2, 2023

That's exciting news! Thanks for making this happen @amyleadem , let me know if I can be useful.

@amyleadem
Copy link
Contributor

Absolutely! Thanks for your patience on this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Needs: Author Response 🔴 We're waiting for more information from a participant Package: Table Type: Feature Request New functionality
Projects
None yet
Development

Successfully merging this pull request may close these issues.

USWDS - Feature: Ability to have <Table/> headers sticky to the top
4 participants