ScrollView

Added in version 1.0.4.

The ScrollView widget provides a scrollable/pannable viewport that is clipped at the scrollview’s bounding box.

Note

Use RecycleView for generating large numbers of widgets in order to display many data items.

Scrolling Behavior

The ScrollView accepts only one child and applies a viewport/window to it according to the scroll_x and scroll_y properties. Touches are analyzed to determine if the user wants to scroll or control the child in some other manner: you cannot do both at the same time. To determine if interaction is a scrolling gesture, these properties are used:

If a touch travels scroll_distance pixels within the scroll_timeout period, it is recognized as a scrolling gesture and translation (scroll/pan) will begin. If the timeout occurs, the touch down event is dispatched to the child instead (no translation).

The default value for those settings can be changed in the configuration file:

[widgets]
scroll_timeout = 250
scroll_distance = 20

Added in version 1.1.1: ScrollView now animates scrolling in Y when a mousewheel is used.

Limiting to the X or Y Axis

By default, the ScrollView allows scrolling along both the X and Y axes. You can explicitly disable scrolling on an axis by setting the do_scroll_x or do_scroll_y properties to False.

Managing the Content Size and Position

The ScrollView manages the position of its children similarly to a RelativeLayout but does not use the size_hint. You must carefully specify the size of your content to get the desired scroll/pan effect.

By default, the size_hint is (1, 1), so the content size will fit your ScrollView exactly (you will have nothing to scroll). You must deactivate at least one of the size_hint instructions (x or y) of the child to enable scrolling. Setting size_hint_min to not be None will also enable scrolling for that dimension when the ScrollView is smaller than the minimum size.

To scroll a GridLayout on it’s Y-axis/vertically, set the child’s width to that of the ScrollView (size_hint_x=1), and set the size_hint_y property to None:

from kivy.uix.gridlayout import GridLayout
from kivy.uix.button import Button
from kivy.uix.scrollview import ScrollView
from kivy.core.window import Window
from kivy.app import runTouchApp

layout = GridLayout(cols=1, spacing=10, size_hint_y=None)
# Make sure the height is such that there is something to scroll.
layout.bind(minimum_height=layout.setter('height'))
for i in range(100):
    btn = Button(text=str(i), size_hint_y=None, height=40)
    layout.add_widget(btn)
root = ScrollView(size_hint=(1, None), size=(Window.width, Window.height))
root.add_widget(layout)

runTouchApp(root)

Kv Example:

ScrollView:
    do_scroll_x: False
    do_scroll_y: True

    Label:
        size_hint_y: None
        height: self.texture_size[1]
        text_size: self.width, None
        padding: 10, 10
        text:
            'really some amazing text\n' * 100

Overscroll Effects

Added in version 1.7.0.

When scrolling would exceed the bounds of the ScrollView, it uses a ScrollEffect to handle the overscroll. These effects can perform actions like bouncing back, changing opacity, or simply preventing scrolling beyond the normal boundaries. Note that complex effects may perform many computations, which can be slow on weaker hardware.

You can change what effect is being used by setting effect_cls to any effect class. Current options include:

  • ScrollEffect: Does not allow scrolling beyond the ScrollView boundaries.

  • DampedScrollEffect: The current default. Allows the user to scroll beyond the normal boundaries, but has the content spring back once the touch/click is released.

  • OpacityScrollEffect: Similar to the DampedScrollEffect, but also reduces opacity during overscroll.

You can also create your own scroll effect by subclassing one of these, then pass it as the effect_cls in the same way.

Alternatively, you can set effect_x and/or effect_y to an instance of the effect you want to use. This will override the default effect set in effect_cls.

All the effects are located in the kivy.effects.

Nested ScrollViews

An application can have multiple levels of nested ScrollViews. The ScrollView class manages the hierarchy of nested ScrollViews.

It is important to set the do_scroll_x and do_scroll_y properties to the correct values for the nested ScrollViews. The nested scrolling behavior, described below, is only applied if the do_scroll_x and do_scroll_y properties are set to the appropriate values.

To achieve orthogonal scrolling, for example, the outer ScrollView should have do_scroll_x set to False and the inner ScrollView should have do_scroll_y set to True, or vice versa.

