The KV Language
KV is the declarative language that describes a Kivy UI: widget classes, the rules that define their internal tree, and the property assignments and event bindings that make them behave. It looks like an indentation-based configuration format (it is parsed by a grammar, not by YAML or JSON), and its power is that the same notation expresses both "a class and its layout" and "an instance of a widget with these property values." This chapter is the reference for the syntax - the two kinds of blocks, the rule, property assignment, id and references, and the @ operators for resources - so the later chapters can use the notation without re-explaining it.
The Two Kinds of Blocks
# Block 1: a "class definition" - Name: (no angle brackets)
# Declares a custom widget class and its children.
# The children listed here are ADDED to the class's own content.
MyPanel:
Button:
text: "child of MyPanel"
# Block 2: a "rule" - <Name>: (angle brackets)
# Defines the widget tree that the class ITSELF is made of.
<MyPanel>:
BoxLayout:
orientation: "horizontal"
Label:
text: "inside MyPanel"
The distinction is the single most-confused point in KV, so it is worth being precise. A Name: block (no brackets) is read as "create an instance of Name, and here are its children and property overrides" - it is an instance declaration with a class name as the header. A <Name>: block (brackets) is the rule for the class - the widget tree that a Name widget contains when it is created. A class usually has exactly one rule (<MyPanel>:) that defines its body, and can be instantiated many times via Name: blocks (in the app's root rule, or inside another class). In the first-app chapter, CounterScreen: was the instance block and <CounterScreen>: was the rule - the same two-part pattern.
Property Assignment and References
<MyForm>:
BoxLayout:
orientation: "vertical"
title: lbl
TextInput:
id: name_field
text: "Ada"
hint_text: "Name"
Label:
id: lbl
# reference the sibling's property:
text: "Hello " + name_field.text
# a plain value, a string, or an expression referencing other ids
Inside a rule, a property line (text: "...") sets the property on the widget defined by the enclosing block. The value can be a literal, a number, a boolean, or an expression - and expressions can reference other widgets in the same rule by their id (name_field.text). That reference is the KV idiom for "this label shows what the field contains," and it is one-directional: it is evaluated when the rule is applied, not a live binding (the live, reactive version is the << operator or a property event in Python - the properties chapter covers it). The id: property must be unique within its rule, and it is the name Python uses (via the App's root_widget children or an ObjectProperty) to reach the widget.
Event Bindings in KV
<MyForm>:
BoxLayout:
orientation: "vertical"
Button:
text: "Save"
# call a method on the enclosing widget (root of this rule)
on_press: root.save(self)
Button:
text: "Back"
# call a method on the App instance
on_press: app.do_back()
Button:
text: "Reset"
# chain: reset the field, then the label
on_press: self.parent.name_field.text = ''
An on_<event>: line binds an event to a Python expression - usually a method call. The names available in that expression are the KV reserved names: root (the widget the rule defines - the target of the handler), self (the widget the on_ line is on - the button), app (the App instance), and any id in the rule. The two most common shapes are on_press: root.method(self) - call a method on the screen, passing the button - and on_press: app.method() - call up to the app. The expression is evaluated in Python at event time, so it can be a full statement chain, though a single method call is the readable norm.
Resource and Template Operators
MyScreen:
BoxLayout:
Image:
# @ is the "load a resource" operator
source: "at data/logo.png"
Label:
# @@ loads from the app's data directory specifically
font: "data/DejaVuSans.ttf" 42
# a template: reuse a widget fragment with a name
<RowItem@RowTemplate>:
BoxLayout:
orientation: "horizontal"
Label:
text: self.name
Button:
text: "Edit"
The @ prefix marks a resource reference - source: "at data/logo.png" loads the image file (the at keyword is the path form; a bare quoted path is treated as a URL-ish source). The <Name@Template> form defines a template: a reusable fragment that other rules can instantiate as Name@Template:, parameterized by the properties the template reads. Templates are KV's answer to "this widget cluster appears in five places" - define the fragment once, reference it where needed. For a small app, inline repetition is fine; for a real UI, templates and a small set of custom classes are the maintainable path.
Pitfalls
- Confusing the block kinds. A
Name:block instantiates; a<Name>:block defines the class's body. Writing the rule without brackets makes it an instance, and the class is left empty - the "my custom widget shows nothing" bug. - Ids are per-rule. An
idis only visible inside its own rule; reaching a widget in another rule goes through a property orApp-level lookup, not a bare id. - Expression references are not live.
text: other.textcopies the value at build time; for a live link use a binding (text:<< other.text) or a Python property event. - Indentation is structure. KV is indentation-based; a mis-indented line changes which widget a property belongs to, and the error is often a silent wrong-parent rather than a syntax failure.
Summary
KV has two block kinds - a Name: instance declaration (children and overrides) and a <Name>: rule (the class's own widget tree) - and the confusion between them is the most common KV bug. Property lines set values, can be expressions, and can reference sibling widgets by id; on_<event>: lines bind events to Python expressions where root, self, app, and rule ids are in scope. The @ operators load resources and templates reuse fragments. Keep the rules straight - brackets define, no brackets instantiate, ids are per-rule, references are not live bindings - and the KV file becomes a precise, readable description of the UI that the Python side reacts to. The next chapter surveys the widgets those rules are made of.