Quick answer: Set every per-state StyleBox key in the Theme’s Button section: normal, hover, pressed, disabled, focus. Skipping any falls back to defaults. Use Theme Type Variation (e.g. ButtonDanger) for stylistic variants without rebuilding all five styleboxes.
You design a beautiful Button stylebox in your Theme. The button looks correct at rest. Hover or click and the default gray flashbox appears. The Theme has six stylebox slots and you only filled one.
The Symptom
Custom Button styling appears only in the idle state. Hover, pressed, disabled, and focus states show the engine defaults. Or the focus rectangle clashes with a custom focus outline.
The Theme Slots
Each Button-derived control has a Theme section listing every customizable resource. For Button:
StyleBox:
normal # default state
hover # mouse over, not pressed
pressed # mouse held down
disabled # control disabled
focus # keyboard focus indicator
hover_pressed
Color:
font_color, font_color_hover, font_color_pressed, ...
Font / FontSize / Constants: ...
Each slot is independent. Set normal alone: only normal looks right. The fix is to set them all.
The Fix
Step 1: Open the Theme. Either the project-wide theme or a custom Theme Resource. Click + on the Button type if not added. Expand StyleBox.
Step 2: Set every state. For each state, click +, pick StyleBoxFlat (or your StyleBoxTexture). Configure colors and borders.
Quickest workflow: design the normal stylebox, right-click it, Duplicate, paste into hover (with brighter bg), pressed (darker bg), disabled (gray), focus (outline only).
Step 3: Verify font color per state. Don’t forget font_color_hover, font_color_pressed, etc. White text on hover and unchanged dark text on pressed looks broken; bring those colors with the styleboxes.
Theme Type Variation
For variants like “Danger Button” (red theme):
Theme:
Button (base, neutral colors)
ButtonDanger: # variation, base = Button
StyleBox/normal: red flat
StyleBox/hover: brighter red
Color/font_color: white
On the button instance: theme_type_variation = ButtonDanger. The control looks for ButtonDanger overrides first, falls back to Button.
Programmatic Overrides
For one-off styling without polluting the Theme:
$Button.add_theme_stylebox_override("normal", my_stylebox)
$Button.add_theme_color_override("font_color", Color.RED)
Verifying
Run the scene. Mouse over the button: hover style. Click: pressed style. Tab to focus: focus outline. Disable via code: disabled style. All four should look intentional.
“Five states, five styleboxes. Variations layer over base. UI feels coherent.”
Related Issues
For Control anchor on resize, see anchor. For RichTextLabel parsing, see BBCode.
Five styleboxes. Variation for variants. UI looks done.