Styling#

Styling in ttkbootstrap runs through one engine and reaches widgets three ways. The Style engine owns the active theme and builds ttk styles on demand. The shipped widgets carry the bootstyle keyword; to put that keyword on a widget ttkbootstrap does not ship, use the delivery helpers below. And when a name in the bootstyle vocabulary can’t describe the look you want, the toolkit builds a ttk style by hand. The Custom styles guide shows the toolkit in use.

The style engine#

Style is a process-wide singleton, bound to the first application window and reachable as its style attribute (or Style.get_instance()). It holds the theme definitions, switches the active theme, and exposes the current theme’s colors.

class Style(*args, **kwargs)#

Bases: Style

A singleton class for creating and managing the application theme and widget styles.

This class is meant to be a drop-in replacement for ttk.Style and inherits all of it’s methods and properties. However, in ttkbootstrap, this class is implemented as a singleton. Subclassing is not recommended and may have unintended consequences.

Parameters:
  • theme (str) – The name of the theme to use when styling the widget. themename is a permanent, non-deprecated alias accepted for the same purpose (pre-2.0 spelling); pass either.

  • light_theme (str) – Optionally designate the themes that toggle_theme() / theme_mode switch between. If omitted, the counterpart is derived from the <family>-light / <family>-dark naming convention, so designation is only needed to pin a specific pair (e.g. a light theme from one family with a dark theme from another). Read once on the first Style/App; ignored on the existing singleton (set later via set_theme_modes(...)).

  • dark_theme (str) – Optionally designate the themes that toggle_theme() / theme_mode switch between. If omitted, the counterpart is derived from the <family>-light / <family>-dark naming convention, so designation is only needed to pin a specific pair (e.g. a light theme from one family with a dark theme from another). Read once on the first Style/App; ignored on the existing singleton (set later via set_theme_modes(...)).

  • default_button (str) – The color a bare Button/Menubutton (no bootstyle) uses. Defaults to "neutral"; pass "primary" for the pre-2.0 accented default. Read once when the base styles build, so set it on the first Style/App; ignored on the existing singleton. If omitted, a pre-root ttk.set_default_button(...) setting is used, else "neutral"; an explicit argument here wins over that setter.

static get_instance()#

Returns the singleton Style instance (or None if not yet created).

clear_image_cache()#

Drop all cached widget asset images.

Releases the cached PhotoImage objects (and their underlying Tcl images). This is a memory-reclamation and diagnostics escape hatch, not a live refresh: styles are built once per (theme, style), so styles built before the clear keep referencing the freed image names until they are rebuilt – which happens when a not-yet-built theme is activated, not on a same-theme switch. Clear when image widgets for the affected styles are not currently displayed (e.g. before moving to a fresh theme), or to reclaim memory at shutdown.

configure(style, query_opt=None, **kw)#

Configure a ttk style, resolving style through the bootstyle parser if it is not already a registered ttk style name.

Parameters:
  • style (str) – A ttk style name or a bootstyle string to resolve first.

  • query_opt (Any) – If given, query this single style option instead of setting options; forwarded to ttk.Style.configure.

  • **kw – Style options to configure (forwarded to ttk.Style.configure).

element_create(elementname, etype, *args, **kw)#

Create a ttk element, idempotently within the current theme.

ttk raises Duplicate element if the same element name is created twice in one theme. Every ttkbootstrap theme maps to a single clam-derived Tcl theme with fixed colors, so an element only ever needs to be created once per theme; the second run of a recipe – whether a test that force-rebuilds a style, or a production theme-rebuild after the per-theme style registry (_theme_styles) desyncs from the Tcl theme – must be a safe no-op, not a crash. The configure/layout/ map steps that follow are already idempotent, so skipping the redundant element create makes the whole recipe re-runnable.

load_user_theme(theme)#

Load a user theme definition

Parameters:

theme (ThemeDefinition)

load_user_themes(file)#

Load user themes saved in json format

on_theme_change(callback, *, call_now=True)#

Register callback(style) to run after every theme change.

Use it to (re)build a custom style so it tracks the active theme: the callback re-runs on each theme_use / toggle_theme. When call_now (the default), it also runs once immediately if a theme is already active, so the style exists before the first switch.