For Parallel scrolling, both ScrollViews should have the same value for do_scroll_x and do_scroll_y. This can allow vertical in vertical, horizontal in horizontal, or XY in XY scrolling.

For mixed scrolling, the outer ScrollView should have do_scroll_x and do_scroll_y set to True, and the inner ScrollView should have either do_scroll_x or do_scroll_y set to False.

Orthogonal Scrolling (outer and inner scroll in different directions):
  • Touch: Each ScrollView scrolls only in its direction

  • Wheel: Innermost ScrollView scrolls if it supports that axis

  • Example: Vertical outer + Horizontal inner

Parallel Scrolling (outer and inner scroll in the same direction):
  • Touch: Web-style boundary delegation (see below)

  • Wheel: Innermost ScrollView scrolls, no delegation to outer

  • Scrollbar: Scroll does not affect other ScrollView

  • Example: Vertical outer + Vertical inner

Mixed Scrolling (outer scrolls XY, inner one axis, or vice versa):
  • Shared axis: Web-style boundary delegation

  • Exclusive axes: Immediate delegation or inner-only scrolling

  • Wheel: Innermost ScrollView scrolls if it supports the axis

  • Example: XY outer + Horizontal inner

Web-Style Boundary Delegation

For parallel and shared-axis scrolling, ScrollView uses web-style delegation:

  • If a touch starts at the inner boundary and moves out, it delegates scrolling to the outer ScrollView right away.

  • If a touch starts at the inner boundary and moves in, only the inner ScrollView scrolls.

  • If a touch starts not at a boundary, only the inner ScrollView scrolls, even if the gesture later reaches a boundary. Delegation to the outer never occurs mid-gesture in this case.

  • A new touch starting at the boundary is required to delegate to the outer.

Disable this behavior by setting parallel_delegation to False.

Wheel Behavior in Nested ScrollViews

When the mouse scroll wheel or a trackpad is used, ScrollView always applies web-style delegation:

  • Only the innermost ScrollView under the pointer/cursor will handle the wheel event.

  • If that ScrollView cannot scroll further along the wheel axis, the event is not propagated to outer ScrollViews. This matches standard browser and OS behavior.

  • Outer ScrollViews never respond to wheel events unless the pointer is over their scrollbars or unless there are no deeper nested ScrollViews.

This prevents “scroll hijacking” and provides an intuitive nested scroll experience.

Examples:
  • In a vertical ScrollView containing a horizontal ScrollView, using the wheel over the horizontal ScrollView means only the vertical (outer) ScrollView scrolls, if its direction matches the wheel.

  • For two nested vertical ScrollViews, the innermost one under the pointer will scroll with the wheel until it cannot scroll further; wheel events are not delegated to the parent.

Wheel behavior is always active and is NOT affected by the parallel_delegation or delegate_to_outer properties. Those only control touch and touchpad gesture behavior.

Changed in version 3.0.0: The ScrollView widget now supports nesting to arbitrary levels and configurations.

class kivy.uix.scrollview.ScrollView(**kwargs)[source]

Bases: StencilView

ScrollView class. See module documentation for more information.

Events:
on_scroll_start

Dispatch when scrolling is detected.

on_scroll_move

Dispatched when scrolling continues. Fires continuously during scrolling.

on_scroll_stop

Dispatched when scrolling stops. Fires when velocity reaches zero and scroll position stabilizes for 3 consecutive frames.

Changed in version 3.0.0: on_scroll_start, on_scroll_move and on_scroll_stop events are now dispatched for nested and non-nested ScrollViews. The behavior has been updated. Previously these events mirrored the behavior of the on_touch_* methods. Now they fire when scrolling starts, continues and stops.

Changed in version 1.9.0: on_scroll_start, on_scroll_move and on_scroll_stop events are now dispatched when scrolling to handle nested ScrollViews.

