# Sticky
**Also known as:** Affix
## Description
BitSticky keeps its content in the normal flow until the scroll carries it to an edge of its nearest scrolling container, where it stays while the rest passes. The edge is a Placement or exact offsets, the root can be any tag, and since CSS has no event for the moment an element pins, the component derives one - for callbacks, stuck-only styling and a theme shadow. ScrollPadding keeps what the browser scrolls into view out from under it.
## Notes
A sticky pins within its nearest scrolling ancestor and only travels inside its own parent: any ancestor with an overflow other than visible becomes the boundary, even one that does not scroll, and a parent no taller than the element - or a flex parent stretching it - leaves it no room to stick. For a page app bar that hides while scrolling down and reveals itself on the way back up, use BitHeader (Reveal).
## Parameters
| Name | Type | Default Value | Description |
| :--- | :--- | :------------ | :---------- |
| Bottom | `string?` | null | The vertical offset the element pins at from the bottom edge. A bare number is read as a pixel count; anything else is used as written, so any CSS length is accepted. |
| ChildContent | `RenderFragment?` | null | The content of the Sticky, it can be any custom tag or text. |
| Element | `string?` | null | The custom html element used for the root node, which is a div by default - a header, a footer, a nav, an aside or a th is what names the sticky region for assistive technologies. A name that is not one a tag can have falls back to the default. |
| ElevateOnStuck | `bool` | false | Gives the element a surface and the theme's shadow only while it is stuck, cast away from the edge holding it (the app-bar shadow on the top and bottom, the card shadow on the sides). A background from Class or Style still wins; forced colors mode draws an outline instead. Attaches the stuck detection. |
| Left | `string?` | null | The horizontal offset the element pins at from the left edge, for a container that scrolls horizontally. A bare number is read as a pixel count; any CSS length is accepted. |
| OnStuckChanged | `EventCallback<bool>` | | Callback for when the stuck state changes: true while the element is pinned to an edge of its scrolling container. Using it (or OnStuckEdgesChanged, StuckClass, StuckStyle or ElevateOnStuck) attaches the stuck detection. |
| OnStuckEdgesChanged | `EventCallback<BitStickyEdges>` | | Callback for when the set of edges the element is pinned to changes. Unlike OnStuckChanged it also reports the move from one edge of a pair to the other, which never flips the boolean. |
| Placement | `BitPlacement?` | null | The edge of the scrolling container the element pins to. Start and End follow the reading direction. Left, Right and Center are not honoured and fall back to the default: when neither a Placement nor any offset is set, the component sticks to the top. |
| Right | `string?` | null | The horizontal offset the element pins at from the right edge, for a container that scrolls horizontally. A bare number is read as a pixel count; any CSS length is accepted. |
| ScrollPadding | `bool` | false | Reserves the room the element covers (its offset plus its size) as the scroll padding of its scrolling container on every edge it can pin to, so nothing the browser scrolls into view - the focused control, an anchor - lands underneath it (WCAG 2.4.11). Stickies of one container keep the largest claim per edge, and a larger scroll padding the container already has is kept; released while disabled. |
| StuckClass | `string?` | null | The CSS class applied to the root element only while the component is stuck - a shadow, an opaque background, a border once content passes underneath. The bit-stk-stc class and one naming each pinned edge accompany it. |
| StuckStyle | `string?` | null | The CSS style applied to the root element only while the component is stuck, the inline counterpart of StuckClass. |
| Top | `string?` | null | The vertical offset the element pins at from the top edge. A bare number is read as a pixel count; anything else is used as written, so any CSS length is accepted. |
| ZIndex | `int?` | null | The z-index of the root element. When not set, the component keeps a z-index of 1 - enough to stay above the plain flowing content it sticks over without covering popups and overlays. The --bit-Sticky-z-index variable sets the same default from a stylesheet. |
| 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. |
| Disabled | `bool` | false | Gets or sets a value indicating whether the component is disabled and cannot respond to user interaction. |
| 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. An attribute written on the component wins over an entry of the same name. |
| Id | `string?` | null | Gets or sets the unique identifier for the component's root element. |
| 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. |
## Public Members
| Name | Type | Default Value | Description |
| :--- | :--- | :------------ | :---------- |
| IsStuck | `bool` | false | Whether the component is currently stuck to an edge of its scrolling container. Always false unless one of OnStuckChanged, OnStuckEdgesChanged, StuckClass, StuckStyle or ElevateOnStuck is used, since those are what attach the stuck detection. |
| StuckEdges | `BitStickyEdges` | BitStickyEdges.None | The edges of the scrolling container the component is currently pinned to. This is IsStuck with the edges named, and it carries both of them while the element is pinned into a corner. |
| RefreshAsync | `ValueTask` | | Reads the stuck state and the scroll padding claim again, along with everything they are derived from. Both settle themselves on every scroll, on every resize of the element, its parent, the container or the page, and on a change of Position, the offsets, Dir, Class or Style, so this is only for a change none of those can see - content moved around inside the container, a stylesheet or a --bit-Sticky-offset-* variable changed. |
| 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. |
## Enums
### BitPlacement Enum
| Name | Value | Description |
| :--- | :--- | :---------- |
| Top | 0 | The top edge. |
| Bottom | 1 | The bottom edge. |
| Start | 2 | The edge the reading direction starts from - the left in LTR, the right in RTL. On the vertical axis, which does not turn around, it is the top. |
| End | 3 | The edge the reading direction ends at - the right in LTR, the left in RTL. On the vertical axis, which does not turn around, it is the bottom. |
| Left | 4 | The left edge, in both reading directions. |
| Right | 5 | The right edge, in both reading directions. |
| Center | 6 | The middle of the axis, against neither edge. |
| TopAndBottom | 7 | Both edges of the block axis at once. |
| StartAndEnd | 8 | Both edges of the inline axis at once, following the reading direction the way Start and End do. |
### BitStickyEdges Enum
| Name | Value | Description |
| :--- | :--- | :---------- |
| None | 0 | The element is not pinned: it is travelling with the content of its scrolling container. |
| Top | 1 | The element is pinned to the top edge of its scrolling container. |
| Bottom | 2 | The element is pinned to the bottom edge of its scrolling container. |
| Left | 4 | The element is pinned to the left edge of its scrolling container. |
| Right | 8 | The element is pinned to the right edge of its scrolling container. |
### 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. |
## CSS Variables
Public CSS custom properties read off the component's root. Set one on `:root` to restyle every instance, on any ancestor to restyle the ones inside it, or on the `Style` of one instance to restyle it and every instance nested inside it, which inherits the value too - a parameter changes one alone, as does the real CSS property on its `Style` / `Styles` when that property does not inherit (`opacity`); an inherited one (`color`, `font-family`) reaches the nested instances that do not set it themselves.
| Name | Default Value | Description |
| :--- | :------------ | :---------- |
| `--bit-Sticky-z-index` | 1 | Stacking order of the element. The ZIndex parameter wins over it. |
| `--bit-Sticky-offset-top` | 0 | Gap a Top or TopAndBottom sticky (and one with no Placement or offset) keeps from the top edge - e.g. the height of a fixed app bar above the container. The Top parameter wins over it. |
| `--bit-Sticky-offset-bottom` | 0 | Gap a Bottom or TopAndBottom sticky keeps from the bottom edge. The Bottom parameter wins over it. |
| `--bit-Sticky-offset-start` | 0 | Gap a Start or StartAndEnd sticky keeps from the start edge (left in LTR, right in RTL). The Left and Right parameters win over it. |
| `--bit-Sticky-offset-end` | 0 | Gap an End or StartAndEnd sticky keeps from the end edge. The Left and Right parameters win over it. |
| `--bit-Sticky-background` | var(--bit-clr-bg-pri) | Surface of an ElevateOnStuck sticky while stuck. A background from Class or Style wins over it. |
| `--bit-Sticky-shadow-top` | var(--bit-shd-appbar-top) | Shadow of an ElevateOnStuck sticky pinned to the top edge. |
| `--bit-Sticky-shadow-bottom` | var(--bit-shd-appbar-bottom) | Shadow of an ElevateOnStuck sticky pinned to the bottom edge. |
| `--bit-Sticky-shadow-left` | var(--bit-shd-card) | Shadow of an ElevateOnStuck sticky pinned to the left edge. |
| `--bit-Sticky-shadow-right` | var(--bit-shd-card) | Shadow of an ElevateOnStuck sticky pinned to the right edge. |
## Examples
\n**Basic**:
```razor
Basic Sticky
Once upon a time, stories wove connections between people, a symphony of voices crafting shared dreams. Each word carried meaning, each pause brought understanding.
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 of something remarkable.
In the beginning, there is silence: a blank canvas yearning to be filled, a quiet space where creativity waits to awaken, standing in place of ideas yet to come.
In this space, potential reigns supreme. It is a moment suspended in time, where imagination dances freely and each word can become something extraordinary.
Imagine this space as a window into the future, empty yet alive with the energy of endless possibilities, ready to transform into something meaningful.
```
\n**Placement**:
```razor
Once upon a time, stories wove connections between people, a symphony of voices crafting shared dreams. Each word carried meaning, each pause brought understanding.
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 of something remarkable.
In the beginning, there is silence: a blank canvas yearning to be filled, a quiet space where creativity waits to awaken, standing in place of ideas yet to come.
Placement="@verticalPosition"
In this space, potential reigns supreme. It is a moment suspended in time, where imagination dances freely and each word can become something extraordinary.
Imagine this space as a window into the future, empty yet alive with the energy of endless possibilities, ready to transform into something meaningful.
Once upon a time, stories wove connections between people, a symphony of voices crafting shared dreams. Each word carried meaning, each pause brought understanding.
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 of something remarkable.
Once upon a time, stories wove connections between people, a symphony of voices crafting shared dreams.
Placement="@horizontalPosition"
Once upon a time, stories wove connections between people, a symphony of voices crafting shared dreams.
```
```csharp
private BitPlacement verticalPosition = BitPlacement.TopAndBottom;
private BitPlacement horizontalPosition = BitPlacement.StartAndEnd;
```
\n**Offsets**:
```razor
Once upon a time, stories wove connections between people, a symphony of voices crafting shared dreams. Each word carried meaning, each pause brought understanding.
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 of something remarkable.
In the beginning, there is silence: a blank canvas yearning to be filled, a quiet space where creativity waits to awaken, standing in place of ideas yet to come.
Top="16" Bottom="2rem"
In this space, potential reigns supreme. It is a moment suspended in time, where imagination dances freely and each word can become something extraordinary.
Imagine this space as a window into the future, empty yet alive with the energy of endless possibilities, ready to transform into something meaningful.
Once upon a time, stories wove connections between people, a symphony of voices crafting shared dreams. Each word carried meaning, each pause brought understanding.
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 of something remarkable.
Once upon a time, stories wove connections between people, a symphony of voices crafting shared dreams.
Left="16" Right="2rem"
Once upon a time, stories wove connections between people, a symphony of voices crafting shared dreams.
```
\n**Stuck state**:
```razor
Stuck: @isStuck
Once upon a time, stories wove connections between people, a symphony of voices crafting shared dreams. Each word carried meaning, each pause brought understanding.
@(isStuck ? "Stuck" : "Not stuck yet")
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 of something remarkable.
In the beginning, there is silence: a blank canvas yearning to be filled, a quiet space where creativity waits to awaken, standing in place of ideas yet to come.
In this space, potential reigns supreme. It is a moment suspended in time, where imagination dances freely and each word can become something extraordinary.
Imagine this space as a window into the future, empty yet alive with the energy of endless possibilities, ready to transform into something meaningful.
```
```csharp
private bool isStuck;
```
\n**Stuck edges**:
```razor
Pinned to: @stuckEdges
Once upon a time, stories wove connections between people, a symphony of voices crafting shared dreams. Each word carried meaning, each pause brought understanding.
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 of something remarkable.
In the beginning, there is silence: a blank canvas yearning to be filled, a quiet space where creativity waits to awaken, standing in place of ideas yet to come.
@(stuckEdges is BitStickyEdges.None ? "Travelling with the content" : $"Pinned to {stuckEdges}")
In this space, potential reigns supreme. It is a moment suspended in time, where imagination dances freely and each word can become something extraordinary.
Imagine this space as a window into the future, empty yet alive with the energy of endless possibilities, ready to transform into something meaningful.
Once upon a time, stories wove connections between people, a symphony of voices crafting shared dreams. Each word carried meaning, each pause brought understanding.
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 of something remarkable.
```
```csharp
private BitStickyEdges stuckEdges;
```
\n**Element**:
```razor
A sticky header
Once upon a time, stories wove connections between people, a symphony of voices crafting shared dreams. Each word carried meaning, each pause brought understanding.
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 of something remarkable.
In the beginning, there is silence: a blank canvas yearning to be filled, a quiet space where creativity waits to awaken, standing in place of ideas yet to come.
A sticky footer
Name
Role
@foreach (var person in people)
{
| @person.Name |
@person.Role |
}
```
```csharp
private record Person(string Name, string Role, string KnownFor, int Born);
private readonly Person[] people =
[
new("Ada Lovelace", "Mathematician", "The first published algorithm", 1815),
new("Grace Hopper", "Rear Admiral", "The first compiler", 1906),
new("Alan Turing", "Cryptanalyst", "The Turing machine", 1912),
new("Katherine Johnson", "Physicist", "Orbital mechanics at NASA", 1918),
new("Barbara Liskov", "Computer Scientist", "The substitution principle", 1939),
new("Donald Knuth", "Author", "The Art of Computer Programming", 1938),
new("Edsger Dijkstra", "Computer Scientist", "The shortest-path algorithm", 1930),
new("Margaret Hamilton", "Software Engineer", "The Apollo flight software", 1936),
];
```
\n**ZIndex**:
```razor
Default z-index
Once upon a time, stories wove connections between people, a symphony of voices crafting shared dreams. Each word carried meaning, each pause brought understanding.
A positioned box with z-index: 2
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 of something remarkable.
In the beginning, there is silence: a blank canvas yearning to be filled, a quiet space where creativity waits to awaken, standing in place of ideas yet to come.
In this space, potential reigns supreme. It is a moment suspended in time, where imagination dances freely and each word can become something extraordinary.
ZIndex="3"
Once upon a time, stories wove connections between people, a symphony of voices crafting shared dreams. Each word carried meaning, each pause brought understanding.
A positioned box with z-index: 2
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 of something remarkable.
In the beginning, there is silence: a blank canvas yearning to be filled, a quiet space where creativity waits to awaken, standing in place of ideas yet to come.
In this space, potential reigns supreme. It is a moment suspended in time, where imagination dances freely and each word can become something extraordinary.
```
\n**Elevate on stuck**:
```razor
Once upon a time, stories wove connections between people, a symphony of voices crafting shared dreams. Each word carried meaning, each pause brought understanding.
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 of something remarkable.
In the beginning, there is silence: a blank canvas yearning to be filled, a quiet space where creativity waits to awaken, standing in place of ideas yet to come.
Elevated only while stuck
In this space, potential reigns supreme. It is a moment suspended in time, where imagination dances freely and each word can become something extraordinary.
Imagine this space as a window into the future, empty yet alive with the energy of endless possibilities, ready to transform into something meaningful.
Once upon a time, stories wove connections between people, a symphony of voices crafting shared dreams. Each word carried meaning, each pause brought understanding.
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 of something remarkable.
Name
Role
Known for
Born
@foreach (var person in people)
{
@person.Name
| @person.Role |
@person.KnownFor |
@person.Born |
}
```
```csharp
private record Person(string Name, string Role, string KnownFor, int Born);
private readonly Person[] people =
[
new("Ada Lovelace", "Mathematician", "The first published algorithm", 1815),
new("Grace Hopper", "Rear Admiral", "The first compiler", 1906),
new("Alan Turing", "Cryptanalyst", "The Turing machine", 1912),
new("Katherine Johnson", "Physicist", "Orbital mechanics at NASA", 1918),
new("Barbara Liskov", "Computer Scientist", "The substitution principle", 1939),
new("Donald Knuth", "Author", "The Art of Computer Programming", 1938),
new("Edsger Dijkstra", "Computer Scientist", "The shortest-path algorithm", 1930),
new("Margaret Hamilton", "Software Engineer", "The Apollo flight software", 1936),
];
```
\n**Accessibility**:
```razor
Reading list
@foreach (var person in people)
{
@person.Name
}
```
```csharp
private bool reservesScrollPadding = true;
private record Person(string Name, string Role, string KnownFor, int Born);
private readonly Person[] people =
[
new("Ada Lovelace", "Mathematician", "The first published algorithm", 1815),
new("Grace Hopper", "Rear Admiral", "The first compiler", 1906),
new("Alan Turing", "Cryptanalyst", "The Turing machine", 1912),
new("Katherine Johnson", "Physicist", "Orbital mechanics at NASA", 1918),
new("Barbara Liskov", "Computer Scientist", "The substitution principle", 1939),
new("Donald Knuth", "Author", "The Art of Computer Programming", 1938),
new("Edsger Dijkstra", "Computer Scientist", "The shortest-path algorithm", 1930),
new("Margaret Hamilton", "Software Engineer", "The Apollo flight software", 1936),
];
```
\n**Disabled**:
```razor
@(isStickyDisabled ? "Scrolling away with the content" : "Sticking to the top")
Once upon a time, stories wove connections between people, a symphony of voices crafting shared dreams. Each word carried meaning, each pause brought understanding.
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 of something remarkable.
In the beginning, there is silence: a blank canvas yearning to be filled, a quiet space where creativity waits to awaken, standing in place of ideas yet to come.
In this space, potential reigns supreme. It is a moment suspended in time, where imagination dances freely and each word can become something extraordinary.
```
```csharp
private bool isStickyDisabled;
```
\n**Cascading parameters**:
```razor
Cascaded: elevated, 0.5rem from the top
Once upon a time, stories wove connections between people, a symphony of voices crafting shared dreams. Each word carried meaning, each pause brought understanding.
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 of something remarkable.
Cascaded as well
In the beginning, there is silence: a blank canvas yearning to be filled, a quiet space where creativity waits to awaken, standing in place of ideas yet to come.
In this space, potential reigns supreme. It is a moment suspended in time, where imagination dances freely and each word can become something extraordinary.
Its own ElevateOnStuck, the cascaded rest
Imagine this space as a window into the future, empty yet alive with the energy of endless possibilities, ready to transform into something meaningful.
Once upon a time, stories wove connections between people, a symphony of voices crafting shared dreams. Each word carried meaning, each pause brought understanding.
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 of something remarkable.
```
```csharp
private readonly BitStickyParams[] stickyParams =
[
new() { ElevateOnStuck = true, Top = "0.5rem" }
];
```
\n**Style & Class**:
```razor
Styled Sticky
Once upon a time, stories wove connections between people, a symphony of voices crafting shared dreams. Each word carried meaning, each pause brought understanding.
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 of something remarkable.
In the beginning, there is silence: a blank canvas yearning to be filled, a quiet space where creativity waits to awaken, standing in place of ideas yet to come.
In this space, potential reigns supreme. It is a moment suspended in time, where imagination dances freely and each word can become something extraordinary.
Classed Sticky
Once upon a time, stories wove connections between people, a symphony of voices crafting shared dreams. Each word carried meaning, each pause brought understanding.
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 of something remarkable.
In the beginning, there is silence: a blank canvas yearning to be filled, a quiet space where creativity waits to awaken, standing in place of ideas yet to come.
In this space, potential reigns supreme. It is a moment suspended in time, where imagination dances freely and each word can become something extraordinary.
```
\n**RTL**:
```razor
روزی روزگاری، داستانها میان مردم پیوند میساختند؛ همنوایی صداهایی که رویاهای مشترک میآفریدند.
چسبیده به آغاز
روزی روزگاری، داستانها میان مردم پیوند میساختند؛ همنوایی صداهایی که رویاهای مشترک میآفریدند.
روزی روزگاری، داستانها میان مردم پیوند میساختند؛ همنوایی صداهایی که رویاهای مشترک میآفریدند.
چسبیده به پایان
روزی روزگاری، داستانها میان مردم پیوند میساختند؛ همنوایی صداهایی که رویاهای مشترک میآفریدند.
```