Surfaces
ScrollablePane
ScrollablePane is a box that scrolls whatever is put in it, with the browser's own scrolling - momentum, keyboard and assistive technology included. Around that it sizes the box, picks the axes, stops scroll chaining, draws the scrollbar in the theme's colors and hides it until it is wanted, fades the edges that have more beyond them, snaps onto items, scrolls a strip with a drag or a wheel, and becomes a keyboard stop of its own. It reports its position, the start and end of each scroll and each edge it reaches; it scrolls from code; and it stays pinned to a growing log or holds still while older content loads above.
Notes
A pane that only sizes a box, picks its axes, reserves a gutter, snaps or styles its scrollbar is pure CSS: one element, no JavaScript. The browser side is set up only for AutoScroll, Fade, DragScroll, HorizontalWheel, PreserveScroll, AutoHideScrollbar and the scroll and edge callbacks.
Smooth collapses to an instant move under prefers-reduced-motion: reduce - use the ForceAnimation toggle at the top of this page to see it animate anyway.
Usage
Every example is live. Open its code to see exactly what produced the component running underneath.
Basic
Every story starts with a blank canvas, a quiet space waiting to be filled with ideas, emotions, and dreams. These placeholder words symbolize the beginning - a moment of possibility where creativity has yet to take shape.
In the beginning, there is silence, a blank canvas yearning to be filled, a quiet space where creativity waits to awaken. Think of this text as a bridge, connecting the empty spaces of now with the narratives of tomorrow.
In this space, potential reigns supreme. It is a moment suspended in time, where imagination dances freely and each word has the power to transform into something extraordinary.
For now, these lines are here to remind you of the beauty of beginnings. They are the quiet before the symphony, the foundation upon which your creativity will build.
Dimensions
Once upon a time, stories wove connections between people, a symphony of voices crafting shared dreams. Each word carried meaning, each pause brought understanding, and every story found its listener.
Overflow & Horizontal
Overscroll
Scrollbar
Modern
Every story starts with a blank canvas, a quiet space waiting to be filled with ideas, emotions, and dreams. These placeholder words symbolize the beginning - a moment of possibility where creativity has yet to take shape.
In the beginning, there is silence, a blank canvas yearning to be filled, a quiet space where creativity waits to awaken. Think of this text as a bridge, connecting the empty spaces of now with the narratives of tomorrow.
In this space, potential reigns supreme. It is a moment suspended in time, where imagination dances freely and each word has the power to transform into something extraordinary.
For now, these lines are here to remind you of the beauty of beginnings. They are the quiet before the symphony, the foundation upon which your creativity will build.
Fade
Every story starts with a blank canvas, a quiet space waiting to be filled with ideas, emotions, and dreams. These placeholder words symbolize the beginning - a moment of possibility where creativity has yet to take shape.
In the beginning, there is silence, a blank canvas yearning to be filled, a quiet space where creativity waits to awaken. Think of this text as a bridge, connecting the empty spaces of now with the narratives of tomorrow.
In this space, potential reigns supreme. It is a moment suspended in time, where imagination dances freely and each word has the power to transform into something extraordinary.
For now, these lines are here to remind you of the beauty of beginnings. They are the quiet before the symphony, the foundation upon which your creativity will build.
Keyboard & accessibility
Every story starts with a blank canvas, a quiet space waiting to be filled with ideas, emotions, and dreams. These placeholder words symbolize the beginning - a moment of possibility where creativity has yet to take shape.
In the beginning, there is silence, a blank canvas yearning to be filled, a quiet space where creativity waits to awaken. Think of this text as a bridge, connecting the empty spaces of now with the narratives of tomorrow.
In this space, potential reigns supreme. It is a moment suspended in time, where imagination dances freely and each word has the power to transform into something extraordinary.
For now, these lines are here to remind you of the beauty of beginnings. They are the quiet before the symphony, the foundation upon which your creativity will build.
Scroll events
Reaching the edges
Scrolling from code
AutoScroll
Preserving the reader's place
Snapping
Dragging & the wheel
CSS variables
Cascading parameters
Style & Class
RTL
داستانها روزگاری پیوند میان مردم را میبافتند، سمفونیای از صداها که رویاهای مشترک را میساخت. هر واژه معنایی داشت و هر مکث فهمی به همراه میآورد.
در آغاز، سکوت است؛ بومی سفید که در انتظار پر شدن است، فضایی آرام که در آن خلاقیت منتظر بیدار شدن است. این واژهها موقتیاند و جای ایدههایی را گرفتهاند که هنوز نیامدهاند.
در این فضا، امکان حکمرانی میکند. لحظهای معلق در زمان، جایی که تخیل آزادانه میرقصد و هر واژه توان آن را دارد که به چیزی خارقالعاده بدل شود.
CSS variables
The public custom properties this component reads off its root, for what no parameter covers.
Every variable is read with a fallback and never declared by the component, so it inherits like any other custom property:
set one on :root (or in a [bit-theme] block) to restyle every instance, on any ancestor to restyle the ones inside it,
or on the Style of one instance to restyle that one alone. Leave a variable unset and the component falls back to the theme token beside it.
BitScrollablePane CSS variables
| Name | Default value | Description |
|---|---|---|
| --bit-ScrollablePane-scrollbar-size | spacing(0.75), 6px | Thickness of the Modern scrollbar. Not applied in Firefox, which draws its thin standard bar. |
| --bit-ScrollablePane-scrollbar-thumb-color | --bit-clr-fg-ter | Modern thumb at rest. |
| --bit-ScrollablePane-scrollbar-thumb-hover-color | --bit-clr-fg-ter-hover | Modern thumb under the pointer. Not applied in Firefox. |
| --bit-ScrollablePane-scrollbar-thumb-active-color | --bit-clr-fg-ter-active | Modern thumb while it is dragged. Not applied in Firefox. |
| --bit-ScrollablePane-scrollbar-thumb-radius | --bit-shp-radius-full | Corner of the Modern thumb. Not applied in Firefox. |
| --bit-ScrollablePane-scrollbar-track-color | transparent | Modern track. Hidden with the thumb while AutoHideScrollbar keeps the bar out of sight. |
| --bit-ScrollablePane-fade-size | spacing(4), 2rem | How far the Fade reaches into the pane. The FadeSize parameter wins over it. |
| --bit-ScrollablePane-focus-color | --bit-shd-focus-ring | Focus ring color of a pane put in the tab order by Focusable or TabIndex. Unset, the pane draws the library's own --bit-shd-focus-ring. |
API
Every parameter, public member, sub-class and enum this component exposes.
BitScrollablePane parameters
| Name | Type | Default value | Description |
|---|---|---|---|
| AutoScroll | bool | false | Keeps the pane pinned to the end of its content as the content grows. It pins once as soon as it is turned on, and after that only while the reader left the pane standing at the end. |
| AutoScrollThreshold | int | 0 | How near the end of the content (in pixels) the pane has to have been left for AutoScroll to keep pinning it there. |
| AutoHeight | bool | false | Makes the height of the pane auto. |
| AutoSize | bool | false | Makes both height and width of the pane auto. |
| AutoWidth | bool | false | Makes the width of the pane auto. |
| AutoHideScrollbar | bool | false | Keeps the Modern scrollbar of the pane out of sight until the pane is pointed at, holds a focus the keyboard gave it, or has just been scrolled. |
| AutoHideDelay | int | 800 | How long (in milliseconds) the AutoHideScrollbar scrollbar lingers after the pane was last pointed at, focused or scrolled. 0 hides it as soon as the pointer or the focus leaves. |
| Body | RenderFragment? | null | Alias for the ChildContent parameter. |
| ChildContent | RenderFragment? | null | The content of the pane, it can be any custom tag or text. |
| DragMomentum | bool | false | Lets a released drag carry on at the speed it was let go at and slow to a stop, instead of stopping dead with the button. It only applies to DragScroll. |
| ExpandOnPrint | bool | false | Prints the whole of the content instead of the part the pane is showing: the height, the height caps and the clipping are lifted for the print stylesheet only. |
| DragScroll | bool | false | Lets the pane be scrolled by dragging its content with a mouse or a pen, which is how a strip that only scrolls sideways is reached without a horizontal wheel. |
| Fade | bool | false | Fades out each edge of the pane that still has content beyond it, and takes the fade off the moment that edge is reached. |
| FadeSize | string? | null | How far the Fade reaches into the pane, as any CSS length. It defaults to 2rem and wins over an inherited --bit-ScrollablePane-fade-size. |
| FitHeight | bool | false | Makes the height of the pane fit-content. |
| FitSize | bool | false | Makes both height and width of the pane fit-content. |
| FitWidth | bool | false | Makes the width of the pane fit-content. |
| Focusable | bool | false | Puts the pane itself in the tab order, so a pane holding nothing focusable can still be scrolled with the keyboard. It adds no tab stop to a NoScroll pane. |
| FullHeight | bool | false | Makes the height of the pane 100%. |
| FullSize | bool | false | Makes both height and width of the pane 100%. |
| FullWidth | bool | false | Makes the width of the pane 100%. |
| Gutter | BitScrollbarGutter? | null | Allows to reserve space for the scrollbar, preventing unwanted layout changes as the content grows while also avoiding unnecessary visuals when scrolling isn't needed. |
| Height | string? | null | The height of the pane. |
| Horizontal | bool | false | Lays the content out on a single line that scrolls sideways instead of wrapping, and turns the vertical scrolling off. |
| HorizontalWheel | bool | false | Turns a vertical wheel over a pane that only scrolls sideways into a sideways scroll, and hands the scroll back to the page once the pane reaches that end. |
| InitialScrollLeft | double? | null | Where the pane stands the first time it is rendered, measured from the visual left edge of the content in pixels. It is applied once and never animated. |
| InitialScrollTop | double? | null | Where the pane stands the first time it is rendered, measured from the top of the content in pixels. It is applied once and never animated. |
| MaxHeight | string? | null | The maximum height of the pane, which is what makes it grow with its content and only start scrolling once there is too much of it. |
| MaxWidth | string? | null | The maximum width of the pane. |
| MinHeight | string? | null | The minimum height of the pane. |
| MinWidth | string? | null | The minimum width of the pane. |
| Modern | bool | false | Draws the scrollbar of the pane in the colors of the theme instead of by the operating system, restyled through the --bit-ScrollablePane-scrollbar-* variables. Forced colors mode keeps the system scrollbar. |
| NoScroll | bool | false | Turns the scrolling of the pane off while leaving its content interactive and the scrolling API of the component working. |
| OnReachedBottom | EventCallback | Callback for when the pane has been scrolled to the bottom of its content. | |
| OnReachedLeft | EventCallback | Callback for when the pane has been scrolled to the visual left edge of its content. | |
| OnReachedRight | EventCallback | Callback for when the pane has been scrolled to the visual right edge of its content. | |
| OnReachedTop | EventCallback | Callback for when the pane has been scrolled to the top of its content. | |
| OnScroll | EventCallback<BitScrollOffset> | Callback for when the pane is scrolled, carrying where it now stands. | |
| OnScrollEnd | EventCallback<BitScrollOffset> | Callback for when the pane has come to rest after being scrolled, carrying where it stopped. | |
| OnScrollStart | EventCallback<BitScrollOffset> | Callback for when the pane starts being scrolled, carrying where it stood as it set off. | |
| Overflow | BitOverflow? | null | Controls the visibility of scrollbars in the pane. |
| OverflowX | BitOverflow? | null | Controls the visibility of X-axis scrollbar in the pane. It has the last word on that axis, over both Overflow and Horizontal. |
| OverflowY | BitOverflow? | null | Controls the visibility of Y-axis scrollbar in the pane. It has the last word on that axis, over both Overflow and Horizontal. |
| Overscroll | BitOverscroll? | null | What the browser does with a scroll that has already reached the edge of the pane. |
| OverscrollX | BitOverscroll? | null | What the browser does with a horizontal scroll that has already reached the edge of the pane. |
| OverscrollY | BitOverscroll? | null | What the browser does with a vertical scroll that has already reached the edge of the pane. |
| PreserveScroll | bool | false | Keeps the reader's place when content is added above what they are looking at, which is what a conversation that loads older messages at its top needs. Every engine but WebKit already does this on its own, so it only steps in where the browser is not anchoring the pane - which a pane setting overflow-anchor: none on itself is not, on any engine. |
| ReachOffset | int | 0 | How near an edge (in pixels) counts as having reached it, for the four edge callbacks. |
| Role | string? | null | The ARIA role of the pane. An unnamed pane has none; a pane named with AriaLabel or aria-labelledby defaults to region. An empty string renders no role at all, keeping a named pane out of the landmarks. |
| ScrollbarColor | string? | null | Sets the color of the scrollbar thumb and track, in that order. For specific colors, it has to contain both colors separated by a space or otherwise it won't work. |
| ScrollbarWidth | BitScrollbarWidth? | null | Sets the desired thickness of scrollbars when they are shown. |
| ScrollPadding | string? | null | The inset the pane keeps between its edges and anything scrolled into view inside it, as any CSS length. |
| ScrollThrottle | int | 0 | The shortest interval (in milliseconds) between two OnScroll reports. Reports are always coalesced to at most one per animation frame. |
| Smooth | bool | false | Animates every move the pane does not make by hand: the scrolling API, a fragment navigation into it, and the pinning AutoScroll does. |
| Snap | BitScrollSnap? | null | Makes the pane come to rest on the snap positions of its content instead of anywhere between them. |
| SnapAlign | BitScrollSnapAlign? | null | Where the direct children of the pane come to rest in it while Snap is on. |
| SnapStop | bool | false | Keeps a fast scroll from passing over the snap positions it goes by, which is what turns a snapping strip into a carousel that moves one item per gesture. |
| Width | string? | null | The width of the pane. |
BitScrollablePane public members
| Name | Type | Default value | Description |
|---|---|---|---|
| FocusAsync | ValueTask FocusAsync() / ValueTask FocusAsync(bool preventScroll) | Gives the focus to the pane itself, which only takes it while Focusable or a TabIndex has put it in the tab order. | |
| GetScrollOffset | ValueTask<BitScrollOffset?> | Reads where the pane currently stands, straight from the browser. | |
| Refresh | ValueTask | Re-measures the pane and brings the fade and the edge callbacks back up to date, for the size changes neither of its observers can see. | |
| ScrollBy | ValueTask ScrollBy(double x, double y, bool? smooth = null) | Scrolls the pane by a distance from wherever it currently stands, in pixels and measured on the screen: a positive x always moves the pane rightwards. | |
| ScrollTo | ValueTask ScrollTo(double? left, double? top, bool? smooth = null) | Scrolls the pane to an absolute position, in pixels from the top and from the visual left edge of the content. An axis that is left null stays where it is. | |
| ScrollToElement | ValueTask ScrollToElement(string elementId, double offset = 0, bool? smooth = null, BitScrollAlignment alignment = BitScrollAlignment.Start) | Brings an element inside the pane into view by scrolling the pane itself, leaving every scrolling ancestor of it alone. An overload takes an ElementReference (from @ref) in place of the id. | |
| ScrollToEnd | ValueTask ScrollToEnd(bool? smooth = null) | Scrolls the pane to the end of its content, both horizontally and vertically, which on the horizontal axis is the visual left edge of a right-to-left pane. | |
| ScrollToStart | ValueTask ScrollToStart(bool? smooth = null) | Scrolls the pane back to the start of its content, both horizontally and vertically, which on the horizontal axis is the visual right edge of a right-to-left pane. |
BitComponentBase parameters
| Name | Type | Default value | Description |
|---|---|---|---|
| AriaLabel | string? | null | Gets or sets the accessible label for the component, used by assistive technologies. |
| Class | string? | null | Gets or sets the CSS class name(s) to apply to the rendered element. |
| Dir | BitDir? | null | Gets or sets the text directionality for the component's content. |
| ForceAnimation | bool | false | Gets or sets a value indicating whether the component's animations play at their full duration even when reduced motion is requested. |
| HtmlAttributes | Dictionary<string, object> | new Dictionary<string, object>() | Captures additional HTML attributes to be applied to the rendered element, in addition to the component's parameters. |
| Id | string? | null | Gets or sets the unique identifier for the component's root element. |
| IsEnabled | bool | true | Gets or sets a value indicating whether the component is enabled and can respond to user interaction. |
| Style | string? | null | Gets or sets the CSS style string to apply to the rendered element. |
| TabIndex | string? | null | Gets or sets the tab order index for the component when navigating with the keyboard. |
| Visibility | BitVisibility | BitVisibility.Visible | Gets or sets the visibility state (visible, hidden, or collapsed) of the component. |
BitComponentBase public members
| Name | Type | Default value | Description |
|---|---|---|---|
| UniqueId | Guid | Guid.NewGuid() | Gets the readonly unique identifier for the component's root element, assigned when the component instance is constructed. |
| RootElement | ElementReference | Gets the reference to the root HTML element associated with this component. |
BitScrollOffset properties
Where a pane stands, as measured in the browser. Everything is in CSS pixels.
| Name | Type | Default value | Description |
|---|---|---|---|
| Left | double | 0 | The raw scrollLeft of the pane, so in a right-to-left pane it starts at 0 at the right edge and runs negative. |
| Top | double | 0 | How far the content has been scrolled down. |
| ScrollWidth | double | 0 | The full width of the content, including the part of it that is scrolled out of sight. |
| ScrollHeight | double | 0 | The full height of the content, including the part of it that is scrolled out of sight. |
| ClientWidth | double | 0 | The width of the visible area of the pane, without its scrollbar. |
| ClientHeight | double | 0 | The height of the visible area of the pane, without its scrollbar. |
| Rtl | bool | false | Whether the pane was laid out right to left when it was measured, which is what tells the two readings of a Left of 0 apart. |
| DeltaLeft | double | 0 | How far the pane moved sideways since the position before this one was reported, positive rightwards on the screen. Only the reports OnScroll makes carry it. |
| DeltaTop | double | 0 | How far the pane moved up or down since the position before this one was reported, positive downwards. Only the reports OnScroll makes carry it. |
| OffsetLeft | double | 0 | The distance from the visual left edge of the content, which is Left made positive and direction independent. |
| MaxLeft | double | 0 | The largest horizontal offset the pane can reach. |
| MaxTop | double | 0 | The largest vertical offset the pane can reach. |
| ScrollableX | bool | false | Whether the content is wider than the pane. |
| ScrollableY | bool | false | Whether the content is taller than the pane. |
| AtLeft | bool | false | Whether the pane is standing at the visual left edge of its content. |
| AtRight | bool | false | Whether the pane is standing at the visual right edge of its content. |
| AtTop | bool | false | Whether the pane is standing at the top of its content. |
| AtBottom | bool | false | Whether the pane is standing at the bottom of its content. |
| PercentX | double | 0 | How far the pane has been scrolled sideways, from 0 at the visual left edge to 1 at the right one. |
| PercentY | double | 0 | How far the pane has been scrolled down, from 0 at the top to 1 at the bottom. |
| ScrollingDown | bool | false | Whether the move this report carries was downwards, which is what a header that folds away on the way down reads. |
| ScrollingUp | bool | false | Whether the move this report carries was upwards. |
| ScrollingRight | bool | false | Whether the move this report carries was to the right on the screen, whichever way the pane reads. |
| ScrollingLeft | bool | false | Whether the move this report carries was to the left on the screen, whichever way the pane reads. |
BitScrollAlignment enum
| Name | Value | Description |
|---|---|---|
| Start | 0 | The element is brought to the start of the pane: its top edge to the top of the pane, and its leading edge to the leading edge of the pane. |
| Center | 1 | The element is centered in the pane along both axes. |
| End | 2 | The element is brought to the end of the pane: its bottom edge to the bottom of the pane, and its trailing edge to the trailing edge of the pane. |
| Nearest | 3 | The pane moves as little as it can: an element that is already fully in view is not moved to at all, and one that is not is brought to whichever edge it is nearest. |
BitScrollSnap enum
| Name | Value | Description |
|---|---|---|
| None | 0 | The pane does not snap, which is the initial value. |
| Proximity | 1 | The pane snaps to a position only when it comes to rest near one, so a scroll can still be left anywhere between two items. |
| Mandatory | 2 | The pane always comes to rest on a snap position, which is what a carousel or a row of pages wants. |
BitScrollSnapAlign enum
| Name | Value | Description |
|---|---|---|
| None | 0 | The children carry no snap position of their own. |
| Start | 1 | Each child comes to rest at the start of the pane. |
| Center | 2 | Each child comes to rest in the middle of the pane. |
| End | 3 | Each child comes to rest at the end of the pane. |
BitOverflow enum
| Name | Value | Description |
|---|---|---|
| Auto | 0 | Scrollbars are displayed automatically when needed based on the content size, and hidden when not needed. |
| Hidden | 1 | Scrollbars are always hidden, even if the content overflows the visible area. |
| Scroll | 2 | Scrollbars are always visible, allowing users to scroll through the content even if it doesn't overflow the visible area. |
| Visible | 3 | Overflow content is not clipped and may be visible outside the element's padding box. |
BitOverscroll enum
| Name | Value | Description |
|---|---|---|
| Auto | 0 | The initial value: the scroll carries on into the nearest scrolling ancestor once the pane has reached its edge, and the platform's own overscroll affordance is kept. |
| Contain | 1 | The scroll stops at the edge of the pane instead of carrying on into the page behind it, while the platform's own overscroll affordance inside the pane is kept. |
| None | 2 | Like Contain, and the platform's own overscroll affordance is suppressed as well, so the pane neither bounces nor triggers a pull to refresh at its edges. |
BitScrollbarGutter enum
| Name | Value | Description |
|---|---|---|
| Auto | 0 | The initial value. Classic scrollbars create a gutter when overflow is scroll, or when overflow is auto and the box is overflowing. Overlay scrollbars do not consume space. |
| Stable | 1 | When using classic scrollbars, the gutter will be present if overflow is auto, scroll, or hidden even if the box is not overflowing. When using overlay scrollbars, the gutter will not be present. |
| BothEdges | 2 | If a gutter would be present on one of the inline start/end edges of the box, another will be present on the opposite edge as well. |
BitScrollbarWidth enum
| Name | Value | Description |
|---|---|---|
| Auto | 0 | The default scrollbar width for the platform. |
| Thin | 1 | A thin scrollbar width variant on platforms that provide that option, or a thinner scrollbar than the default platform scrollbar width. |
| None | 2 | No scrollbar shown, however the element will still be scrollable. |
BitVisibility enum
| Name | Value | Description |
|---|---|---|
| Visible | 0 | The content of the component is visible. |
| Hidden | 1 | The content of the component is hidden, but the space it takes on the page remains (visibility:hidden). |
| Collapsed | 2 | The component is hidden (display:none). |
BitDir enum
| Name | Value | Description |
|---|---|---|
| Ltr | 0 | Ltr (left to right) is to be used for languages that are written from the left to the right (like English). |
| Rtl | 1 | Rtl (right to left) is to be used for languages that are written from the right to the left (like Arabic). |
| Auto | 2 | Auto lets the user agent decide. It uses a basic algorithm as it parses the characters inside the element until it finds a character with a strong directionality, then applies that directionality to the whole element. |
Feedback
Found a mistake, a gap, or something that could be clearer? Every page and every component is one click from its source.