Skip to content

Add a scroll view

Use the ScrollView helper from Extra/DebugUI/ to wrap content that is larger than its container. The helper handles scrollbar drawing, mouse-wheel input, and clip-rect setup. Your code supplies the total content size and lays out items inside the scope.

To add a scroll view

  1. Decide the total content size. For text content, call ui.MeasureTextLines first to compute the height.
  2. Build a ScrollConfig. It carries the direction, a background padding, and the scrollbar thickness.
    var scrollConfig = new ScrollConfig
    {
        Direction = ScrollDirection.Vertical,
        BackgroundPadding = 0,
        ScrollSize = 12,
    };
    
  3. Open the scope.
    ScrollView.Begin(ui, "log_scroll",
        new Vector2Int(contentW, contentH), scrollConfig);
    {
        // content layout goes here
    }
    ScrollView.End(ui);
    
  4. Lay out items inside the scope. The helper has already pushed a clipped rect, so layout calls stay inside it.
  5. Close the scope with ScrollView.End.

The helper draws scrollbars automatically. Mouse-wheel input inside the scope adjusts the scroll position.

Measure text content

Call ui.MeasureTextLines before ScrollView.Begin to compute the content height for a known string:

Rect bounds = ui.MeasureTextLines(
    m_logRect, m_logText, "roboto_mono", 14,
    TextAlign.TopLeft, Wrap.Wrap);

var scrollConfig = new ScrollConfig
{
    Direction = ScrollDirection.Vertical,
    BackgroundPadding = 0,
    ScrollSize = 12,
};

ScrollView.Begin(ui, "log",
    new Vector2Int((int)bounds.width, (int)bounds.height),
    scrollConfig);

ui.Text(m_logText, "roboto_mono", 14, textColor,
    TextAlign.TopLeft, Wrap.Wrap);

ScrollView.End(ui);

The measurement runs against the same wrap and font settings that the actual Text call uses, so the bounds match.

Scrollbar drawing and styling

The helper renders a default scrollbar inside the scope. To draw custom scrollbar visuals, use the lower-level API. Refer to Use the scroll API directly.

Mouse-wheel input

Mouse-wheel scrolling works automatically when the cursor is over the scroll view's rect and the scroll view's panel is the hovered panel. For the focus-resolution rules, refer to Input and focus.

Pitfalls

The wrong content size. : Scrollbar geometry is incorrect. Content either does not scroll, or scrolls past the end. Recompute the content size before ScrollView.Begin; for text, use MeasureTextLines.

Forgetting ScrollView.End. : The clip and rect stacks accumulate entries that ValidateStacks asserts on at end of frame. Pair every Begin with an End.

Mouse wheel does nothing. : The scroll view's panel is not the hovered panel. Confirm the panel hierarchy and the input-priority order.

Scroll position resets every frame. : The scroll ID changed between frames. Pass a stable string id to ScrollView.Begin.

Additional resources

  • Use the scroll API directly: bypass the helper to draw custom scrollbars or apply your own clipping.
  • Layout: the rect-pushing API used inside the scope.
  • Stacks: why ScrollView.End matters.
  • State: scroll position is owned by Tick UI, keyed by the scroll ID.
  • Input and focus: the rules for mouse-wheel routing.