import { ScrollArea } from '@chakra-ui/react'
import LoremIpsum from 'react-lorem-ipsum'
export const ScrollAreaBasic = () => (
<ScrollArea.Root height="8.5rem" maxW="lg">
<ScrollArea.Viewport>
<ScrollArea.Content spaceY="4" textStyle="sm">
<LoremIpsum p={3} />
</ScrollArea.Content>
</ScrollArea.Viewport>
<ScrollArea.Scrollbar>
<ScrollArea.Thumb />
</ScrollArea.Scrollbar>
<ScrollArea.Corner />
</ScrollArea.Root>
)
Anatomy
import { ScrollArea } from '@chakra-ui/react'<ScrollArea.Root>
<ScrollArea.Viewport>
<ScrollArea.Content />
</ScrollArea.Viewport>
<ScrollArea.Scrollbar>
<ScrollArea.Thumb />
</ScrollArea.Scrollbar>
<ScrollArea.Corner />
</ScrollArea.Root>Examples
Variants
Use the variant prop to change the scrollbar visibility behavior. Values can
be either hover (default) or always.
variant="hover"
variant="always"
import { For, ScrollArea, Stack, Text } from '@chakra-ui/react'
import Lorem from 'react-lorem-ipsum'
const variants = ['hover', 'always'] as const
export const ScrollAreaWithVariants = () => (
<Stack gap="8" maxW="lg">
<For each={variants}>
{(variant) => (
<Stack gap="2" key={variant}>
<Text fontWeight="medium">variant="{variant}"</Text>
<ScrollArea.Root height="8rem" variant={variant}>
<ScrollArea.Viewport>
<ScrollArea.Content paddingEnd="3" textStyle="sm">
<Lorem p={4} />
</ScrollArea.Content>
</ScrollArea.Viewport>
<ScrollArea.Scrollbar />
</ScrollArea.Root>
</Stack>
)}
</For>
</Stack>
)
Sizes
Use the size prop to change the size of the scroll area. This affects the
scrollbar thickness and content padding.
size="xs"
size="sm"
size="md"
size="lg"
import { For, ScrollArea, Stack, Text } from '@chakra-ui/react'
import LoremIpsum from 'react-lorem-ipsum'
const sizes = ['xs', 'sm', 'md', 'lg'] as const
export const ScrollAreaWithSizes = () => (
<Stack gap="8" maxW="lg">
<For each={sizes}>
{(size) => (
<Stack gap="2" key={size}>
<Text fontWeight="medium">size="{size}"</Text>
<ScrollArea.Root size={size} height="8rem" variant="always">
<ScrollArea.Viewport>
<ScrollArea.Content paddingEnd="5" textStyle="sm">
<LoremIpsum p={2} />
</ScrollArea.Content>
</ScrollArea.Viewport>
<ScrollArea.Scrollbar />
</ScrollArea.Root>
</Stack>
)}
</For>
</Stack>
)
Horizontal Scrolling
The scroll area automatically supports horizontal scrolling when content overflows horizontally.
import { Flex, ScrollArea } from '@chakra-ui/react'
import { DecorativeBox } from '#lib/decorative-box'
export const ScrollAreaHorizontal = () => (
<ScrollArea.Root width="24rem" size="xs">
<ScrollArea.Viewport>
<ScrollArea.Content py="4">
<Flex gap="4" flexWrap="nowrap">
{Array.from({ length: 12 }, (_, i) => (
<DecorativeBox rounded="sm" key={i} h="20" w="40" flexShrink="0">
Item {i + 1}
</DecorativeBox>
))}
</Flex>
</ScrollArea.Content>
</ScrollArea.Viewport>
<ScrollArea.Scrollbar orientation="horizontal" />
<ScrollArea.Corner />
</ScrollArea.Root>
)
Both Directions
When content overflows in both directions, both scrollbars will appear.
import { ScrollArea } from '@chakra-ui/react'
import LoremIpsum from 'react-lorem-ipsum'
export const ScrollAreaBothDirections = () => (
<ScrollArea.Root height="12rem" width="lg" size="xs" p="2">
<ScrollArea.Viewport>
<ScrollArea.Content spaceY="4" w="40rem" textStyle="sm">
<LoremIpsum p={3} />
</ScrollArea.Content>
</ScrollArea.Viewport>
<ScrollArea.Scrollbar orientation="horizontal" />
<ScrollArea.Scrollbar orientation="vertical" />
<ScrollArea.Corner bg="bg" />
</ScrollArea.Root>
)
ScrollArea.Corner component to show a corner indicator to
fill the intersection of the two scrollbars for a seamless, styled appearance.Scroll Shadow
Add visual feedback when content is scrollable by implementing scroll shadows
that appear at the edges using mask-image.
Use the data-overflow-y attribute to only show shadows when content actually
overflows—this prevents shadows from appearing when there's a single item or no
scrollable content.
import { ScrollArea } from '@chakra-ui/react'
import { DecorativeBox } from '#lib/decorative-box'
export const ScrollAreaWithScrollShadow = () => {
return (
<ScrollArea.Root height="20rem" maxW="lg">
<ScrollArea.Viewport
css={{
'--scroll-shadow-size': '4rem',
maskImage: 'linear-gradient(#000, #000)',
'&[data-overflow-y]': {
maskImage:
'linear-gradient(#000,#000,transparent 0,#000 var(--scroll-shadow-size),#000 calc(100% - var(--scroll-shadow-size)),transparent)',
'&[data-at-top]': {
maskImage:
'linear-gradient(180deg,#000 calc(100% - var(--scroll-shadow-size)),transparent)',
},
'&[data-at-bottom]': {
maskImage:
'linear-gradient(0deg,#000 calc(100% - var(--scroll-shadow-size)),transparent)',
},
},
}}
>
<ScrollArea.Content spaceY="4">
{Array.from({ length: 10 }, (_, i) => (
<DecorativeBox key={i} h="20">
Item {i + 1}
</DecorativeBox>
))}
</ScrollArea.Content>
</ScrollArea.Viewport>
</ScrollArea.Root>
)
}
Thumb Styling
Customize the appearance of the scrollbar thumb with different styles and colors.
import { ScrollArea } from '@chakra-ui/react'
import LoremIpsum from 'react-lorem-ipsum'
export const ScrollAreaWithThumbStyling = () => (
<ScrollArea.Root height="8rem" maxW="2xl" variant="always">
<ScrollArea.Viewport>
<ScrollArea.Content spaceY="4" pe="2">
<LoremIpsum p={2} />
</ScrollArea.Content>
</ScrollArea.Viewport>
<ScrollArea.Scrollbar bg="red.subtle">
<ScrollArea.Thumb bg="red.solid" />
</ScrollArea.Scrollbar>
</ScrollArea.Root>
)
Props
Root
| Prop | Default | Type |
|---|---|---|
colorPalette | 'gray' | 'base' | 'gray' | 'zinc' | 'neutral' | 'stone' | 'red' | 'orange' | 'amber' | 'yellow' | 'lime' | 'green' | 'emerald' | 'teal' | 'cyan' | 'sky' | 'blue' | 'indigo' | 'violet' | 'purple' | 'fuchsia' | 'pink' | 'rose' | 'sidebar' | 'sidebar.accent' | 'interaction' | 'accent' | 'presence' | 'status' | 'slate'The color palette of the component |
variant | 'hover' | 'hover' | 'always'The variant of the component |
size | 'md' | 'xs' | 'sm' | 'md' | 'lg'The size of the component |
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. | |
ids | Partial<{ root: string; viewport: string; content: string; scrollbar: string; thumb: string }>The ids of the scroll area elements |
Viewport
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
Content
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
Scrollbar
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. | |
orientation | Orientation |
Thumb
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
Corner
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |