NuGrid supports sticky headers that remain visible at the top of the grid as you scroll through data.
Enable sticky headers with the layout.stickyHeaders option:
<template>
<NuGrid
:data="data"
:columns="columns"
:layout="{ stickyHeaders: true }"
/>
</template>
Sticky headers work with grouped data. Both column headers and group headers stay visible:
<script setup lang="ts">
const grouping = ref(['category'])
</script>
<template>
<NuGrid
v-model:grouping="grouping"
:data="data"
:columns="columns"
:layout="{ mode: 'group', stickyHeaders: true }"
/>
</template>
When scrolling within a group:
Sticky headers integrate with virtualization for large datasets:
<template>
<div class="h-[600px]">
<NuGrid
:data="data"
:columns="columns"
:layout="{ stickyHeaders: true }"
virtualization
/>
</div>
</template>
For sticky headers to work correctly, the grid should be in a scrollable container:
<template>
<!-- Fixed height container -->
<div class="h-[500px]">
<NuGrid
:data="data"
:columns="columns"
:layout="{ stickyHeaders: true }"
/>
</div>
<!-- Flex container -->
<div class="flex h-screen flex-col">
<header>Header</header>
<div class="flex-1 min-h-0">
<NuGrid
:data="data"
:columns="columns"
:layout="{ stickyHeaders: true }"
/>
</div>
</div>
</template>
Customize the appearance of sticky headers using the ui prop:
<template>
<NuGrid
:data="data"
:columns="columns"
:layout="{ stickyHeaders: true }"
:ui="{
stickyColumnHeader: 'sticky top-0 z-20 bg-gray-100 dark:bg-gray-800',
stickyGroupHeader: 'sticky top-0 z-30 bg-gray-50 dark:bg-gray-900',
}"
/>
</template>
| Slot | Default Classes |
|---|---|
stickyColumnHeader | sticky top-0 z-20 bg-default |
stickyGroupHeader | sticky top-0 z-30 bg-default |
Allow users to toggle sticky headers:
<script setup lang="ts">
const stickyEnabled = ref(true)
</script>
<template>
<div class="mb-4">
<UButton
:color="stickyEnabled ? 'primary' : 'neutral'"
@click="stickyEnabled = !stickyEnabled"
>
Sticky Headers: {{ stickyEnabled ? 'On' : 'Off' }}
</UButton>
</div>
<NuGrid
:data="data"
:columns="columns"
:layout="{ stickyHeaders: stickyEnabled }"
/>
</template>
When sticky headers are enabled, header elements receive a data-sticky-header="true" attribute for CSS targeting:
[data-sticky-header="true"] {
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
<script setup lang="ts">
interface Product {
id: number
name: string
category: string
price: number
stock: number
}
const data = ref<Product[]>([
{ id: 1, name: 'Widget A', category: 'Electronics', price: 29.99, stock: 150 },
{ id: 2, name: 'Widget B', category: 'Electronics', price: 49.99, stock: 75 },
{ id: 3, name: 'Gadget X', category: 'Accessories', price: 19.99, stock: 200 },
// ... more data
])
const columns: NuGridColumn<Product>[] = [
{ accessorKey: 'category', header: 'Category' },
{ accessorKey: 'name', header: 'Name' },
{ accessorKey: 'price', header: 'Price' },
{ accessorKey: 'stock', header: 'Stock' },
]
const grouping = ref(['category'])
const stickyEnabled = ref(true)
</script>
<template>
<div class="h-[400px]">
<NuGrid
v-model:grouping="grouping"
:data="data"
:columns="columns"
:layout="{
mode: 'group',
stickyHeaders: stickyEnabled,
}"
virtualization
/>
</div>
</template>