Flet is a rich User Interface framework to quickly build interactive web, desktop and mobile apps in Python without prior knowledge of web technologies.
—
This document covers Flet's comprehensive theming and styling system, including themes, colors, typography, and visual effects for creating beautiful, consistent user interfaces.
import flet as ftclass Theme(Control):
"""Application theme configuration."""
def __init__(
self,
color_scheme_seed: str = None,
color_scheme: ColorScheme = None,
text_theme: TextTheme = None,
primary_swatch: str = None,
primary_color: str = None,
primary_color_dark: str = None,
primary_color_light: str = None,
accent_color: str = None,
canvas_color: str = None,
card_color: str = None,
dialog_background_color: str = None,
disabled_color: str = None,
divider_color: str = None,
focus_color: str = None,
highlight_color: str = None,
hint_color: str = None,
hover_color: str = None,
indicator_color: str = None,
secondary_header_color: str = None,
selected_row_color: str = None,
splash_color: str = None,
unselected_widget_color: str = None,
font_family: str = None,
use_material3: bool = True,
visual_density: VisualDensity = None,
page_transitions: PageTransitionsTheme = None,
scrollbar_theme: ScrollbarTheme = None,
tabs_theme: TabsTheme = None,
tooltip_theme: TooltipTheme = None,
banner_theme: BannerTheme = None,
bottom_app_bar_theme: BottomAppBarTheme = None,
bottom_navigation_bar_theme: BottomNavigationBarTheme = None,
bottom_sheet_theme: BottomSheetTheme = None,
button_theme: ButtonTheme = None,
card_theme: CardTheme = None,
checkbox_theme: CheckboxTheme = None,
chip_theme: ChipTheme = None,
data_table_theme: DataTableTheme = None,
dialog_theme: DialogTheme = None,
divider_theme: DividerTheme = None,
elevated_button_theme: ElevatedButtonTheme = None,
floating_action_button_theme: FloatingActionButtonTheme = None,
list_tile_theme: ListTileTheme = None,
navigation_bar_theme: NavigationBarTheme = None,
navigation_rail_theme: NavigationRailTheme = None,
outlined_button_theme: OutlinedButtonTheme = None,
popup_menu_theme: PopupMenuTheme = None,
progress_indicator_theme: ProgressIndicatorTheme = None,
radio_theme: RadioTheme = None,
slider_theme: SliderTheme = None,
snack_bar_theme: SnackBarTheme = None,
switch_theme: SwitchTheme = None,
text_button_theme: TextButtonTheme = None,
**kwargs
)Key Parameters:
color_scheme_seed (str, optional): Seed color for Material 3 color scheme generationcolor_scheme (ColorScheme, optional): Custom color schemetext_theme (TextTheme, optional): Typography themeuse_material3 (bool, optional): Use Material Design 3 (default: True)font_family (str, optional): Default font familyExample:
page.theme = ft.Theme(
color_scheme_seed=ft.colors.GREEN,
use_material3=True
)
# Or with custom color scheme
page.theme = ft.Theme(
color_scheme=ft.ColorScheme(
primary=ft.colors.BLUE,
secondary=ft.colors.GREEN,
background=ft.colors.WHITE,
surface=ft.colors.GREY_50
)
)
page.update()class ColorScheme(Control):
"""Color scheme definition for theming."""
def __init__(
self,
brightness: Brightness = None,
primary: str = None,
on_primary: str = None,
primary_container: str = None,
on_primary_container: str = None,
primary_fixed: str = None,
primary_fixed_dim: str = None,
on_primary_fixed: str = None,
on_primary_fixed_variant: str = None,
secondary: str = None,
on_secondary: str = None,
secondary_container: str = None,
on_secondary_container: str = None,
secondary_fixed: str = None,
secondary_fixed_dim: str = None,
on_secondary_fixed: str = None,
on_secondary_fixed_variant: str = None,
tertiary: str = None,
on_tertiary: str = None,
tertiary_container: str = None,
on_tertiary_container: str = None,
tertiary_fixed: str = None,
tertiary_fixed_dim: str = None,
on_tertiary_fixed: str = None,
on_tertiary_fixed_variant: str = None,
error: str = None,
on_error: str = None,
error_container: str = None,
on_error_container: str = None,
surface_dim: str = None,
surface: str = None,
surface_bright: str = None,
surface_container_lowest: str = None,
surface_container_low: str = None,
surface_container: str = None,
surface_container_high: str = None,
surface_container_highest: str = None,
on_surface: str = None,
on_surface_variant: str = None,
outline: str = None,
outline_variant: str = None,
shadow: str = None,
scrim: str = None,
inverse_surface: str = None,
on_inverse_surface: str = None,
inverse_primary: str = None,
surface_tint: str = None,
**kwargs
)Key Color Roles:
primary (str, optional): Primary brand colorsecondary (str, optional): Secondary accent colortertiary (str, optional): Tertiary accent colorerror (str, optional): Error state colorsurface (str, optional): Background surface coloron_primary (str, optional): Text/icon color on primary backgroundoutline (str, optional): Border and outline colorclass TextTheme(Control):
"""Typography theme configuration."""
def __init__(
self,
display_large: TextStyle = None,
display_medium: TextStyle = None,
display_small: TextStyle = None,
headline_large: TextStyle = None,
headline_medium: TextStyle = None,
headline_small: TextStyle = None,
title_large: TextStyle = None,
title_medium: TextStyle = None,
title_small: TextStyle = None,
label_large: TextStyle = None,
label_medium: TextStyle = None,
label_small: TextStyle = None,
body_large: TextStyle = None,
body_medium: TextStyle = None,
body_small: TextStyle = None,
**kwargs
)Typography Scale:
display_* - Largest text, for hero sectionsheadline_* - High-emphasis headerstitle_* - Medium-emphasis headersbody_* - Body text contentlabel_* - Small text for labels and captionsclass ThemeMode(Enum):
"""Theme mode options."""
SYSTEM = "system" # Follow system theme
LIGHT = "light" # Light theme
DARK = "dark" # Dark themeExample:
page.theme_mode = ft.ThemeMode.DARK
page.update()class Colors:
"""Material Design color constants."""
# Primary colors
RED = "red"
PINK = "pink"
PURPLE = "purple"
DEEP_PURPLE = "deeppurple"
INDIGO = "indigo"
BLUE = "blue"
LIGHT_BLUE = "lightblue"
CYAN = "cyan"
TEAL = "teal"
GREEN = "green"
LIGHT_GREEN = "lightgreen"
LIME = "lime"
YELLOW = "yellow"
AMBER = "amber"
ORANGE = "orange"
DEEP_ORANGE = "deeporange"
BROWN = "brown"
GREY = "grey"
BLUE_GREY = "bluegrey"
# Shades (50-900)
RED_50 = "red50"
RED_100 = "red100"
# ... continuing through RED_900
# Surface colors
BACKGROUND = "background"
SURFACE = "surface"
SURFACE_VARIANT = "surfacevariant"
ON_BACKGROUND = "onbackground"
ON_SURFACE = "onsurface"
ON_SURFACE_VARIANT = "onsurfacevariant"
# Semantic colors
PRIMARY = "primary"
ON_PRIMARY = "onprimary"
PRIMARY_CONTAINER = "primarycontainer"
ON_PRIMARY_CONTAINER = "onprimarycontainer"
SECONDARY = "secondary"
ON_SECONDARY = "onsecondary"
ERROR = "error"
ON_ERROR = "onerror"
# Special colors
TRANSPARENT = "transparent"
WHITE = "white"
BLACK = "black"class CupertinoColors:
"""iOS-style color constants."""
SYSTEM_BLUE = "systemblue"
SYSTEM_GREEN = "systemgreen"
SYSTEM_INDIGO = "systemindigo"
SYSTEM_ORANGE = "systemorange"
SYSTEM_PINK = "systempink"
SYSTEM_PURPLE = "systempurple"
SYSTEM_RED = "systemred"
SYSTEM_TEAL = "systemteal"
SYSTEM_YELLOW = "systemyellow"
SYSTEM_GREY = "systemgrey"
SYSTEM_GREY2 = "systemgrey2"
SYSTEM_GREY3 = "systemgrey3"
SYSTEM_GREY4 = "systemgrey4"
SYSTEM_GREY5 = "systemgrey5"
SYSTEM_GREY6 = "systemgrey6"
# Background colors
SYSTEM_BACKGROUND = "systembackground"
SECONDARY_SYSTEM_BACKGROUND = "secondarysystembackground"
TERTIARY_SYSTEM_BACKGROUND = "tertiarysystembackground"
# Label colors
LABEL = "label"
SECONDARY_LABEL = "secondarylabel"
TERTIARY_LABEL = "tertiarylabel"
QUATERNARY_LABEL = "quaternarylabel"def colors.with_opacity(opacity: float, color: str) -> str:
"""Create color with specified opacity."""
# Returns color with alpha channel
# Usage examples:
semi_transparent_blue = ft.colors.with_opacity(0.5, ft.colors.BLUE)
fade_red = ft.colors.with_opacity(0.3, ft.colors.RED)class TextStyle(Control):
"""Text styling configuration."""
def __init__(
self,
size: float = None,
weight: FontWeight = None,
italic: bool = None,
color: str = None,
bgcolor: str = None,
decoration: TextDecoration = None,
decoration_color: str = None,
decoration_style: TextDecorationStyle = None,
decoration_thickness: float = None,
font_family: str = None,
font_family_fallback: List[str] = None,
letter_spacing: float = None,
word_spacing: float = None,
height: float = None,
baseline: TextBaseline = None,
foreground: Paint = None,
background: Paint = None,
shadow: List[BoxShadow] = None,
**kwargs
)Parameters:
size (float, optional): Font size in logical pixelsweight (FontWeight, optional): Font weight (NORMAL, BOLD, W100-W900)italic (bool, optional): Italic stylecolor (str, optional): Text colordecoration (TextDecoration, optional): Text decoration (UNDERLINE, OVERLINE, LINE_THROUGH)font_family (str, optional): Font family nameletter_spacing (float, optional): Character spacingshadow (List[BoxShadow], optional): Text shadowsExample:
ft.Text(
"Styled Text",
style=ft.TextStyle(
size=24,
weight=ft.FontWeight.BOLD,
color=ft.colors.BLUE,
decoration=ft.TextDecoration.UNDERLINE,
font_family="Arial",
letter_spacing=2
)
)class ButtonStyle(Control):
"""Button styling configuration."""
def __init__(
self,
color: ControlStateProperty = None,
bgcolor: ControlStateProperty = None,
overlay_color: ControlStateProperty = None,
shadow_color: ControlStateProperty = None,
surface_tint_color: ControlStateProperty = None,
elevation: ControlStateProperty = None,
animation_duration: int = None,
padding: ControlStateProperty = None,
side: ControlStateProperty = None,
shape: ControlStateProperty = None,
text_style: ControlStateProperty = None,
icon_color: ControlStateProperty = None,
icon_size: ControlStateProperty = None,
**kwargs
)Parameters:
Example:
ft.ElevatedButton(
"Custom Button",
style=ft.ButtonStyle(
color=ft.colors.WHITE,
bgcolor=ft.colors.BLUE,
elevation=8,
padding=ft.padding.symmetric(horizontal=20, vertical=10),
shape=ft.RoundedRectangleBorder(radius=20)
)
)class BorderSide(Control):
"""Border side styling."""
def __init__(
self,
width: float = None,
color: str = None,
stroke_align: float = None,
**kwargs
)
class Border(Control):
"""Border styling for all sides."""
def __init__(
self,
top: BorderSide = None,
right: BorderSide = None,
bottom: BorderSide = None,
left: BorderSide = None,
**kwargs
)
@staticmethod
def all(width: float = None, color: str = None) -> "Border":
"""Create border on all sides."""
@staticmethod
def symmetric(vertical: BorderSide = None, horizontal: BorderSide = None) -> "Border":
"""Create symmetric borders."""Example:
ft.Container(
content=ft.Text("Bordered content"),
border=ft.border.all(2, ft.colors.BLUE),
padding=20
)class BorderRadius(Control):
"""Border radius styling."""
def __init__(
self,
top_left: float = None,
top_right: float = None,
bottom_left: float = None,
bottom_right: float = None,
**kwargs
)
@staticmethod
def all(radius: float) -> "BorderRadius":
"""Uniform radius on all corners."""
@staticmethod
def circular(radius: float) -> "BorderRadius":
"""Circular border radius."""
@staticmethod
def horizontal(left: float = None, right: float = None) -> "BorderRadius":
"""Horizontal border radius."""
@staticmethod
def vertical(top: float = None, bottom: float = None) -> "BorderRadius":
"""Vertical border radius."""
@staticmethod
def only(
top_left: float = None,
top_right: float = None,
bottom_left: float = None,
bottom_right: float = None
) -> "BorderRadius":
"""Specific corner radius."""class BoxDecoration(Control):
"""Box decoration with background, border, shadows, and gradients."""
def __init__(
self,
color: str = None,
image: DecorationImage = None,
border: Border = None,
border_radius: BorderRadiusValue = None,
box_shadow: List[BoxShadow] = None,
gradient: Gradient = None,
blend_mode: BlendMode = None,
shape: BoxShape = None,
**kwargs
)class BoxShadow(Control):
"""Box shadow effect."""
def __init__(
self,
spread_radius: float = None,
blur_radius: float = None,
color: str = None,
offset: OffsetValue = None,
blur_style: ShadowBlurStyle = None,
**kwargs
)Example:
ft.Container(
content=ft.Text("Shadow container"),
padding=20,
decoration=ft.BoxDecoration(
color=ft.colors.WHITE,
border_radius=10,
box_shadow=[
ft.BoxShadow(
spread_radius=1,
blur_radius=15,
color=ft.colors.BLUE_GREY_300,
offset=ft.Offset(0, 0),
)
]
)
)class LinearGradient(Control):
"""Linear gradient effect."""
def __init__(
self,
begin: AlignmentValue = None,
end: AlignmentValue = None,
colors: List[str] = None,
stops: List[float] = None,
tile_mode: GradientTileMode = None,
rotation: float = None,
**kwargs
)Parameters:
begin (AlignmentValue, optional): Gradient start alignmentend (AlignmentValue, optional): Gradient end alignmentcolors (List[str], optional): List of gradient colorsstops (List[float], optional): Color stop positions (0.0-1.0)rotation (float, optional): Gradient rotation in radiansclass RadialGradient(Control):
"""Radial gradient effect."""
def __init__(
self,
center: AlignmentValue = None,
radius: float = None,
colors: List[str] = None,
stops: List[float] = None,
tile_mode: GradientTileMode = None,
focal: AlignmentValue = None,
focal_radius: float = None,
**kwargs
)class SweepGradient(Control):
"""Sweep (conical) gradient effect."""
def __init__(
self,
center: AlignmentValue = None,
start_angle: float = None,
end_angle: float = None,
colors: List[str] = None,
stops: List[float] = None,
tile_mode: GradientTileMode = None,
**kwargs
)Example:
ft.Container(
width=200,
height=200,
gradient=ft.LinearGradient(
begin=ft.alignment.top_center,
end=ft.alignment.bottom_center,
colors=[
ft.colors.BLUE,
ft.colors.BLUE_400,
ft.colors.BLUE_100,
],
stops=[0.1, 0.5, 0.9]
)
)class Blur(Control):
"""Blur effect."""
def __init__(
self,
sigma_x: float = None,
sigma_y: float = None,
tile_mode: BlurTileMode = None,
**kwargs
)class ShaderMask(Control):
"""Shader mask effect for gradient text and icons."""
def __init__(
self,
content: Control = None,
shader: Gradient = None,
blend_mode: BlendMode = None,
**kwargs
)Example:
ft.ShaderMask(
content=ft.Text(
"Gradient Text",
size=40,
weight=ft.FontWeight.BOLD
),
shader=ft.LinearGradient(
colors=[ft.colors.PURPLE, ft.colors.BLUE, ft.colors.RED],
begin=ft.alignment.top_left,
end=ft.alignment.bottom_right
),
blend_mode=ft.BlendMode.SRC_IN
)class ButtonTheme(Control):
"""Global button theming."""
def __init__(
self,
alignment_geometry: AlignmentGeometry = None,
bar_height: float = None,
button_color: str = None,
color_scheme: ColorScheme = None,
disabled_color: str = None,
focus_color: str = None,
height: float = None,
highlight_color: str = None,
hover_color: str = None,
layout_behavior: ButtonBarLayoutBehavior = None,
material_tap_target_size: MaterialTapTargetSize = None,
min_width: float = None,
padding: PaddingValue = None,
shape: OutlinedBorder = None,
splash_color: str = None,
text_theme: ButtonTextTheme = None,
**kwargs
)class ElevatedButtonTheme(Control):
"""Elevated button specific theming."""
def __init__(
self,
style: ButtonStyle = None,
**kwargs
)class TextButtonTheme(Control):
"""Text button specific theming."""
def __init__(
self,
style: ButtonStyle = None,
**kwargs
)class CheckboxTheme(Control):
"""Checkbox theming."""
def __init__(
self,
fill_color: ControlStateProperty = None,
check_color: ControlStateProperty = None,
overlay_color: ControlStateProperty = None,
splash_radius: float = None,
material_tap_target_size: MaterialTapTargetSize = None,
visual_density: VisualDensity = None,
shape: OutlinedBorder = None,
side: ControlStateProperty = None,
**kwargs
)class Padding(Control):
"""Padding specification."""
def __init__(
self,
left: float = None,
top: float = None,
right: float = None,
bottom: float = None,
**kwargs
)
@staticmethod
def all(value: float) -> "Padding":
"""Uniform padding on all sides."""
@staticmethod
def symmetric(vertical: float = None, horizontal: float = None) -> "Padding":
"""Symmetric padding."""
@staticmethod
def only(left: float = None, top: float = None, right: float = None, bottom: float = None) -> "Padding":
"""Specific side padding."""class Margin(Control):
"""Margin specification (same API as Padding)."""
passclass Alignment(Control):
"""Alignment specification."""
def __init__(
self,
x: float,
y: float,
**kwargs
)
# Predefined alignments
top_left = Alignment(-1, -1)
top_center = Alignment(0, -1)
top_right = Alignment(1, -1)
center_left = Alignment(-1, 0)
center = Alignment(0, 0)
center_right = Alignment(1, 0)
bottom_left = Alignment(-1, 1)
bottom_center = Alignment(0, 1)
bottom_right = Alignment(1, 1)class Animation(Control):
"""Animation configuration."""
def __init__(
self,
duration: int = None,
curve: AnimationCurve = None,
**kwargs
)class AnimationCurve(Enum):
"""Animation curve types."""
LINEAR = "linear"
EASE = "ease"
EASE_IN = "easeIn"
EASE_OUT = "easeOut"
EASE_IN_OUT = "easeInOut"
BOUNCE_IN = "bounceIn"
BOUNCE_OUT = "bounceOut"
ELASTIC_IN = "elasticIn"
ELASTIC_OUT = "elasticOut"class Rotate(Control):
"""Rotation transform."""
def __init__(
self,
angle: float,
alignment: Alignment = None,
**kwargs
)
class Scale(Control):
"""Scale transform."""
def __init__(
self,
scale: float = None,
scale_x: float = None,
scale_y: float = None,
alignment: Alignment = None,
**kwargs
)
class Offset(Control):
"""Position offset."""
def __init__(
self,
x: float,
y: float,
**kwargs
)def create_app_theme():
return ft.Theme(
color_scheme_seed=ft.colors.DEEP_PURPLE,
use_material3=True,
text_theme=ft.TextTheme(
body_large=ft.TextStyle(
font_family="Roboto",
size=16
)
),
elevated_button_theme=ft.ElevatedButtonTheme(
style=ft.ButtonStyle(
padding=ft.padding.symmetric(horizontal=20, vertical=12),
shape=ft.RoundedRectangleBorder(radius=8)
)
)
)
# Apply theme
page.theme = create_app_theme()
page.update()def create_dark_theme():
return ft.Theme(
color_scheme=ft.ColorScheme(
brightness=ft.Brightness.DARK,
primary=ft.colors.BLUE_200,
secondary=ft.colors.AMBER_200,
surface=ft.colors.GREY_900,
background=ft.colors.BLACK,
on_primary=ft.colors.BLACK,
on_surface=ft.colors.WHITE
)
)
# Toggle theme mode
def toggle_theme(e):
page.theme_mode = (
ft.ThemeMode.DARK
if page.theme_mode == ft.ThemeMode.LIGHT
else ft.ThemeMode.LIGHT
)
page.update()# Consistent button styling
def create_primary_button(text, on_click):
return ft.ElevatedButton(
text,
style=ft.ButtonStyle(
bgcolor=ft.colors.PRIMARY,
color=ft.colors.ON_PRIMARY,
elevation=4,
padding=ft.padding.symmetric(horizontal=24, vertical=12),
shape=ft.RoundedRectangleBorder(radius=8)
),
on_click=on_click
)
# Styled containers
def create_card(content):
return ft.Container(
content=content,
padding=20,
border_radius=12,
bgcolor=ft.colors.SURFACE,
shadow=ft.BoxShadow(
spread_radius=1,
blur_radius=10,
color=ft.colors.with_opacity(0.1, ft.colors.BLACK)
)
)def get_responsive_text_size(base_size, page_width):
if page_width < 600:
return base_size * 0.8
elif page_width < 1200:
return base_size
else:
return base_size * 1.2
# Usage
title_size = get_responsive_text_size(24, page.window_width)
ft.Text(
"Responsive Title",
size=title_size,
weight=ft.FontWeight.BOLD
)This covers Flet's comprehensive theming and styling system, enabling you to create beautiful, consistent, and professional-looking applications with full control over visual appearance and user experience.
Install with Tessl CLI
npx tessl i tessl/pypi-flet