Returns callback, so it doubles as a decorator.

Parameters:
  • callback (Callable[[Style], None]) – Called with this Style; typically rebuilds a style from style.colors.

  • call_now (bool) – Also run it once now (if a theme is active).

register_theme(definition)#

Register a theme definition for use by the Style object. This makes the definition and name available at run-time so that the assets and styles can be created when needed.

Parameters:

definition (ThemeDefinition) – A ThemeDefinition object.

remove_theme_change_callback(callback)#

Unregister a callback previously passed to on_theme_change.

Return type:

None

reset_style_options(style=None)#

Drop durable style-option overrides recorded via configure().

With no argument, clears every recorded override; with a style name, clears only that one. The recipe’s default value returns the next time the affected style is rebuilt (a theme switch or a new variant build).

Parameters:

style (str, optional) – The style name to reset; None (default) resets all.

set_theme_modes(light=None, dark=None)#

Designate the light and/or dark theme that theme_mode / toggle_theme() switch between.

By default the counterpart is derived from the <family>-light / <family>-dark naming convention, so this is only needed to pin a specific pair (e.g. a light theme from one family with a dark theme from another). Each name must be a registered theme; a name whose own type disagrees with the slot it is assigned to earns a warning.

Parameters:
  • light (str) – Theme to use as the light-mode target.

  • dark (str) – Theme to use as the dark-mode target.

Return type:

None

style_exists_in_theme(ttkstyle)#

Check if a style exists in the current theme.

Parameters:

ttkstyle (str) – The ttk style to check.

Returns:

boolTrue if the style exists, otherwise False.

theme_create(themename, parent=None, settings=None)#

Create a new theme in the Tcl interpreter. If the parent is a registered ttkbootstrap theme, the new theme will be registered with a copied ThemeDefinition and builder. Duplicate registration is avoided.

Parameters:
  • themename (str) – The name of the new theme.

  • parent (str) – The name of the parent theme to inherit from.

  • settings (dict) – A dictionary of style settings (Tcl-style).

Return type:

None

theme_names()#

Return a list of all ttkbootstrap themes.

Returns:

list[str, …] – A list of theme names.

theme_use(themename=None)#

Changes the theme used in rendering the application widgets.

If themename is None, returns the theme in use, otherwise, set the current theme to themename, refreshes all widgets and emits a <<ThemeChanged>> event.

Only use this method if you are changing the theme during runtime. Otherwise, pass the theme name into the Style constructor to instantiate the style with a theme.

Parameters:

themename (str) – The name of the theme to apply when creating new widgets

Returns:

Union[str, None] – The name of the current theme if themename is None otherwise, None.

toggle_theme()#

Toggle between the light and dark theme, returning the new mode.

Return type:

str | None

use_dynamic_foreground(enable=True)#

Enable or disable dynamic foreground color selection.

When enabled, the foreground color of widgets will be decided between the fg and selectfg colors based on the contrast ratio with the widget’s background color. At default, this is disabled.

Parameters:

enable (bool) – If True, dynamic foreground selection is enabled. Otherwise, it is disabled.

property colors#

An object that contains the colors used for the current theme.

Returns:

Colors – The colors object for the current theme.

property dynamic_foreground#

Returns True if dynamic foreground selection is enabled, otherwise False.

instance = None#
property theme_mode: str | None#

The active theme mode ("light" or "dark").

Read it, or assign "light"/"dark" to switch the current family to that mode (the designated theme, else the -light/-dark sibling):

style.theme_mode           # -> "light"
style.theme_mode = "dark"  # switch

Reads the active theme’s mode; None before a theme is applied.

Applying styles to any widget#

The widgets ttkbootstrap ships already accept bootstyle. These helpers extend that keyword to widgets it does not ship — a third-party ttk widget, or a plain tkinter.ttk widget you created yourself.

How much of the bootstyle vocabulary applies depends on the widget’s ttk class. A widget that keeps a standard ttk class (a subclass of ttk.Button, ttk.Entry, …) gets the full vocabulary and behaves exactly like the corresponding ttkbootstrap widget. A widget with its own ttk class has no ttkbootstrap style recipe: a bare color (bootstyle="info") warns and leaves the widget’s style unchanged, and naming a base type explicitly (bootstyle="info-frame") borrows that standard recipe where the widget’s elements support it.

