4 ms·
I don't suppose this (or another forthcoming CSS property) would allow multiple `position: sticky` elements to stack after each other (instead of underneath)?
by stephen 4y ago
I don't suppose this (or another forthcoming CSS property) would allow multiple `position: sticky` elements to stack after each other (instead of underneath)?
That is one of our biggest layout PITAs, is the slippery slope of "sticky the table header" ... "and the filtering controls above it" ... "and the page header as well", and these are all across different levels of the DOM / component tree.
We currently solve it with React portals, which lets elements in the component tree "promote up" their localized content to the single/top-level-stickied div, so that within that div they can all flow after each other & not overlap.
- traviswt 4y agoThis sounds interesting to me. One of the struggles with sticky table headers is supporting automatic column widths. How does your portal trick support that? Currently I'm using a double rendering trick combined with resize observers.
- stephen 4y agoWe only use `position: sticky` for the first row of the table, but then stack everything else in a separate div, so something like: - parent div -- 1st child div, everything that is "stickied" to the top of the screen (really a tree of react components like the header + filters + table actions) -- 2nd child div, the table itself with a single position: sticky header row The portal trick/approach is that technically the table is rendered by some leaf-ish component in the 1st child's component tree, but once the leaf components knows "hey I'm the leaf", it uses a portal to push it's content to the 2nd top-level child, which gets it stuck below everything in the 1st child. It sounds kind of elaborate, but it lets everything in the top div get correctly dynamically sized without any hard-coded offset hacks.
- DaiPlusPlus 4y ago> is the slippery slope of "sticky the table header" ... "and the filtering controls above it" ... "and the page header as well", and these are all across different levels of the DOM / component tree. I've been using `thead > tr > * { position: sticky; }` just fine for years, with filtering controls within `<th>`. Don't forget to also specify `scroll-margin:` though, as that's how you get `position: sticky` to play-nice with other potentially-overlapping elements.
- systoll 4y agoThe spec implies that: header { position: sticky; anchor-name: --header; top: 0; } .controls { position: sticky; anchor-scroll: --header; anchor-name: --controls; top: anchor(--header bottom); } th { position: sticky; anchor-scroll: --controls; top: anchor(--controls bottom); } Should work, but 'stickiness' is not taken into account in the current build. Not sure why the anchor names are global instead of following the normal cascade. you could just have: .sticky { position: sticky; anchor-scroll: --sticky; top: anchor(--sticky bottom, 0); anchor-name: --sticky; } And .sticky children would stick to the bottom of their .sticky ancestors. As it is it still seems like most practical use cases will wind up needing JS to find and then name the position-anchor.