Skip to content

Animatable properties

An animation changes one or more properties of a widget. The same names work everywhere: in animate(), transition(), pz.Animation keyframes and timeline tracks.

Twelve cards, each one moving one property back and forth: opacity, x, y, scale, rotate, blur, background, border color, radius, glow, width and font size

Property Values Notes
opacity 0 (invisible) to 1. Fades the widget and everything inside it.
x, y Pixels, or "50%" of the widget’s own size. Moves it without moving its neighbours.
scale A number: 1 is its size, 0.5 half, 1.2 a fifth bigger. Around its center.
rotate Degrees clockwise, or "0.25turn", "1.5rad", "90deg". Around its center.
blur Pixels. Blurs the widget and everything inside it.
background, border_color, color, glow_color "#rrggbb", "#rrggbbaa" or a theme token ("accent", "elevated"…). Colors blend smoothly. color changes the text inside.
radius, border_width, glow Pixels. glow is the size of the halo around the box.
width, height Pixels. Change the layout: the widgets around it move.
padding Pixels. Inside a container or button (all four sides follow); elsewhere it adds space around. Changes the layout.
font_size Pixels. Every text inside. Changes the layout.

pz.animation.PROPERTIES lists them in code.

Without a preset, the values you pass are the animation. What they mean depends on the trigger:

Trigger The widget…
mount starts from those values and settles on its own look: animate(opacity=0, y=12) appears from below.
hover, press, focus, active goes to those values while the condition holds, and back after.
click goes to those values and back, on every click.
pz.text("Hi").animate(opacity=0, y=12, duration=250) # appears from below
card.animate(on="hover", scale=1.03, background="elevated") # grows and lightens on hover
button.animate(on="press", scale=0.96, duration=90) # sinks in while pressed
icon.animate(on="click", rotate=360, duration=500) # a full turn on each click

The default duration is 300 ms for mount and click, and 150 ms for hover, press and focus.

A property you don’t give at the start or the end of an animation goes from or to the widget’s own value. So an animation can change the background of any button without knowing its color:

flash = pz.Animation({"50%": {"background": "#fbbf24"}}, duration=400) # to yellow and back

That’s also why a mount animation can end on “the widget’s own look”: the last frame leaves the property out.

icon.animate("spin") # a loading spinner
card.animate(on="hover", rotate=-3, scale=1.02) # tilts on hover
sidebar.transition(width=240 if self.open else 56, duration=200) # the content beside it reflows
title.transition(font_size=28 if self.big else 16)
status.animate(on="active", active=self.online, background="#14532d", border_color="#22c55e")