Decision Tree: Container type → script
| Need |
Prefer |
MANDATORY script |
| Breakpoint shell / full-screen adaptive root |
Margin + Box containers |
[responsivelayoutbuilder.gd](scripts/responsivelayoutbuilder.gd) |
| Fixed columns that change with width |
GridContainer |
[responsivegrid.gd](scripts/responsivegrid.gd) / [responsiveinventorygrid.gd](scripts/responsiveinventorygrid.gd) |
| Wrapping chips / tags |
HFlowContainer |
[responsivetagcloud.gd](scripts/responsivetagcloud.gd) |
| Thousands of scroll rows |
Virtual pool (not raw children) |
[virtuallist.gd](scripts/virtuallist.gd) |
| Log/chat autoscroll |
ScrollContainer |
[terminalautoscroll.gd](scripts/terminalautoscroll.gd) |
| 3D character/item preview in UI |
SubViewportContainer |
[viewport3dpreview.gd](scripts/viewport3dpreview.gd) |
| Deep nesting causing layout spikes |
Anchors/offsets instead |
[performanceanchorlayout.gd](scripts/performanceanchorlayout.gd) |
| Radial/wheel menus |
Custom Container |
[customradialcontainer.gd](scripts/customradialcontainer.gd) |
Do-NOT-Load (by scenario)
| Scenario |
Load |
Do NOT load |
| Inventory / shop grid |
responsivegrid.gd / responsiveinventory_grid.gd |
customradialcontainer.gd, viewport3dpreview.gd |
| Tag cloud / chip wrap |
responsivetagcloud.gd |
Grid column scripts, virtual_list.gd |
| Thousands of log/chat rows |
virtuallist.gd + terminalautoscroll.gd |
Inventory/radial/viewport scripts |
| 3D item/character preview |
viewport3dpreview.gd |
Radial menu + inventory grid scripts |
| Radial / wheel menu |
customradialcontainer.gd |
Virtual list + tag cloud |
| Deep nesting / layout spikes |
performanceanchorlayout.gd |
Full responsive builder catalog |
Available Scripts
[virtuallist.gd](scripts/virtuallist.gd)
Virtual List Pooling — recycle a small Control pool + spacer height for O(1) ScrollContainer rows.
[responsivelayoutbuilder.gd](scripts/responsivelayoutbuilder.gd)
Expert container builder with breakpoint-based responsive layouts.
[responsivegrid.gd](scripts/responsivegrid.gd)
Auto-adjusting GridContainer that changes column count based on available width.
[responsiveinventorygrid.gd](scripts/responsiveinventorygrid.gd)
Expert logic for dynamic Grid columns based on available width and item minimum size.
[terminalautoscroll.gd](scripts/terminalautoscroll.gd)
Safe ScrollContainer management. Handles the common "one-frame delay" bug when adding logs or chat.
[viewport3dpreview.gd](scripts/viewport3dpreview.gd)
High-performance 3D-in-UI setup. Uses stretchshrink and transparentbg for character previews.
[dynamictabmanager.gd](scripts/dynamictabmanager.gd)
Pattern for dynamic tab spawning, custom titles, and tab closing logic.
[responsivetagcloud.gd](scripts/responsivetagcloud.gd)
Wrapping item lists using HFlowContainer, essential for tag clouds and responsive menus.
[performanceanchorlayout.gd](scripts/performanceanchorlayout.gd)
Optimization architecture. Replaces deep container nesting with lightweight Anchor and Offset logic.
[customradialcontainer.gd](scripts/customradialcontainer.gd)
Expert custom container logic implementing a radial/circle layout via NOTIFICATIONSORTCHILDREN.
[animatedcontainershuffle.gd](scripts/animatedcontainershuffle.gd)
Dynamic sibling reordering and animation logic for interactive UI lists.
[aspectratiominimap.gd](scripts/aspectratiominimap.gd)
Enforcing strict aspect ratios (e.g. 1:1, 16:9) across fluid window resizes using AspectRatioContainer.
[containersizeflagspro.gd](scripts/containersizeflagspro.gd)
Advanced sizing logic using SIZEEXPANDFILL and stretch_ratio for weighted layouts.
NEVER Do in UI Containers
- NEVER ignore
mouse_filter properties; strictly set to PASS or IGNORE on overlay containers to prevent them from blocking clicks to underlying buttons.
- NEVER instantiate thousands of nodes in a
ScrollContainer; strictly use Virtual List Pooling — MANDATORY read [virtuallist.gd](scripts/virtuallist.gd) (VScrollBar hook + single spacer child) for O(1) rendering performance.
- NEVER manually calculate card dimensions for responsive grids; strictly use an
AspectRatioContainer to lock proportions (e.g., 2:3 ratio) while allowing parent containers to handle scaling.
- NEVER manually set child
position or size in a Container — Containers override child transforms during queuesort(). Use customminimumsize or sizeflags instead [1].
- NEVER forget
sizeflags for expansion — Default is SIZESHRINKBEGIN. Children will stay tiny unless you set SIZEEXPAND_FILL for responsive containers.
- NEVER use
GridContainer without setting columns — Default is 1, creating a simple vertical list. For responsive wrapping, use HFlowContainer instead [8].
- NEVER nest containers too deeply (10+ levels) — Heavy nesting causes layout recalculation spikes. Replace intermediate containers with Anchor Layouts for static padding [16].
- NEVER skip separation overrides — Default theme separation is often too tight. Use
addthemeconstant_override("separation", value) for professional breathing room.
- NEVER use
ScrollContainer without a minimum size — Without it, the container may collapse to zero or expand infinitely, breaking the scroll mechanism.
- NEVER scroll to a new child on the same frame it was added — The layout hasn't updated yet. You MUST
await gettree().processframe before setting scroll_vertical [5].
- NEVER scale a
SubViewportContainer to change its size — This distorts the rendered contents. Adjust margins or use stretch and stretch_shrink properties instead [2].
- NEVER leave
mousefilter on default for layered Viewports — Input events might not reach children. Use MOUSEFILTER_PASS or STOP to ensure events drill down [6].
- NEVER use
GridContainer for responsive wrapping — Use HFlowContainer if you want items to wrap based on width. GridContainer enforces a strict column count [7].
- NEVER animate
position directly inside a container — Use Tween on customminimumsize to smoothly "push" siblings during transitions [1].
Expert Layout Patterns
1. Split-Screen-Container (Dynamic)
Standard pattern for local multiplayer or comparisons using HSplitContainer.
# split_screen.gd
func setup_split(v1: SubViewport, v2: SubViewport):
var hsplit = HSplitContainer.new()
var c1 = SubViewportContainer.new()
c1.stretch = true # Resize viewport to match container
c1.add_child(v1)
hsplit.add_child(c1)
# repeat for c2/v2...
2. Virtual List ScrollContainer (Pooling)
High-performance list for thousands of items. MANDATORY: implement via [virtuallist.gd](scripts/virtuallist.gd) (setuppool + setdata) — do not paste a one-off scroll recycler inline.
3. Aspect-Ratio-Locked Cards
Responsive cards that maintain proportions (e.g., 2:3) in any grid or flow container.
# card_grid.gd
func add_card(texture: Texture2D):
var arc = AspectRatioContainer.new()
arc.ratio = 0.66 # 2:3 proportions
arc.stretch_mode = AspectRatioContainer.STRETCH_FIT
var tr = TextureRect.new()
tr.texture = texture
tr.expand_mode = TextureRect.EXPAND_IGNORE_SIZE
tr.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED
arc.add_child(tr)
grid_container.add_child(arc)
Size-flag recipes: MANDATORY [containersizeflagspro.gd](scripts/containersizeflagspro.gd) — do not paste beginner SIZEEXPANDFILL tutorials inline.
Deep recipes (on demand)
LLM-ignorance rule: if a general agent would not know it before reading, it lives here or in scripts/ — never delete, only move.
| Topic |
Reference |
| Anchors, flags, separation |
[container-layout-recipes.md](references/container-layout-recipes.md) |
Reference
Progressive disclosure: open Official Documentation links only when researching a specific API; load Related Skills when routing to a peer domain — do not preload the whole lattice.
Official Documentation
- Using Containers — Canonical guide for box/grid/flow/split containers, size flags, and when Containers override child transforms.
- Size and anchors — Anchor presets and offsets for responsive Control placement when you intentionally skip deep Container nesting.
- Control node gallery — Visual catalog of Control/Container types so agents pick HFlow vs Grid vs Split correctly.
- Custom GUI controls — NOTIFICATIONSORTCHILDREN and fitchildin_rect patterns required for custom radial/layouts.
- GUI navigation — Focus neighbors and keyboard/gamepad traversal across container-built menus.
- Multiple resolutions — Stretch modes and content scale that interact with container-driven responsive UI.
- Control — sizeflags*, customminimumsize, mousefilter, and anchors APIs every layout script uses.
- Container — Base sort lifecycle (queuesort / SORT_CHILDREN) that forbids manual child position/size.
- ScrollContainer — Scroll bars, minimum size pitfalls, and post-frame scrollvertical updates for log/chat UIs.
- HFlowContainer — Width-based wrapping for tag clouds and chip lists (prefer over fixed-column GridContainer).
- AspectRatioContainer — Lock card/minimap proportions under fluid parent sizes.
- SubViewportContainer — stretch / stretchshrink for 3D-in-UI previews without scaling distortion.
Related Skills
Prerequisites
- godot-project-foundations — Scene tree ownership, Control roots, and project layout conventions every responsive menu assumes before wiring containers.
- godot-gdscript-mastery — Typed Control APIs,
@onready, and safe child rebuild loops used when building grids/tabs at runtime.
- godot-signal-architecture — Resize, tab-changed, and inventory-refresh signals should flow signal-up / call-down so layout scripts never own game state.
Complements
- godot-ui-theming — Theme constants (
separation, margins) and type variations style container chrome without hardcoding colors in layout code.
- godot-ui-rich-text — RichTextLabel minimum sizes and BBCode content drive ScrollContainer height; pair after the layout shell exists.
- godot-tweening — Animate
customminimumsize / reorder feedback instead of tweening position inside Containers.
- godot-input-handling — Focus, mouse_filter, and action maps for interactive lists/tabs built from Containers.
- godot-adapt-desktop-to-mobile — Breakpoint-driven column counts and safe-area margins compose with responsive Grid/HFlow builders.
- godot-inventory-system — Inventory grids consume responsive column logic; containers present slots, inventory owns item truth.
- godot-performance-optimization — Virtual list pooling and shallow anchor layouts when ScrollContainer would otherwise spawn thousands of Controls.
Downstream / consumers
- godot-dialogue-system — Dialogue choice lists and history panels are Scroll/VBox layouts that reuse autoscroll and separation patterns.
- godot-genre-card-game — Hand arcs, drag layers, and deck UIs assemble AspectRatio/HFlow containers around card Resources.
- godot-composition-apps — Tooling/app UIs reuse the same Container size-flag and split patterns outside gameplay HUDs.
Master
- godot-master — Router and mirrored module entry for UI Containers when agents start from the library index.