Describe in documentation how to implement scrollable areas properly #1804
Reference in New Issue
Block a user
No description provided.
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Hi,
I presume all the documentation for this project is here: https://www.yogalayout.dev/docs/about-yoga
It does not tell how to make a scrollable area. Could you take a little bit of time to explain how it's done?
I'm using poga bindings to apply yoga in my project. It's providing C bindings directly, eg.
YGNodeStyleSetOverflow
would allow me to set the scroll on.So once I've set the overflow: scroll, how do I actually make it scroll? Eg. Set the scroll offsets and get the scroll limits so I won't let the user scroll over the content.
Thank you for writing yoga. It's been a nice library to use overall.
(I'm also interested about making very large scrollable areas that need to dynamically remove/add content based on where user is scrolling. But the basic recipe would be nice and I could then apply it on the infinite scrolling -problem)
I realised it was simpler than I expected. I was not examining the whole palette of options I actually have.
The following recipe assumes you don't have paddings in the scroll area element:
When I'm doing it properly, I have less need for infinite scrolling element.
What do you mean scroll-able areas? If your using OpenGL, Vulkan, Direct3D use viewports and if your using Skia, Direct2D or Cairo then use clipping. A scroll-able area is just a larger area clipped by a smaller area and you match the width of your content to the clipping or viewport container. Then the top of your scrolling content is 0.0 and the bottom of your content is 1.0. The blue container is yoga root and pink is yoga root children, the black is your clipped area or viewport.
Hi Steven, thanks for late reply. With scrollable area I mean for exactly
what you appear to mean and propose to build.
I mostly solved my problems except to one thing: it appears difficult to
make a scrolling area that scrolls both vertically and horizontally.
Particularly measuring areas in such case. I should build a demonstration
for this. Maybe I'll do so when I have motivation for solving it again.
su 27. huhtik. 2025 klo 16.16 steven @.***> kirjoitti:
Ditto, I initially hugely overcomplicated this :)
Here's what I ended up doing:
InnerContainer
- which hasYGOverflowVisible
(default)OuterContainer
- which hasYGOverflowScroll
ScrollView
ScrollView
based onInnerContainer
's measured dimensions.min-width
, and then I setmax-height
to the measured height for that widthInnerContainer
's width and height are the actual size of your scrollable contentOuterContainer
's width and height will be the size of your scrollable area, not the contentScrollView
withYGPositionTypeAbsolute
InnerContainer
can be removed by:InnerContainer
, if you require that your scrollable area has a single logical child as its' contentOn a side note, calculating the minimum width to avoid a horizontal scrollbar is somewhat irritating, because:
Using the workaround suggested at https://github.com/facebook/yoga/issues/1003#issuecomment-642888983 to work around the caching bug, here's my implementation:
As a binary search, it's reasonably fast for initialization or when constraints change, but isn't suitable for calling every frame.
With your recipe I seem to get a neat scrolling container but it appears to scroll only horizontally or vertically. If I set outer_container.flex-direction to row, it scrolls as a row, and vice versa.
But to my surprise I got a very passable bidirectional scrolling container by doing this:
It looks like for dual scroll container you won't need scroll overflow setting.
I think a lot of the varying behavior and requirements we're seeing is because of Yoga caching bugs, leading to small differences in our usages that should be insignificant actually changing things at a large scale. This feels likely due to Yoga being primarily designed for React Native, which is in turn primarily designed for fixed-size displays like full-screen on phones, rather than resizable windows.
For example, AIUI this code should have no observable effect beyond hurting performance, but sprinkling it in code paths with 'surprising' results often fixes the issue, and lets me keep my scroll handling code simple: