Skip to content

Feature: sticky group row headers (per-level, stacked) #4924

Description

@Bizordec

Is your feature request related to a problem? Please describe.

When a grouped table is tall enough to scroll, the group header rows scroll out of view along with the data rows. For multi-level groupBy configurations it's easy to lose track of which group the currently-visible rows belong to — you have to scroll back up to find the parent group header, then back down to keep reading. This makes working with large grouped datasets disorienting, especially with two or three grouping levels where a level-0 group may contain dozens of level-1 sub-groups spanning many screens.

Describe the solution you'd like

An opt-in groupStickyHeader boolean table option that keeps group headers pinned to the top of the scroll viewport while their group's rows scroll underneath. For nested groups, levels stack: level-0 sticks at the top of the viewport, level-1 sticks directly below the active level-0 header, level-2 below level-1, and so on. This is a common interaction pattern (similar to sticky section headers in file explorers, contact lists, and spreadsheet outline groups) and would benefit any user working with large grouped datasets.

new Tabulator("#table", {
  data: [...],
  groupBy: ["region", "team"],
  groupStickyHeader: true,
  // ...
});

Expected behavior:

  • level-0 group headers stick at the top of the viewport.
  • level-N group headers stick directly below the active header of level N-1, regardless of the groupHeader generator's output height.
  • When all of a group's rows have scrolled past, the stuck header for that level swaps to the next group's header.
  • Clicking a stuck header still toggles the group's visibility.
  • Works in both the basic and virtual DOM renderers.
  • Interacts correctly with frozen columns and frozen rows.
  • Defaults to off — existing tables are unaffected.

Describe alternatives you've considered

  • Manually tracking the current top-level group and re-rendering it outside the table — fragile, doesn't handle nested levels, and breaks when the user sorts or filters.
  • Using the existing frozenRows feature on group header rows — frozen rows live outside the scroll container, so they can't follow the active group as the user scrolls; they only ever show one fixed set.
  • Applying CSS position: sticky via a custom theme — works in the basic renderer but is broken by the virtual DOM renderer, which removes off-screen group headers from the DOM entirely.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Suggested FeatureA suggested feature that is waiting review

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions