Layout & Display

Sticky Headers

Keep column and group headers visible while scrolling.

NuGrid supports sticky headers that remain visible at the top of the grid as you scroll through data.

Enabling Sticky Headers

Enable sticky headers with the layout.stickyHeaders option:

<template>
  <NuGrid
    :data="data"
    :columns="columns"
    :layout="{ stickyHeaders: true }"
  />
</template>

With Grouping

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:

  • The column headers remain at the top with z-index 30
  • The active group header stays below the column headers with z-index 20

With Virtualization

Sticky headers integrate with virtualization for large datasets:

<template>
  <div class="h-[600px]">
    <NuGrid
      :data="data"
      :columns="columns"
      :layout="{ stickyHeaders: true }"
      virtualization
    />
  </div>
</template>

Container Requirements

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>

Styling Sticky Headers

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>

Default Classes

SlotDefault Classes
stickyColumnHeadersticky top-0 z-20 bg-default
stickyGroupHeadersticky top-0 z-30 bg-default

Dynamic Toggle

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>

Data Attribute

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);
}

Complete Example

<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>

Next Steps

Grouping

Group rows by columns.

Virtualization

Handle large datasets efficiently.