ui
ui copied to clipboard
The content in ScrollArea doesn't scroll when using max-height
The content in ScrollArea scrolls well when height is specified in className, but not when max-height is used.
here's the example
working
<ScrollArea className="min-w-full h-screen border-slate-200 border rounded-lg">
//content...(the height is larger than screen)
</ScrollArea>
not working
<ScrollArea className="min-w-full max-h-screen border-slate-200 border rounded-lg">
//content...(the height is larger than screen)
</ScrollArea>
Just noticed that has well.
I found a very bad solution but it works right now. Just need to set a height, detect the actual height of the content, and adapt it if it's lower than the max height.
import { Root as ScrollAreaRoot } from "@radix-ui/react-scroll-area"
...
const [scrollAreaHeight, setScrollAreaHeight] = useState<number>(200) // the max height
const scrollArea = useRef<React.ElementRef<typeof ScrollAreaRoot>>(null)
...
useEffect(() => {
const textDiv = (
document.querySelector(
"[data-radix-scroll-area-viewport]"
) as HTMLDivElement // The viewport containing the content of scroll area
)?.children[0] as HTMLDivElement // The actual content of the scroll area
setScrollAreaHeight(textDiv?.offsetHeight < 200 ? textDiv?.offsetHeight : 200) // Set it to the actual height if it's lower than max height
}, [])
...
return (
<ScrollArea
ref={scrollArea}
className={`h-[${scrollAreaHeight}px]`}
>
// The content
</ScrollArea>
)
Here is a solution that works with resizing. I would be happy if someone came up with better/css only solution.
const ScrollArea = React.forwardRef<
React.ElementRef<typeof ScrollAreaPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.Root>
>(({ className, children, ...props }, forwardedRef) => {
const ref = React.useRef<HTMLDivElement>(null);
React.useEffect(() => {
const content = document.querySelector("[data-radix-scroll-area-viewport]")?.children[0] as HTMLElement | undefined;
if (!content) return;
const observer = new ResizeObserver((entries) => {
const entry = entries[0].target as HTMLElement;
if (ref.current) {
// NOTE: This is a hack to fix the scroll area not resizing properly
// when the content is smaller than the scroll area.
ref.current.style.height = entry.offsetHeight + "px";
ref.current.style.height =
entry.offsetHeight < ref.current.offsetHeight
? entry.offsetHeight + "px"
: ref.current.offsetHeight + "px";
}
});
observer.observe(content);
return () => {
observer.disconnect();
};
}, []);
return (
<ScrollAreaPrimitive.Root
ref={composeRefs(forwardedRef, ref)}
className={cn("relative overflow-hidden", className)}
{...props}
>
<ScrollAreaPrimitive.Viewport className="h-full w-full rounded-[inherit]">
{children}
</ScrollAreaPrimitive.Viewport>
<ScrollBar />
<ScrollAreaPrimitive.Corner />
</ScrollAreaPrimitive.Root>
);
});
Hey guys, can you confirm if works if you pass the max-h-* to the Viewport instead of the Root?. Thanks!
This worked for me
<ScrollArea>
<div className="max-h-[20rem]">
... content
</div>
</ScrollArea>
This worked for me
<ScrollArea> <div className="max-h-[20rem]"> ... content </div> </ScrollArea>
This is it 👏! Thanks!
set the components like this, use flex limit viewport height
const ScrollArea = React.forwardRef<
React.ElementRef<typeof ScrollAreaPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.Root>
>(({ className, children, ...props }, ref) => (
<ScrollAreaPrimitive.Root
className={classX('flex flex-col relative overflow-hidden', className)}
>
<ScrollAreaPrimitive.Viewport
ref={ref}
className="flex-grow w-full rounded-[inherit]"
{...props}
>
{children}
</ScrollAreaPrimitive.Viewport>
<ScrollBar />
<ScrollAreaPrimitive.Corner />
</ScrollAreaPrimitive.Root>
))
this code works fine
<ScrollArea className="min-w-full max-h-[80vh] border-slate-200 border rounded-lg">
<div className="h-[110vh]"></
</ScrollArea>
This issue has been automatically closed because it received no activity for a while. If you think it was closed by accident, please leave a comment. Thank you.