# Scrolling > Programmatic scrolling, smooth scroll, and overscroll behavior. --- .. llms_copy::references/scrolling .. toc:: ### Overview Control scroll behavior with programmatic navigation, smooth scrolling animations, and overscroll padding. ### Scrolling To A Cell Programmatically scroll to any cell using `scrollToCell`. Specify alignment to control where the cell appears in the viewport. .. exec::examples.reference.scrolling.scroll_to :code: false ```python # File: examples/reference/scrolling/scroll_to.py import dash_glide_grid as dgg import dash_mantine_components as dmc from dash import callback, Input, Output, State columns = [ {"title": "ID", "id": "id", "width": 60}, {"title": "Name", "id": "name", "width": 140}, {"title": "Value", "id": "value", "width": 100}, {"title": "Status", "id": "status", "width": 100}, {"title": "Notes", "id": "notes", "width": 200}, ] # Generate 100 rows data = [ { "id": i + 1, "name": f"Item {i + 1}", "value": (i + 1) * 100, "status": "Active" if i % 3 != 0 else "Pending", "notes": f"Note for item {i + 1}", } for i in range(100) ] component = dmc.Stack([ dmc.Group([ dmc.NumberInput(id="scroll-to-row", label="Row", value=50, min=0, max=99, w=80), dmc.NumberInput(id="scroll-to-col", label="Column", value=2, min=0, max=4, w=80), dmc.Select( id="scroll-to-align", label="Alignment", data=["start", "center", "end"], value="center", w=100, ), dmc.Button("Scroll To Cell", id="scroll-to-btn", variant="light"), ]), dgg.GlideGrid( id={"type": "glide-grid", "index": "scrolling-scroll-to"}, columns=columns, data=data, height=250, ), ], gap="md") @callback( Output({"type": "glide-grid", "index": "scrolling-scroll-to"}, "scrollToCell"), Input("scroll-to-btn", "n_clicks"), State("scroll-to-row", "value"), State("scroll-to-col", "value"), State("scroll-to-align", "value"), prevent_initial_call=True, ) def scroll_to_cell(n_clicks, row, col, align): if n_clicks: return { "col": col or 0, "row": row or 0, "direction": "both", "hAlign": align, "vAlign": align, } return None ``` :defaultExpanded: false :withExpandedButton: true ### Smooth Scrolling Behavior Enable smooth scrolling for animated transitions between cells. Disable for instant cell-aligned scrolling. .. exec::examples.reference.scrolling.smooth :code: false ```python # File: examples/reference/scrolling/smooth.py import dash_glide_grid as dgg import dash_mantine_components as dmc from dash import callback, Input, Output columns = [ {"title": "ID", "id": "id", "width": 80}, {"title": "Name", "id": "name", "width": 150}, {"title": "Category", "id": "category", "width": 120}, {"title": "Brand", "id": "brand", "width": 120}, {"title": "Price", "id": "price", "width": 100}, {"title": "Stock", "id": "stock", "width": 100}, {"title": "Rating", "id": "rating", "width": 100}, {"title": "Reviews", "id": "reviews", "width": 100}, {"title": "SKU", "id": "sku", "width": 120}, {"title": "Warehouse", "id": "warehouse", "width": 120}, ] categories = ["Electronics", "Clothing", "Home", "Sports"] brands = ["Acme", "Beta", "Gamma", "Delta", "Echo"] warehouses = ["East", "West", "Central", "North", "South"] # Generate 200 rows data = [ { "id": i + 1, "name": f"Product {i + 1}", "category": categories[i % len(categories)], "brand": brands[i % len(brands)], "price": round(10 + (i * 0.5) % 500, 2), "stock": (i * 7) % 1000, "rating": round(3 + (i % 20) / 10, 1), "reviews": (i * 13) % 500, "sku": f"SKU-{i + 1:05d}", "warehouse": warehouses[i % len(warehouses)], } for i in range(200) ] component = dmc.Stack([ dmc.Group([ dmc.Switch(id="smooth-scroll-x", label="Smooth Scroll X", checked=False), dmc.Switch(id="smooth-scroll-y", label="Smooth Scroll Y", checked=False), dmc.Switch(id="prevent-diagonal", label="Prevent Diagonal", checked=False), ]), dgg.GlideGrid( id={"type": "glide-grid", "index": "scrolling-smooth"}, columns=columns, data=data, height=250, smoothScrollX=False, smoothScrollY=False, preventDiagonalScrolling=False, ), dmc.Text("Toggle smooth scrolling to see the difference. Smooth scrolling animates between cells.", size="sm", c="dimmed"), ], gap="md") @callback( Output({"type": "glide-grid", "index": "scrolling-smooth"}, "smoothScrollX"), Output({"type": "glide-grid", "index": "scrolling-smooth"}, "smoothScrollY"), Output({"type": "glide-grid", "index": "scrolling-smooth"}, "preventDiagonalScrolling"), Input("smooth-scroll-x", "checked"), Input("smooth-scroll-y", "checked"), Input("prevent-diagonal", "checked"), ) def update_smooth(x, y, diagonal): return x, y, diagonal ``` :defaultExpanded: false :withExpandedButton: true ### Overscrolling Add extra scrollable space beyond content bounds. Useful for providing visual padding at edges. .. exec::examples.reference.scrolling.overscroll :code: false ```python # File: examples/reference/scrolling/overscroll.py import dash_glide_grid as dgg import dash_mantine_components as dmc from dash import callback, Input, Output columns = [ {"title": "ID", "id": "id", "width": 80}, {"title": "Name", "id": "name", "width": 150}, {"title": "Category", "id": "category", "width": 120}, {"title": "Status", "id": "status", "width": 100}, {"title": "Value", "id": "value", "width": 100}, {"title": "Quantity", "id": "quantity", "width": 100}, {"title": "Price", "id": "price", "width": 100}, {"title": "Total", "id": "total", "width": 120}, {"title": "Notes", "id": "notes", "width": 200}, ] categories = ["Electronics", "Clothing", "Food", "Books", "Home"] statuses = ["Active", "Pending", "Shipped", "Delivered"] data = [ { "id": i + 1, "name": f"Item {i + 1}", "category": categories[i % len(categories)], "status": statuses[i % len(statuses)], "value": (i + 1) * 10, "quantity": (i % 10) + 1, "price": round(9.99 + (i * 2.5), 2), "total": round(((i % 10) + 1) * (9.99 + (i * 2.5)), 2), "notes": f"Note for item {i + 1}", } for i in range(30) ] component = dmc.Stack([ dmc.Group([ dmc.NumberInput( id="overscroll-x-val", label="Overscroll X (px)", value=0, min=0, max=300, step=50, w=140, ), dmc.NumberInput( id="overscroll-y-val", label="Overscroll Y (px)", value=0, min=0, max=300, step=50, w=140, ), ]), dgg.GlideGrid( id={"type": "glide-grid", "index": "scrolling-overscroll"}, columns=columns, data=data, height=250, overscrollX=0, overscrollY=0, ), dmc.Text("Overscroll adds extra scrollable space beyond the content bounds.", size="sm", c="dimmed"), ], gap="md") @callback( Output({"type": "glide-grid", "index": "scrolling-overscroll"}, "overscrollX"), Output({"type": "glide-grid", "index": "scrolling-overscroll"}, "overscrollY"), Input("overscroll-x-val", "value"), Input("overscroll-y-val", "value"), ) def update_overscroll(x, y): return x or 0, y or 0 ``` :defaultExpanded: false :withExpandedButton: true ### Scroll To Active Cell Control whether the grid auto-scrolls to keep the active cell visible with `scrollToActiveCell`. When enabled (default), arrow key navigation scrolls the viewport. When disabled, the active cell can move outside the visible area. .. exec::examples.reference.scrolling.scroll_active :code: false ```python # File: examples/reference/scrolling/scroll_active.py import dash_glide_grid as dgg import dash_mantine_components as dmc from dash import callback, Input, Output columns = [ {"title": "Row", "id": "row", "width": 70}, {"title": "A", "id": "a", "width": 90}, {"title": "B", "id": "b", "width": 90}, {"title": "C", "id": "c", "width": 90}, {"title": "D", "id": "d", "width": 90}, ] data = [ {"row": i, "a": f"A{i}", "b": f"B{i}", "c": f"C{i}", "d": f"D{i}"} for i in range(30) ] component = dmc.Stack([ dmc.Switch( id="scrolling-active-toggle", label="Scroll to Active Cell", checked=True, ), dgg.GlideGrid( id={"type": "glide-grid", "index": "scrolling-active"}, columns=columns, data=data, height=220, scrollToActiveCell=True, ), dmc.Text(id="scrolling-active-output", size="sm", c="dimmed"), ]) @callback( Output({"type": "glide-grid", "index": "scrolling-active"}, "scrollToActiveCell"), Input("scrolling-active-toggle", "checked"), ) def update_scroll_behavior(checked): return checked @callback( Output("scrolling-active-output", "children"), Input("scrolling-active-toggle", "checked"), ) def show_description(enabled): if enabled: return "Arrow keys will scroll to keep the active cell visible" return "Arrow keys navigate but the grid does not auto-scroll" ``` :defaultExpanded: false :withExpandedButton: true ### Scroll Behavior During Editing [dgg] Control how the grid behaves when the user scrolls while a cell editor is open. This is useful for preventing orphaned editor overlays or ensuring focused data entry. .. exec::examples.reference.scrolling.editor_scroll :code: false ```python # File: examples/reference/scrolling/editor_scroll.py import dash_glide_grid as dgg import dash_mantine_components as dmc from dash import callback, Input, Output columns = [ {"title": "ID", "id": "id", "width": 60}, {"title": "Name", "id": "name", "width": 150}, {"title": "Status", "id": "status", "width": 130}, {"title": "Tags", "id": "tags", "width": 180}, {"title": "Notes", "id": "notes", "width": 200}, ] STATUS_OPTIONS = [ {"value": "active", "label": "Active", "color": "#10b981"}, {"value": "pending", "label": "Pending", "color": "#f59e0b"}, {"value": "inactive", "label": "Inactive", "color": "#ef4444"}, {"value": "review", "label": "Under Review", "color": "#6366f1"}, {"value": "approved", "label": "Approved", "color": "#22c55e"}, {"value": "rejected", "label": "Rejected", "color": "#dc2626"}, {"value": "on-hold", "label": "On Hold", "color": "#9ca3af"}, {"value": "in-progress", "label": "In Progress", "color": "#3b82f6"}, {"value": "completed", "label": "Completed", "color": "#059669"}, {"value": "cancelled", "label": "Cancelled", "color": "#78716c"}, {"value": "draft", "label": "Draft", "color": "#a3a3a3"}, {"value": "scheduled", "label": "Scheduled", "color": "#8b5cf6"}, ] TAG_OPTIONS = [ {"value": "urgent", "label": "Urgent", "color": "#ef4444"}, {"value": "important", "label": "Important", "color": "#f59e0b"}, {"value": "low", "label": "Low Priority", "color": "#22c55e"}, {"value": "followup", "label": "Follow Up", "color": "#3b82f6"}, {"value": "bug", "label": "Bug", "color": "#dc2626"}, {"value": "feature", "label": "Feature", "color": "#8b5cf6"}, {"value": "enhancement", "label": "Enhancement", "color": "#06b6d4"}, {"value": "documentation", "label": "Documentation", "color": "#64748b"}, {"value": "testing", "label": "Testing", "color": "#f97316"}, {"value": "security", "label": "Security", "color": "#be123c"}, {"value": "performance", "label": "Performance", "color": "#0891b2"}, {"value": "refactor", "label": "Refactor", "color": "#7c3aed"}, {"value": "design", "label": "Design", "color": "#ec4899"}, {"value": "backend", "label": "Backend", "color": "#475569"}, {"value": "frontend", "label": "Frontend", "color": "#2563eb"}, {"value": "devops", "label": "DevOps", "color": "#ca8a04"}, ] # Generate 100 rows with dropdown and multi-select cells data = [ { "id": i + 1, "name": f"Project {chr(65 + (i % 26))}{i // 26 + 1}", "status": { "kind": "dropdown-cell", "data": { "value": STATUS_OPTIONS[i % 4]["value"], "allowedValues": STATUS_OPTIONS, }, "allowOverlay": True, }, "tags": { "kind": "multi-select-cell", "data": { "values": ["urgent", "important"] if i % 3 == 0 else ["low"], "options": TAG_OPTIONS, "allowCreation": False, }, "allowOverlay": True, }, "notes": f"Notes for project {i + 1}", } for i in range(100) ] component = dmc.Stack([ dmc.SegmentedControl( id="editor-scroll-mode", data=[ {"value": "default", "label": "Default"}, {"value": "close-overlay-on-scroll", "label": "Close on Scroll"}, {"value": "lock-scroll", "label": "Lock Scroll"}, ], value="default", ), dgg.GlideGrid( id={"type": "glide-grid", "index": "editor-scroll"}, columns=columns, data=data, height=250, editorScrollBehavior="default", ), dmc.Text(id="editor-scroll-description", size="sm", c="dimmed"), ], gap="md") @callback( Output({"type": "glide-grid", "index": "editor-scroll"}, "editorScrollBehavior"), Output("editor-scroll-description", "children"), Input("editor-scroll-mode", "value"), ) def update_editor_scroll(mode): descriptions = { "default": "Editor stays at original position when scrolling (standard behavior)", "close-overlay-on-scroll": "Editor overlay closes when any scroll is detected", "lock-scroll": "Scrolling is disabled while the editor is open", } return mode, descriptions.get(mode, "") ``` :defaultExpanded: false :withExpandedButton: true **Available modes:** | Mode | Description | |------|-------------| | `default` | Editor stays at original position when scrolling. May appear disconnected from its cell after scrolling. | | `close-overlay-on-scroll` | Editor overlay closes when any scroll is detected. Prevents orphaned editors. | | `lock-scroll` | Scrolling is disabled while editor is open (modal-like behavior). Editor stays aligned with cell. | ### Props Reference #### Scroll To Cell | Property | Type | Description | |----------|------|-------------| | `scrollToCell` | dict | Scroll to a specific cell location | scrollToCell object structure: ```python { "col": 5, # Column index "row": 100, # Row index "direction": "both", # "horizontal", "vertical", or "both" "hAlign": "center", # "start", "center", or "end" "vAlign": "center", # "start", "center", or "end" "paddingX": 0, # Horizontal padding in pixels "paddingY": 0, # Vertical padding in pixels } ``` #### Initial Scroll Position | Property | Type | Default | Description | |----------|------|---------|-------------| | `scrollOffsetX` | number | 0 | Initial horizontal scroll offset in pixels | | `scrollOffsetY` | number | 0 | Initial vertical scroll offset in pixels | #### Smooth Scrolling | Property | Type | Default | Description | |----------|------|---------|-------------| | `smoothScrollX` | boolean | False | Enable smooth horizontal scrolling | | `smoothScrollY` | boolean | False | Enable smooth vertical scrolling | | `preventDiagonalScrolling` | boolean | False | Prevent simultaneous horizontal and vertical scrolling | | `scrollToActiveCell` | boolean | True | Auto-scroll to keep active cell visible during keyboard navigation | #### Overscroll | Property | Type | Default | Description | |----------|------|---------|-------------| | `overscrollX` | number | 0 | Extra horizontal scroll space in pixels | | `overscrollY` | number | 0 | Extra vertical scroll space in pixels | #### Editor Scroll Behavior | Property | Type | Default | Description | |----------|------|---------|-------------| | `editorScrollBehavior` | string | "default" | Controls behavior when scrolling while editor is open: "default", "close-overlay-on-scroll", or "lock-scroll" | --- *Source: /reference/scrolling* *Generated with dash-improve-my-llms*