A composite widget’s internals follow the active theme on their own — standard-class children resolve against the per-theme base styles, so they match every theme switch without any wrapping. The accent, however, is not fanned out to them: which child should carry it is the widget’s design, not something a wrapper can infer. To accent a specific internal, call apply_bootstyle on that child.

bootify(cls)#

Return a bootstyle-enabled subclass of any ttk widget class.

Use this to wrap a third-party ttk-derived widget that ttkbootstrap does not ship a subclass for:

ThemedGadget = bootify(Gadget)
gadget = ThemedGadget(root, bootstyle="info")

The result is type(cls.__name__, (BootMixin, cls), {}) — the same construction used for the widgets ttkbootstrap ships, so it gains the full bootstyle API without mutating the original class.

How much of the vocabulary applies depends on the widget’s ttk class:

  • A widget that keeps a standard ttk class (a subclass of ttk.Button, ttk.Entry, …) gets the full vocabulary — it behaves exactly like the corresponding ttkbootstrap widget.

  • A widget with its own ttk class has no ttkbootstrap style recipe: a bare color (bootstyle="info") warns and leaves the widget’s style unchanged. Name a base type explicitly (bootstyle="info-frame") to borrow a standard recipe where the widget’s elements support it.

A composite widget’s internals follow the active theme on their own (standard-class children resolve against the per-theme base styles), but the accent is not fanned out to them — which child should carry it is the widget’s design, not something a wrapper can infer. To accent a specific internal, use apply_bootstyle on that child.

apply_bootstyle(widget, bootstyle)#

Apply a bootstyle to an existing widget instance, no class mutation.

For per-instance styling of a widget whose class was never wrapped (for example a plain tkinter.ttk widget): resolves the bootstyle to a ttk style, assigns it, and stamps the widget current for the theme walk.

from tkinter import ttk
b = ttk.Button(root, text="Save")
apply_bootstyle(b, "success")

The same widget-class rules as bootify apply: a widget with its own ttk class has no style recipe, so a bare color warns and leaves the style unchanged — name a base type explicitly ("info-frame") to borrow a standard recipe.

Returns the resolved ttk style name.

Parameters:

bootstyle (Literal['danger', 'danger ghost', 'danger ghost toolbutton', 'danger link', 'danger outline', 'danger outline toolbutton', 'danger round', 'danger round toggle', 'danger square toggle', 'danger striped', 'danger thin', 'danger toggle', 'danger toolbutton', 'dark', 'dark ghost', 'dark ghost toolbutton', 'dark link', 'dark outline', 'dark outline toolbutton', 'dark round', 'dark round toggle', 'dark square toggle', 'dark striped', 'dark thin', 'dark toggle', 'dark toolbutton', 'ghost', 'ghost toolbutton', 'info', 'info ghost', 'info ghost toolbutton', 'info link', 'info outline', 'info outline toolbutton', 'info round', 'info round toggle', 'info square toggle', 'info striped', 'info thin', 'info toggle', 'info toolbutton', 'light', 'light ghost', 'light ghost toolbutton', 'light link', 'light outline', 'light outline toolbutton', 'light round', 'light round toggle', 'light square toggle', 'light striped', 'light thin', 'light toggle', 'light toolbutton', 'link', 'neutral', 'neutral ghost', 'neutral ghost toolbutton', 'neutral link', 'neutral outline', 'neutral outline toolbutton', 'neutral toolbutton', 'outline', 'outline toolbutton', 'primary', 'primary ghost', 'primary ghost toolbutton', 'primary link', 'primary outline', 'primary outline toolbutton', 'primary round', 'primary round toggle', 'primary square toggle', 'primary striped', 'primary thin', 'primary toggle', 'primary toolbutton', 'round', 'round toggle', 'secondary', 'secondary ghost', 'secondary ghost toolbutton', 'secondary link', 'secondary outline', 'secondary outline toolbutton', 'secondary round', 'secondary round toggle', 'secondary square toggle', 'secondary striped', 'secondary thin', 'secondary toggle', 'secondary toolbutton', 'square toggle', 'striped', 'success', 'success ghost', 'success ghost toolbutton', 'success link', 'success outline', 'success outline toolbutton', 'success round', 'success round toggle', 'success square toggle', 'success striped', 'success thin', 'success toggle', 'success toolbutton', 'thin', 'toggle', 'toolbutton', 'warning', 'warning ghost', 'warning ghost toolbutton', 'warning link', 'warning outline', 'warning outline toolbutton', 'warning round', 'warning round toggle', 'warning square toggle', 'warning striped', 'warning thin', 'warning toggle', 'warning toolbutton'] | str)

