Quick answer: Black bars mean your stretch aspect is keep or keep_width and the window aspect does not match the content_scale_size. Switch aspect to expand and design your UI with full-rect anchors, or keep keep intentionally and design around the letterbox.

Godot’s project-level stretch settings are powerful but unintuitive. Three dropdowns — mode, aspect, and scale — interact with a base resolution, and the result at runtime is a composite of all four. The moment the window size changes aspect — a player rotating their phone, resizing on desktop, landing on a 21:9 monitor — the pixels on screen stop matching the editor view. Black bars are the usual symptom; cropped UI is the opposite symptom with the same root cause.

Know what each setting controls

Open Project Settings -> Display -> Window -> Stretch. You have four controls:

Pick the right mode

For most indie games shipping crisp UI, canvas_items is correct. Art is drawn at the device’s actual pixel density and scaled in a way that respects vector UI and font rendering.

Pick viewport only if you want deliberate pixelation — a pixel-art platformer where the whole game is a 320x180 framebuffer upscaled 4x. In viewport mode, fonts get blocky and UI cannot be higher resolution than the base, so use it with intent.

Pick the right aspect

Aspect is the letterbox toggle. A quick reference:

Players on ultrawide monitors complaining about black bars want you on expand. Players on mobile in portrait seeing a squashed UI want keep_width with a scrolling layout below the fold.

Anchor UI for expand mode

If you pick expand, every Control that should fill the window needs full-rect anchors:

func _ready() -> void:
    anchor_left = 0.0
    anchor_top = 0.0
    anchor_right = 1.0
    anchor_bottom = 1.0
    offset_left = 0.0
    offset_top = 0.0
    offset_right = 0.0
    offset_bottom = 0.0

HUD elements pinned to corners should use corner anchors (1,1 with negative offsets for bottom-right, for example) rather than a fixed position. Use the Layout menu in the 2D editor to apply these quickly.

Handle the safe area on mobile

On phones with notches, even expand leaves black strips covered by the OS. Query the safe area and inset the top-level container:

var safe := DisplayServer.get_display_safe_area()
$HUD.offset_top = safe.position.y
$HUD.offset_left = safe.position.x
$HUD.offset_right = -(DisplayServer.window_get_size().x - safe.end.x)

This keeps your health bar out from under the notch without losing the expanded aspect.

Test at multiple window sizes

The editor preview always runs at the design size, so you will never see the stretch bug from the editor alone. Export a debug build and resize the window to 21:9, 4:3, square, and portrait. If the game looks right at all of them, your settings are correct. If it breaks, go back to the aspect dropdown — you almost certainly want something other than what you have.

“Black bars are a feature if you want them and a bug if you don’t. Pick the aspect mode on purpose, not by default.”

Related Issues

For related coordinate-system issues, see Fix Godot shader depth buffer access flipped. If your 2D art still looks off after fixing stretch, Fix Godot 2D sprites blurry when scaled covers the filtering side of the same problem.

Tip: switch stretch mode while the game is running to see each option in real time — Godot applies the change immediately.