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

The react table example doesn't make the <table> element large enough #585

Open
2 tasks done
KOVIKO opened this issue Sep 12, 2023 · 9 comments
Open
2 tasks done

Comments

@KOVIKO
Copy link

KOVIKO commented Sep 12, 2023

Describe the bug

In the "React Virtual Table Example", the translateY approach to row positioning allows rows to be positioned outside of the <table> element.

This causes issues with at least two things:

  1. A sticky header (<thead style="position:sticky;top:0">) cannot go beyond the bounds of the <table> element
  2. Borders on <tr> elements stop displaying when the <tr> element is outside of the bounds of the <table> element (in Chrome & Firefox)

It's also worth noting that intentionally changing the size of the table causes the rows to become huge, so that doesn't appear to be a solution.

Unless something can be done about the size of the <table> element, it may be best to suggest the padding-rows approach (such as the one used in the "React Table Virtualized Rows Example" in the TanStack Table docs).

Your minimal, reproducible example

https://tanstack.com/virtual/v3/docs/examples/react/table

Steps to reproduce

  1. Go to the "React Virtual Table Example" page in the documentation
  2. Change <thead> to a sticky header (<thead style="position:sticky;top:0">)
  3. Scroll down in the result until the header disappears

Expected behavior

<thead style="position:sticky;top:0"> should remain sticky through the entire table's scrolling.

How often does this bug happen?

Every time

Screenshots or Videos

No response

Platform

  • OS: Windows 11
  • Browser: Vivaldi 6.2.3105.47

tanstack-virtual version

3.0.0-beta.60

TypeScript version

No response

Additional context

No response

Terms & Code of Conduct

  • I agree to follow this project's Code of Conduct
  • I understand that if my bug cannot be reliable reproduced in a debuggable environment, it will probably not be fixed and this issue may even be closed.
@piecyk
Copy link
Collaborator

piecyk commented Sep 12, 2023

@KOVIKO you can't really position: sticky; on <thead> checkout https://css-tricks.com/position-sticky-and-table-headers/

also for tables better is to avoid the absolute positioning of virtualized items #476

@KOVIKO
Copy link
Author

KOVIKO commented Sep 12, 2023

That ticket was very useful for knowing the correct way to do the padding-rows approach! Thank you for that!

As far as sticky <thead> vs sticky <th> is concerned, they still have the same issue with being restricted to the actual <table> element's bounds.

If we change the <th> elements in the example to this, we still get the same issue I mentioned:

<th
  key={header.id}
  colSpan={header.colSpan}
  style={{
    width: header.getSize(),
    position: 'sticky',
    top: 0,
    zIndex: 2,
  }}
>

@piecyk
Copy link
Collaborator

piecyk commented Sep 12, 2023

hmm hard to say what is happening, but sticky should work, here virtualization is not adding anything special, like https://codesandbox.io/s/virtual-simple-table-cdqqpg

@KOVIKO
Copy link
Author

KOVIKO commented Sep 12, 2023

That example you just provided is using row(s) for padding to keep the <table> element the correct size. However, the example to which I'm referring (https://tanstack.com/virtual/v3/docs/examples/react/table) uses translateY to shift the rows' position in the <table> element, which has the unfortunate side effect of pushing many rows outside of the <table> element's bounds.

It's in the style attribute of the <tr> elements in the <tbody> element:

<tr key={row.id} 
style={{
  height: `${virtualRow.size}px`,
  transform: `translateY(${virtualRow.start - index * virtualRow.size}px)`,
}}>

To be clear, this isn't necessarily a bug of @tanstack/virtual, but rather a bug of the example used in the documentation.

@piecyk
Copy link
Collaborator

piecyk commented Sep 12, 2023

Yep, i agree that table examples are misleading, we should not use the absolution positions here.

@vojvodics
Copy link

@KOVIKO Thanks - your solution worked for me! I'd suggest doing this slightly differently:

<tr key={row.id} 
style={{
  height: `${virtualRow.size}px`,
  transform: `translateY(${virtualRows[0]?.start ?? 0}px)`,
}}>

If the table rows are all fixed height - the calculation for all rows will be the same as the first virtual item.
If the table row height is dynamic, the calculation won't work, but setting all rows to transform to the start of the first virtual item works.

@tboley-vt
Copy link

This approach helped me when using scrollMargin:

<tbody
    css={{
        "&::after": {
            display: "block",
            content: "''",
            // this ensures the table takes up as much size as the total elements by adding padding to the end
            height: `${ virtualizer.getTotalSize() - virtualizer.scrollRect.height}px`,
        },
    }}
>
    ....
</tbody>

@jmalovera10
Copy link

hmm hard to say what is happening, but sticky should work, here virtualization is not adding anything special, like https://codesandbox.io/s/virtual-simple-table-cdqqpg

This worked out for me! I added the before and after statements around the virtual items map and set the overflowAnchor to none.

@tabarra
Copy link

tabarra commented Mar 6, 2024

Friendly bump on this issue.
I've wasted a few days trying to get my tables to work only to find out this was the issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants