Quick answer: Each Control looks up StyleBoxes by a specific name: Panel and PanelContainer use panel, Buttons use normal, hover, pressed, disabled and focus. Override with add_theme_stylebox_override("panel", style) (Godot 3's add_stylebox_override no longer exists), and remember that a local override beats the Theme.

You create a StyleBoxFlat, assign it, and the Panel looks exactly the same. StyleBoxes are resolved through a lookup chain, and a wrong name anywhere in that chain fails silently.

Use the theme item name the Control actually reads

ControlStyleBox names
Panel, PanelContainerpanel
Buttonnormal, hover, pressed, disabled, focus, hover_pressed
LineEdit, TextEditnormal, focus, read_only
Labelnormal
ProgressBarbackground, fill

Setting normal on a Panel or panel on a Button does nothing. In the Inspector, expand Theme Overrides > Styles on the node to see the exact names it supports.

Use the Godot 4 API

var style := StyleBoxFlat.new()
style.bg_color = Color("1e2433")
style.set_corner_radius_all(8)
style.set_content_margin_all(12)
$Panel.add_theme_stylebox_override("panel", style)

add_stylebox_override() was the Godot 3 name. For Buttons, override each state you care about, or the default theme still draws hover and pressed.

Know the lookup order

A Control looks for a StyleBox in this order:

  1. Its own Theme Overrides.
  2. The theme property on itself, then on each parent Control up the tree (a CanvasLayer or Node2D breaks the chain).
  3. The project theme (Project Settings > GUI > Theme > Custom).
  4. The default engine theme.

So a Theme assigned on a parent is ignored by a child that has a local override, and a theme set on a Control does not reach Controls under a different CanvasLayer.

Theme type variations

If you created a variation such as DangerButton in your Theme, the node must opt in through Theme Type Variation (theme_type_variation = "DangerButton"), and the variation needs its base type set to Button in the Theme editor.

The style applies but looks invisible

Editing one panel changes all of them

StyleBoxes are resources, shared by reference. If several panels use the same .tres, changing one changes all. Call style.duplicate() before modifying it at runtime, or enable Local to Scene on the resource.

Related fixes