Sticky
A wrapper that applies position: sticky and tracks when the element is actually in its stuck state. Use the isStuck slot prop to adapt the UI when sticky behaviour kicks in (e.g. condense a header, change colors, show shadows).
Scroll content row 1.
Scroll content row 2.
Scroll content row 3.
Scroll content row 4.
Scroll content row 5.
Scroll content row 6.
Scroll content row 7.
Scroll content row 8.
Scroll content row 9.
Scroll content row 10.
Scroll content row 11.
Scroll content row 12.
Props
has-shadow-on-stick?: boolean
Apply a shadow when the sticky element is in its stuck state.
offset?: number
The distance in pixels from the sticky edge.
position?: 'top' | 'bottom'
Which edge to stick to.
Default: top
tag?: keyof HTMLElementTagNameMap
The HTML tag to use for the sticky element.
Default: div
Slots
default
The sticky content. Receives `{ isStuck: boolean }` as a slot prop so children can adapt to the stuck state.
Examples
Header
A typical sticky header with a shadow once it sticks.
Body content 1.
Body content 2.
Body content 3.
Body content 4.
Body content 5.
Body content 6.
Body content 7.
Body content 8.
Body content 9.
Body content 10.
Body content 11.
Body content 12.
Body content 13.
Body content 14.
Body content 15.
Body content 16.
Body content 17.
Body content 18.
<template>
<div style="height: 240px; width: 100%; overflow: auto; border: 1px solid var(--surface-stroke); border-radius: 6px">
<FluxSticky has-shadow-on-stick>
<div style="padding: 12px 18px; background: var(--surface); font-weight: 600">
Header
</div>
</FluxSticky>
<div style="padding: 18px">
<p
v-for="i in 18"
:key="i">
Body content {{ i }}.
</p>
</div>
</div>
</template>
<script
setup
lang="ts">
import { FluxSticky } from '@flux-ui/components';
</script>Bottom
Stick to the bottom edge instead.
Content row 1.
Content row 2.
Content row 3.
Content row 4.
Content row 5.
Content row 6.
Content row 7.
Content row 8.
Content row 9.
Content row 10.
Content row 11.
Content row 12.
Content row 13.
Content row 14.
Content row 15.
Content row 16.
Content row 17.
Content row 18.
<template>
<div style="height: 240px; width: 100%; overflow: auto; border: 1px solid var(--surface-stroke); border-radius: 6px">
<div style="padding: 18px">
<p
v-for="i in 18"
:key="i">
Content row {{ i }}.
</p>
</div>
<FluxSticky position="bottom">
<div style="padding: 12px 18px; background: var(--surface); border-top: 1px solid var(--surface-stroke)">
Sticky footer
</div>
</FluxSticky>
</div>
</template>
<script
setup
lang="ts">
import { FluxSticky } from '@flux-ui/components';
</script>Reactive content
Use the `isStuck` slot prop to adapt children to the stuck state.
Body content 1.
Body content 2.
Body content 3.
Body content 4.
Body content 5.
Body content 6.
Body content 7.
Body content 8.
Body content 9.
Body content 10.
Body content 11.
Body content 12.
Body content 13.
Body content 14.
Body content 15.
Body content 16.
Body content 17.
Body content 18.
<template>
<div style="height: 240px; width: 100%; overflow: auto; border: 1px solid var(--surface-stroke); border-radius: 6px">
<FluxSticky has-shadow-on-stick>
<template #default="{ isStuck }">
<div :style="{
padding: isStuck ? '6px 18px' : '18px',
background: 'var(--surface)',
fontWeight: isStuck ? 500 : 700,
fontSize: isStuck ? '14px' : '20px',
transition: 'all .15s var(--swift-out)'
}">
{{ isStuck ? 'Stuck — condensed' : 'Scroll to condense me' }}
</div>
</template>
</FluxSticky>
<div style="padding: 18px">
<p
v-for="i in 18"
:key="i">
Body content {{ i }}.
</p>
</div>
</div>
</template>
<script
setup
lang="ts">
import { FluxSticky } from '@flux-ui/components';
</script>