Style properties are passed via the style prop as a dict (or list of dicts) to any element function. PythonNative also provides a StyleSheet utility for creating reusable styles and a theming system via context.
Pass a style dict to components:
pn.Text("Hello", style={"color": "#FF3366", "font_size": 24, "bold": True})
pn.Button("Tap", style={"background_color": "#FF1E88E5", "color": "#FFFFFF"})
pn.Column(pn.Text("Content"), style={"background_color": "#FFF5F5F5"})Create reusable named styles with StyleSheet.create():
import pythonnative as pn
styles = pn.StyleSheet.create(
title={"font_size": 28, "bold": True, "color": "#333"},
subtitle={"font_size": 14, "color": "#666"},
container={"padding": 16, "spacing": 12, "align_items": "stretch"},
)
pn.Text("Welcome", style=styles["title"])
pn.Column(
pn.Text("Subtitle", style=styles["subtitle"]),
style=styles["container"],
)Merge multiple style dicts with StyleSheet.compose():
base = {"font_size": 16, "color": "#000"}
highlight = {"color": "#FF0000", "bold": True}
merged = pn.StyleSheet.compose(base, highlight)
# Result: {"font_size": 16, "color": "#FF0000", "bold": True}You can also pass a list of dicts to style. They are merged left-to-right:
pn.Text("Highlighted", style=[base, highlight])Flatten a style or list of styles into a single dict:
pn.StyleSheet.flatten([base, highlight])
pn.StyleSheet.flatten(None) # returns {}Pass hex strings (#RRGGBB or #AARRGGBB) to color properties inside style:
pn.Text("Hello", style={"color": "#FF3366"})
pn.Button("Tap", style={"background_color": "#FF1E88E5", "color": "#FFFFFF"})Text and Button accept font_size, color, bold, and text_align inside style:
pn.Text("Title", style={"font_size": 24, "bold": True, "text_align": "center"})
pn.Text("Subtitle", style={"font_size": 14, "color": "#666666"})PythonNative uses a flexbox-inspired layout model. View is the universal flex container, and Column/Row are convenience wrappers.
These go in the style dict of View, Column, or Row:
flex_direction—"column"(default),"row","column_reverse","row_reverse"(only forView;Column/Rowhave fixed directions)justify_content— main-axis distribution:"flex_start","center","flex_end","space_between","space_around","space_evenly"align_items— cross-axis alignment:"stretch","flex_start","center","flex_end"overflow—"visible"(default),"hidden"spacing— gap between children (dp / pt)padding— inner spacing (int for all sides, or dict)
All components accept these in style:
width,height— fixed dimensions in dp (Android) / pt (iOS)flex— flex grow factor (shorthand forflex_grow)flex_grow— how much a child should grow to fill available spaceflex_shrink— how much a child should shrink when space is tightmargin— outer spacing (int for all sides, or dict)min_width,min_height— minimum size constraintsmax_width,max_height— maximum size constraintsalign_self— override parent alignment:"flex_start","center","flex_end","stretch"
Centering content:
pn.View(
pn.Text("Centered!"),
style={"flex": 1, "justify_content": "center", "align_items": "center"},
)Horizontal row with spacer:
pn.Row(
pn.Text("Left"),
pn.Spacer(flex=1),
pn.Text("Right"),
style={"padding": 16, "align_items": "center"},
)Child with flex grow:
pn.Column(
pn.Text("Header", style={"font_size": 20, "bold": True}),
pn.View(pn.Text("Content area"), style={"flex": 1}),
pn.Text("Footer"),
style={"flex": 1, "spacing": 8},
)Horizontal button bar:
pn.Row(
pn.Button("Cancel", style={"flex": 1}),
pn.Button("OK", style={"flex": 1, "background_color": "#007AFF", "color": "#FFF"}),
style={"spacing": 8, "padding": 16},
)Column (vertical) and Row (horizontal) are convenience wrappers for View:
pn.Column(
pn.Text("Username"),
pn.TextInput(placeholder="Enter username"),
pn.Text("Password"),
pn.TextInput(placeholder="Enter password", secure=True),
pn.Button("Login", on_click=handle_login),
style={"spacing": 8, "padding": 16, "align_items": "stretch"},
)Column and Row support align_items and justify_content inside style:
align_items— cross-axis alignment:"stretch","flex_start","center","flex_end","leading","trailing"justify_content— main-axis distribution:"flex_start","center","flex_end","space_between","space_around","space_evenly"
pn.Row(
pn.Text("Left"),
pn.Spacer(flex=1),
pn.Text("Right"),
style={"align_items": "center", "justify_content": "space_between", "padding": 16},
)spacingsets the gap between children in dp (Android) / points (iOS).
padding: 16— all sidespadding: {"horizontal": 12, "vertical": 8}— per axispadding: {"left": 8, "top": 16, "right": 8, "bottom": 16}— per side
PythonNative includes a built-in theme context with light and dark themes:
import pythonnative as pn
from pythonnative.style import DEFAULT_DARK_THEME
@pn.component
def ThemedText(text: str = ""):
theme = pn.use_context(pn.ThemeContext)
return pn.Text(text, style={"color": theme["text_color"], "font_size": theme["font_size"]})
@pn.component
def DarkPage():
return pn.Provider(pn.ThemeContext, DEFAULT_DARK_THEME,
pn.Column(
ThemedText(text="Dark mode!"),
style={"spacing": 8},
)
)Both light and dark themes include:
primary_color,secondary_color— accent colorsbackground_color,surface_color— background colorstext_color,text_secondary_color— text colorserror_color,success_color,warning_color— semantic colorsfont_size,font_size_small,font_size_large,font_size_title— typographyspacing,spacing_large— layout spacingborder_radius— corner rounding
Wrap content in a ScrollView:
pn.ScrollView(
pn.Column(
pn.Text("Item 1"),
pn.Text("Item 2"),
# ... many items
style={"spacing": 8},
)
)