Changed in version 1.7.0: auto_scroll, scroll_friction, scroll_moves, scroll_stoptime’ has been deprecated, use :attr:`effect_cls instead.

add_widget(widget, *args, **kwargs)[source]

Add a new widget as a child of this widget.

Parameters:
widget: Widget

Widget to add to our list of children.

index: int, defaults to 0

Index to insert the widget in the list. Notice that the default of 0 means the widget is inserted at the beginning of the list and will thus be drawn on top of other sibling widgets. For a full discussion of the index and widget hierarchy, please see the Widgets Programming Guide.

Added in version 1.0.5.

canvas: str, defaults to None

Canvas to add widget’s canvas to. Can be ‘before’, ‘after’ or None for the default canvas.

Added in version 1.9.0.

>>> from kivy.uix.button import Button
>>> from kivy.uix.slider import Slider
>>> root = Widget()
>>> root.add_widget(Button())
>>> slider = Slider()
>>> root.add_widget(slider)
always_overscroll

Make sure user can overscroll even if there is not enough content to require scrolling.

This is useful if you want to trigger some action on overscroll, but there is not always enough content to trigger it.

always_overscroll is a BooleanProperty and defaults to True.

Added in version 2.0.0.

The option was added and enabled by default, set to False to get the previous behavior of only allowing to overscroll when there is enough content to allow scrolling.

bar_color

Color of horizontal / vertical scroll bar, in RGBA format.

Added in version 1.2.0.

bar_color is a ColorProperty and defaults to [.7, .7, .7, .9].

Changed in version 2.0.0: Changed from ListProperty to ColorProperty.

bar_inactive_color

Color of horizontal / vertical scroll bar (in RGBA format), when no scroll is happening.

Added in version 1.9.0.

bar_inactive_color is a ColorProperty and defaults to [.7, .7, .7, .2].

Changed in version 2.0.0: Changed from ListProperty to ColorProperty.

bar_margin

Margin between the bottom / right side of the scrollview when drawing the horizontal / vertical scroll bar.

Added in version 1.2.0.

bar_margin is a NumericProperty, default to 0

bar_pos

Which side of the scroll view to place each of the bars on.

bar_pos is a ReferenceListProperty of (bar_pos_x, bar_pos_y)

bar_pos_x

Which side of the ScrollView the horizontal scroll bar should go on. Possible values are ‘top’ and ‘bottom’.

Added in version 1.8.0.

bar_pos_x is an OptionProperty, defaults to ‘bottom’.

bar_pos_y

Which side of the ScrollView the vertical scroll bar should go on. Possible values are ‘left’ and ‘right’.

Added in version 1.8.0.

bar_pos_y is an OptionProperty and defaults to ‘right’.

bar_width

Width of the horizontal / vertical scroll bar. The width is interpreted as a height for the horizontal bar.

Added in version 1.2.0.

bar_width is a NumericProperty and defaults to 2.

convert_distance_to_scroll(dx, dy)[source]

Convert a distance in pixels to a scroll distance, depending on the content size and the scrollview size.

The result will be a tuple of scroll distance that can be added to scroll_x and scroll_y

delegate_to_outer

Controls whether touch scroll gestures delegate to outer ScrollViews.

When True (default):
  • Orthogonal: Cross-axis gestures immediately delegate to outer (e.g., horizontal swipe in vertical-only ScrollView)

  • Parallel: At boundaries, delegates to outer (respects parallel_delegation)

  • Arbitrary depth: Continues searching up hierarchy for capable ScrollView

When False:
  • No delegation to outer ScrollViews

  • Only the directly touched ScrollView handles the gesture

NOTE: Mouse wheel events are NOT affected by this property. Wheel scrolling always uses web-style behavior: scroll the innermost ScrollView under cursor that can handle the direction.

Example use cases:
  • Set False to lock touch scrolling to a specific nested level

  • Set False to prevent inner touch scroll from affecting outer scroll

delegate_to_outer is a BooleanProperty and defaults to True.

Added in version 3.0.0.

do_scroll

Allow scroll on X or Y axis.

do_scroll is a AliasProperty of (do_scroll_x + do_scroll_y)

do_scroll_x

Allow scroll on X axis.

do_scroll_x is a BooleanProperty and defaults to True.

do_scroll_y

Allow scroll on Y axis.

do_scroll_y is a BooleanProperty and defaults to True.

effect_cls

Class effect to instantiate for X and Y axis.

Added in version 1.7.0.

effect_cls is an ObjectProperty and defaults to DampedScrollEffect.

Changed in version 1.8.0: If you set a string, the Factory will be used to resolve the class.

effect_x

Effect to apply for the X axis. If None is set, an instance of effect_cls will be created.

Added in version 1.7.0.

effect_x is an ObjectProperty and defaults to None.

effect_y

Effect to apply for the Y axis. If None is set, an instance of effect_cls will be created.

Added in version 1.7.0.

effect_y is an ObjectProperty and defaults to None, read-only.

hbar

Return a tuple of (position, size) of the horizontal scrolling bar.

Added in version 1.2.0.

The position and size are normalized between 0-1, and represent a proportion of the current scrollview height. This property is used internally for drawing the little horizontal bar when you’re scrolling.

hbar is a AliasProperty, readonly.

on_motion(etype, me)[source]

Called when a motion event is received.

Parameters:
etype: str

Event type, one of “begin”, “update” or “end”

me: MotionEvent

Received motion event

Returns:

bool True to stop event dispatching

Added in version 2.1.0.

Changed in version 3.0.0: Removed “Experimental” warning.

on_scroll_move()[source]

Event fired when the scroll position changes.

This event is dispatched whenever the scroll_x or scroll_y properties change during an active scroll gesture. It provides a unified way to track scrolling regardless of input method. (touch, mouse wheel, scrollbar, or programmatic scroll_x/scroll_y changes).

This event fires continuously during scrolling and is useful for implementing scroll-based animations, progress indicators, or parallax effects.

Changed in version 3.0.0: Removed touch parameter. Use on_touch_down/move/up for touch-specific handling. Now fires for all scroll_x/scroll_y changes including programmatic updates.

on_scroll_start()[source]

Event fired when a scroll gesture starts.

This event is dispatched when scrolling begins, regardless of the input method (touch, mouse wheel, or programmatic). It fires once per scroll gesture when the ScrollView determines that scrolling should commence.

For touch/content scrolling, this fires after the touch has moved beyond the scroll_distance threshold. For scrollbar interactions, it fires when the scrollbar is initially grabbed. For mouse wheel scrolling, it fires on the first scroll wheel event.

Changed in version 3.0.0: Removed touch parameter. Use on_touch_down/move/up for touch-specific handling.

on_scroll_stop()[source]

Event fired when scrolling motion stops.

This event is dispatched when the scrolling motion has completely stopped. Fires when both velocity reaches zero and scroll position stabilizes for 3 consecutive frames.

This event is useful for triggering actions after scrolling completes, such as loading more content, snapping to grid positions, or updating UI state.

Changed in version 3.0.0: Removed touch parameter. Use on_touch_down/move/up for touch-specific handling.

on_touch_down(touch)[source]

Receive a touch down event.

Parameters:
touch: MotionEvent class

Touch received. The touch is in parent coordinates. See relativelayout for a discussion on coordinate systems.

Returns:

bool If True, the dispatching of the touch event will stop. If False, the event will continue to be dispatched to the rest of the widget tree.

on_touch_move(touch)[source]

Receive a touch move event. The touch is in parent coordinates.

See on_touch_down() for more information.

on_touch_up(touch)[source]

Receive a touch up event. The touch is in parent coordinates.

See on_touch_down() for more information.

parallel_delegation

Controls boundary delegation behavior for parallel nested ScrollViews.

When True (default, web-style):
  • Touch starting at inner boundary, moving away → delegates to outer

  • Touch starting not at boundary → scrolls inner only, never delegates

When False:
  • No delegation, only touched ScrollView scrolls

parallel_delegation is a BooleanProperty and defaults to True.

Added in version 3.0.0.

remove_widget(widget, *args, **kwargs)[source]

Remove a widget from the children of this widget.

Parameters:
widget: Widget

Widget to remove from our children list.

>>> from kivy.uix.button import Button
>>> root = Widget()
>>> button = Button()
>>> root.add_widget(button)
>>> root.remove_widget(button)
scroll_distance

Distance to move before scrolling the ScrollView, in pixels. As soon as the distance has been traveled, the ScrollView will start to scroll, and no touch event will go to children. It is advisable that you base this value on the dpi of your target device’s screen.

scroll_distance is a NumericProperty and defaults to 20 (pixels), according to the default value in user configuration.

scroll_timeout

Timeout allowed to trigger the scroll_distance, in milliseconds. If the user has not moved scroll_distance within the timeout, the scrolling will be disabled, and the touch event will go to the children.

scroll_timeout is a NumericProperty and defaults to 55 (milliseconds) according to the default value in user configuration.

Changed in version 1.5.0: Default value changed from 250 to 55.

scroll_to(widget, padding=10, animate=True)[source]

Scrolls the viewport to ensure that the given widget is visible, optionally with padding and animation. If animate is True (the default), then the default animation parameters will be used. Otherwise, it should be a dict containing arguments to pass to Animation constructor.

Added in version 1.9.1.

scroll_type

Sets the type of scrolling to use for the content of the scrollview. Available options are: [‘content’], [‘bars’], [‘bars’, ‘content’].

[‘content’]

Content is scrolled by dragging or swiping the content directly.

[‘bars’]

Content is scrolled by dragging or swiping the scroll bars.

[‘bars’, ‘content’]

Content is scrolled by either of the above methods.

Added in version 1.8.0.

scroll_type is an OptionProperty and defaults to [‘content’].

scroll_wheel_distance

Distance to move when scrolling with a mouse wheel. It is advisable that you base this value on the dpi of your target device’s screen.

Added in version 1.8.0.

scroll_wheel_distance is a NumericProperty , defaults to 20 pixels.

scroll_x

X scrolling value, between 0 and 1. If 0, the content’s left side will touch the left side of the ScrollView. If 1, the content’s right side will touch the right side.

This property is controlled by ScrollView only if do_scroll_x is True.

scroll_x is a NumericProperty and defaults to 0.

scroll_y

Y scrolling value, between 0 and 1. If 0, the content’s bottom side will touch the bottom side of the ScrollView. If 1, the content’s top side will touch the top side.

This property is controlled by ScrollView only if do_scroll_y is True.

scroll_y is a NumericProperty and defaults to 1.

slow_device_support

Enable slow device support for scroll gesture detection.

On very slow devices, at least 3 frames are needed to accumulate velocity data for scroll effects to work properly. When enabled, after the scroll timeout expires, the gesture handoff will be delayed until at least 3 frames have rendered, ensuring sufficient velocity data accumulation.

This addresses issues #1464 and #1499 for low-performance devices. Disable this on modern hardware to improve touch responsiveness.

slow_device_support is a BooleanProperty and defaults to False.

Added in version 3.0.0.

smooth_scroll_end

Whether smooth scroll end should be used when scrolling with the mouse-wheel and the factor of transforming the scroll distance to velocity. This option also enables velocity addition meaning if you scroll more, you will scroll faster and further. The recommended value is 10. The velocity is calculated as scroll_wheel_distance * smooth_scroll_end.

Added in version 1.11.0.

smooth_scroll_end is a NumericProperty and defaults to None.

to_local(x, y, **k)[source]

Transform parent coordinates to local (current widget) coordinates.

See relativelayout for details on the coordinate systems.

Parameters:
relative: bool, defaults to False

Change to True if you want to translate coordinates to relative widget coordinates.

to_parent(x, y, **k)[source]

Transform local (current widget) coordinates to parent coordinates.

See relativelayout for details on the coordinate systems.

Parameters:
relative: bool, defaults to False

Change to True if you want to translate relative positions from a widget to its parent coordinates.

update_from_scroll(*largs)[source]

Force the reposition of the content, according to current value of scroll_x and scroll_y.

This method is automatically called when one of the scroll_x, scroll_y, pos or size properties change, or if the size of the content changes.

vbar

Return a tuple of (position, size) of the vertical scrolling bar.

Added in version 1.2.0.

The position and size are normalized between 0-1, and represent a proportion of the current scrollview height. This property is used internally for drawing the little vertical bar when you’re scrolling.

vbar is a AliasProperty, readonly.

viewport_size

(internal) Size of the internal viewport. This is the size of your only child in the scrollview.