Return type:

str

enable_global_api()#

Re-apply the legacy global monkey-patch (opt-in).

By default the styling API is delivered through concrete subclasses (BootMixin/AutoStyleMixin), so importing ttkbootstrap does not mutate the stock tkinter/tkinter.ttk classes. Call this once if you have code that creates vanilla ttk/tk widgets (e.g. from tkinter import ttk; ttk.Button(..., bootstyle=...)) and want the bootstyle/ autostyle keywords on them anyway. It also makes pack/grid/ place return the widget on every widget (see Bootstyle.patch_geometry_managers), extending FluentGeometryMixin beyond the blessed subclasses.

Idempotent. The installed wrappers defer to BootMixin/AutoStyleMixin instances (the blessed subclasses), so enabling the global API never double-resolves a style for a widget that already carries a mixin.

Building custom styles#

For a look bootstyle can’t name, compose a ttk style from assets, elements, a state map, and a layout — each a small toolkit call. Assets renders cached images, image_element turns one into a named ttk element, state_map is a validated style.map, and layout arranges the elements into the widget’s element tree and registers the style. See the Custom styles guide for a worked example.

class Assets(style)#

Bases: object

Image construction over the engine’s content-addressed cache.

Assets(style) wraps Style._get_or_create_image: each method renders an asset and derives its cache key from the same render inputs, so the key cannot drift from the pixels. Builders reach a shared instance via self.assets; public users construct Assets(Style.get_instance()).

Sizes are logical UI units converted once by the root-bound scaling service; final image dimensions are exact and may be odd. Every method returns the Tcl image name (the _get_or_create_image contract), and the resolved colors are in the key, so cross-theme-identical assets dedupe.

circle(fill, size, *, outline=None, width=0)#

A filled circle; size and width are logical UI units.

icon(name, size, color)#

Render a Bootstrap Icons glyph as a cached widget asset.

size is the logical UI size; color is a resolved color string. Returns the Tcl image name (the same contract as the shape recipes). The key is ("icon", name, physical_size, color) – theme -independent by construction (the resolved color is in the key), so two themes that resolve a glyph to the same color share one image.

IconRenderer is imported lazily here so assets.py keeps no module -level edge to icons.py (which imports this module), and the font is never read at import time.

image(size, draw_fn, *key_parts)#

Escape hatch for custom composite draws (concentric circles, glyphs).

draw_fn(draw, w, h) draws onto the oversampled (w, h) canvas, so the old hand-fit canvas constants become w-relative expressions. The key is (draw_fn.__qualname__, physical_size, *key_parts) – list in key_parts every color/value the draw closes over; they sit beside the draw so the key cannot silently drift from it, and the __qualname__ keeps two different draws from colliding on equal key_parts.

recolor(name, *, white, black, magenta=None, transform=None)#

Recolor a manifest-backed ttk element raster and cache the result.

white, black, and optional magenta are resolved color strings for the source template’s semantic channels. Source alpha is preserved. transform may flip the image horizontally ("flip-x") or rotate it by 90/180/270 degrees ("rotate-90"/"rotate-180"/"rotate-270"); dimensions and border/padding metadata transform with the pixels.

Returns a RecolorResult containing the Tcl image name and scaled logical manifest metadata. Source-image dimensions only validate the vendored PNG; callers do not pass a size.

rect(fill, size)#

A solid axis-aligned rectangle (no anti-aliasing, no size snap).

rounded_rect(fill, size, radius, *, outline=None, width=0)#

