Styling components
Before writing any style, check whether the component already has the look you want. Most components in
pyzed.ui come in variants, tints and sizes that follow the theme. When none fits,
style() changes anything, like CSS.
flowchart LR
T["Theme<br/>colors for everything"] --> V["Variant · tint · size<br/>ui.button(variant='outline')"]
V --> S["style()<br/>.style(radius=0)"]
Each step only overrides what it sets: the theme gives the colors, the variant picks which of them a component
uses, and style() has the last word.
Variants
Section titled “Variants”A variant is a ready-made look of the same component.
Buttons
Section titled “Buttons”ui.button("Save", save, variant="solid") # filled with the accent: the main actionui.button("Cancel", cancel) # "filled" (default): a neutral filled buttonui.button("Details", details, variant="outline") # transparent with a borderui.button("More", more, variant="ghost") # no background until hoveredui.button("Skip", skip, variant="subtle") # like ghost, with muted textui.button("Archive", archive, variant="tinted") # a translucent accent| Variant | Background | Use it for |
|---|---|---|
filled (default) |
element |
Most buttons. |
solid |
the accent (or the tint) | The main action of a screen, one per area. |
tinted |
a translucent accent (or tint) | Secondary actions that should stand out a bit. |
outline |
none, with a border |
Toolbars, secondary actions on busy surfaces. |
ghost |
none until hovered (ghost_hover) |
Toolbars, menus, icon buttons. |
subtle |
like ghost, with text_muted |
Low-priority actions. |

Badges
Section titled “Badges”ui.badge("New") # "soft" (default): translucent backgroundui.badge("Paid", tint="success", variant="solid")ui.badge("Failed", tint="error", variant="outline")ui.icon_button takes variant too ("ghost" by default), and many components have their own options, such as
borderless=True and mono=True on ui.input. Each component’s page in the Library shows its
variants.
A tint recolors a component with one of the status tokens: "accent",
"error", "warning", "success", "info" (and "hint" for callouts):
ui.button("Delete", delete, variant="solid", tint="error")ui.button("Delete", delete, variant="error") # shortcut: a tinted error buttonui.callout("Saved", "Everything is up to date.", tint="success")ui.progress(0.4, tint="warning")ui.spinner(tint="info")ui.count_badge(3, tint="error")Since tints are tokens, they follow the theme: the same red button is a softer red in a light theme.
ui.button("Tiny", on_press, size="xs") # 18 px highui.button("Small", on_press, size="sm") # 22 pxui.button("Normal", on_press) # "md": 28 pxui.button("Large", on_press, size="lg")ui.input(self.name, self.set_name, size="lg")ui.select(options, self.choice, self.pick, size="sm")style() on any component
Section titled “style() on any component”Every widget, including every pyzed.ui component, has a style() method with CSS-like properties
(the full list). It is applied on top of the component’s own look:
ui.button("Square", on_press).style(radius=0, border=(2, "accent"))ui.card(body, title="Usage").style(shadow=("#0006", (0, 8), 24), radius=16)ui.label("Total").style(size=20, weight="bold", color="success")ui.button also takes the low-level colors of the button directly (bg, hover_bg, pressed_bg, color), for
a fully custom button that still behaves like one:
ui.button("Buy", buy, bg="#16a34a", hover_bg="#15803d", pressed_bg="#166534", color="#ffffff")Reuse a look: named styles
Section titled “Reuse a look: named styles”Give a style a name once and use it anywhere. Named styles are the “CSS classes” of Pyzed:
pz.define_style("card", background="surface", border=(1, "border_variant"), radius=12, padding=16)pz.define_style("danger", color="error", weight="semibold")
pz.column([...]).style("card")ui.label("Payment failed").style("danger")pz.column([...]).style("card", shadow=("#0005", (0, 4), 12)) # a name plus extra propertiesA pz.Style object does the same without a global name, and styles combine with | (the right side wins):
CARD = pz.Style(background="surface", radius=12, padding=16)RAISED = CARD | pz.Style(shadow=("#0006", (0, 8), 24))A different theme for one component
Section titled “A different theme for one component”Every pyzed.ui component takes theme=, to draw just that component with another theme, and a with theme:
block changes the theme of everything built inside it:
ui.button("Light", on_press, theme=pz.themes.ONE_LIGHT)
with pz.themes.ONE_DARK.with_accent("#f97316"): warning_area = pz.column([ui.button("Go", go, variant="solid"), ui.progress(0.3)])Your own components
Section titled “Your own components”A component of your own should take its colors from the theme too, so it fits every
theme without changes. Use token names, or read the theme with pz.theme.current() in render():
class Tag(pz.Component): text: str = "" tint: str = "accent"
def render(self): t = pz.theme.current() return pz.text(self.text, size=12).style( color=self.tint, background=pz.Paint(self.tint, opacity=0.15), radius=t.radius_sm, padding=(2, 8), )
Tag(text="beta", tint="warning")Tag(text="new", style={"weight": "bold"}) # every component also accepts style=Components made in the designer’s component view follow the same rules; see Styling forms in the designer.