Scroll Area
A native scroll container with custom scrollbars.
View source
import * as ScrollArea from "@danielfrg/solid-ui/scroll-area"
import styles from "./index.module.css"
export function DemoScrollAreaHero() {
return (
<ScrollArea.Root class={styles.root}>
<ScrollArea.Viewport class={styles.viewport}>
<p class={styles.paragraph}>
Vernacular architecture is building done outside any academic tradition, and without professional guidance. It
is not a particular architectural movement or style, but rather a broad category, encompassing a wide range
and variety of building types, with differing methods of construction, from around the world, both historical
and extant and classical and modern. Vernacular architecture constitutes 95% of the world's built environment,
as estimated in 1995 by Amos Rapoport, as measured against the small percentage of new buildings every year
designed by architects and built by engineers.
</p>
<p class={styles.paragraph}>
This type of architecture usually serves immediate, local needs, is constrained by the materials available in
its particular region and reflects local traditions and cultural practices. The study of vernacular
architecture does not examine formally schooled architects, but instead that of the design skills and
tradition of local builders, who were rarely given any attribution for the work. More recently, vernacular
architecture has been examined by designers and the building industry in an effort to be more energy conscious
with contemporary design and construction — part of a broader interest in sustainable design.
</p>
</ScrollArea.Viewport>
<ScrollArea.Scrollbar class={styles.scrollbar}>
<ScrollArea.Thumb class={styles.thumb} />
</ScrollArea.Scrollbar>
</ScrollArea.Root>
)
}.root {
position: relative;
box-sizing: border-box;
width: 24rem;
height: 8.5rem;
max-width: calc(100vw - 8rem);
}
.viewport {
box-sizing: border-box;
width: 100%;
height: 100%;
border-radius: 0.375rem;
outline: 1px solid var(--color-gray-200);
outline-offset: -1px;
overflow: auto;
padding: 0.75rem 1.5rem 0.75rem 1rem;
}
.viewport:focus-visible {
outline: 2px solid var(--color-blue);
}
/* Hide WebKit native scrollbar */
.viewport::-webkit-scrollbar {
display: none;
}
.paragraph {
margin: 0;
margin-bottom: 1rem;
font-size: 0.875rem;
line-height: 1.375rem;
color: var(--color-gray-900);
}
.paragraph:last-child {
margin-bottom: 0;
}
.scrollbar {
display: flex;
justify-content: center;
background-color: var(--color-gray-200);
width: 0.25rem;
border-radius: 0.375rem;
margin: 0.5rem;
opacity: 0;
transition: opacity 150ms;
pointer-events: none;
}
.scrollbar[data-scrolling] {
transition-duration: 0ms;
}
.root:hover .scrollbar,
.scrollbar[data-hovering],
.scrollbar[data-scrolling] {
opacity: 1;
pointer-events: auto;
}
.scrollbar[data-orientation="horizontal"] {
flex-direction: column;
height: 0.375rem;
width: auto;
}
.thumb {
width: 100%;
border-radius: inherit;
background-color: var(--color-gray-500);
}
.thumb::before {
content: "";
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: calc(100% + 1rem);
height: calc(100% + 1rem);
}
.scrollbar::before {
content: "";
position: absolute;
width: 1.25rem;
height: 100%;
}:root {
--color-blue: oklch(45% 50% 264deg);
--color-red: oklch(50% 55% 31deg);
--color-gray-50: oklch(98% 0.25% 264deg);
--color-gray-100: oklch(12% 9.5% 264deg / 5%);
--color-gray-200: oklch(12% 9% 264deg / 7%);
--color-gray-300: oklch(12% 8.5% 264deg / 17%);
--color-gray-400: oklch(12% 8% 264deg / 38%);
--color-gray-500: oklch(12% 7.5% 264deg / 50%);
--color-gray-600: oklch(12% 7% 264deg / 67%);
--color-gray-700: oklch(12% 6% 264deg / 77%);
--color-gray-800: oklch(12% 5% 264deg / 85%);
--color-gray-900: oklch(12% 5% 264deg / 90%);
--color-gray-950: oklch(12% 5% 264deg / 95%);
}
@media (prefers-color-scheme: dark) {
:root {
--color-blue: oklch(69% 50% 264deg);
--color-red: oklch(80% 55% 31deg);
--color-gray-50: oklch(17% 0.25% 264deg);
--color-gray-100: oklch(28% 0.75% 264deg / 65%);
--color-gray-200: oklch(29% 0.75% 264deg / 80%);
--color-gray-300: oklch(35% 0.75% 264deg / 80%);
--color-gray-400: oklch(47% 0.875% 264deg / 80%);
--color-gray-500: oklch(64% 1% 264deg / 80%);
--color-gray-600: oklch(82% 1% 264deg / 80%);
--color-gray-700: oklch(92% 1.125% 264deg / 80%);
--color-gray-800: oklch(93% 0.875% 264deg / 85%);
--color-gray-900: oklch(95% 0.5% 264deg / 90%);
--color-gray-950: oklch(94% 0.375% 264deg / 95%);
}
}