A rounded rectangle with geometry in logical UI units.

image_element(style, name, *, default, states=None, **options)#

Create an image element with a validated, ordered state->image map.

Wraps style.element_create(name, "image", default, *statespecs, **options). states is an ordered dict {state_string: image}; ttk matches statespecs first-match-wins, so the dict’s insertion order is the match order, made explicit. Each state string is validated by statespec (a typo raises instead of silently never matching). options (width, border, sticky, …) pass through to element_create.

state_map(style, ttk_style, **options)#

Validated style.map analog.

Each keyword is a ttk option (e.g. foreground=) whose value is an ordered dict {state_string: value} (or an iterable of (state_string, value) pairs). State strings are validated by statespec. Replaces bare foreground=[("disabled", fg)] lists.

statespec(spec)#

Validate a ttk state string and split it into a tuple of tokens.

Tokens are space-separated; each may be negated with a leading ! (“!selected”). An unknown token raises ValueError.

layout(style, ttk_style, root)#

Apply an El (or list of El`s) as the layout for `ttk_style.

Structural sugar over style.layout(ttk_style, [...]). Defining a layout is what gives a style its identity, so this also registers ttk_style with the engine (via register_style) – a hand-built style whose terminal step is layout() resolves through style="<ttk_style>" with no extra step. (Built-in builders that also call _register_ttkstyle explicitly are unaffected – registration is an idempotent set add.)

class El(name, *, side=None, sticky=None, expand=None, border=None, children=None)#

Bases: object

A ttk layout element: a name, layout options, and child elements.

Build an El tree and pass it to layout(), which lowers it to ttk’s nested (name, {options, "children": [...]}) form and registers the style.

Parameters:
  • name (str) – The element name (e.g. "Button.border").

  • side (str) – Which side of the remaining space the element occupies: "left", "right", "top", or "bottom".

  • sticky (str) – How the element stretches within its allocation — any combination of "nsew".

  • expand (bool) – Whether the element claims any leftover space.

  • border (int) – The border width reserved inside the element.

  • children (list[El]) – Elements nested inside this one.

name#

The element name.

Type:

str

options#

The layout options that were set (side/sticky/ expand/border).

Type:

dict

children#

The nested child elements.

Type:

list[El]

spec()#

Lower this element (and its subtree) to a ttk (name, opts) tuple.

register_style(style, ttk_style)#

Register a hand-built ttk style name with the ttkbootstrap engine.

A custom style applied to a ttkbootstrap widget via style="My.TButton" is silently re-resolved to its base style unless the engine knows the name – bootstyle resolution only honors style= for a registered style. Building a style with the toolkit (element_create/image_element/icon_element/ map) does not register it on its own; call this (or layout(), which calls it for you) so style="<ttk_style>" resolves to what you built.

Registration is per active theme (it mirrors the built-in builders). A hand-built style is not auto-rebuilt on a theme switch, so re-build + re -register it if you change themes – engine-managed theme-follow for custom styles is a separate effort.

class StyleName(ttk_class, colorname='default', orient=None, surface='')#

Bases: object

Derive the related names a custom style is built from.

From a ttk class token ("TScale", "TRadiobutton"), a color name, and an optional orientation, computes the style name and the matching element-name prefix, so the three always agree.

Parameters:
  • ttk_class (str) – The ttk widget class token (e.g. "TButton", "Treeview").

  • colorname (str) – The accent color name; DEFAULT or "" resolves to "primary".

  • orient (str) – An optional orientation segment ("Horizontal" / "Vertical").

  • surface (str) – An optional surface-color token carried as a name prefix.

colorname#

The resolved color name — "primary" when the input was the default, otherwise the input unchanged.

Type:

str

ttk_style#

The full ttk style name ("Horizontal.TScale", "info.Horizontal.TScale", "TRadiobutton", …).

Type:

str

element#

The element-name prefix: ttk_style with the class token’s leading "T" dropped ("info.Horizontal.TScale""info.Horizontal.Scale").

Type:

str

property ttkstyle#

Backward-compatible spelling of ttk_style.

Note

To render a glyph as an element in a custom layout, see icon_element() on the Imaging page.

See also#