the symptom, in your words

"A ScreenPanel lays out against a height-fixed logical canvas, not a fixed 1920x1080"

✓ verified on 26.07.22
lane Building UIposted

▸ SYMPTOM

You author a UI mockup against a 1920x1080 canvas and position a sheet at its centre with left: (1920 - width) / 2. In the running game the sheet sits about 70px left of true centre.

A panel you spaced to clear its neighbour by 60px clears it by roughly 198px instead. Vertical measurements and left-anchored values land where you drew them, but every right-anchored and hard-centred value drifts. Verified on engine 26.07.22.

▸ CAUSE

A ScreenPanel does not lay out against a fixed 1920x1080 canvas. The logical canvas is fixed in height at 1080. Its width follows the game window aspect ratio.

Measured live at a 1920x1080 window, the logical canvas is 2060.7 x 1080, not 1920 x 1080. So a value computed against an assumed 1920 width is wrong by the difference between 1920 and the real canvas width.

The drift splits by anchor:

  • Vertical measurements and heights transfer 1:1, because the canvas height is the one fixed axis.
  • Left-anchored values transfer 1:1, because the origin does not move.
  • Right-anchored values drift wider than the mockup draws them.
  • Values hard-centred with arithmetic against 1920 sit off-centre, because the real canvas is wider.

▸ FIX

Centre with flex on the parent, not with arithmetic against an assumed width:

  1. Set justify-content: center on the parent to centre children horizontally.
  2. Set align-items: center on the parent to centre children vertically.
  3. Delete any left: (1920 - width) / 2 style expression.

Flex centring is correct at every width the window produces. A hard-coded centre value is correct only at the one aspect ratio it was computed against.

▸ WHY IT WORKS

The one axis you can trust is height, because the canvas fixes it at 1080. Width is a function of the window aspect ratio, so any layout value that assumes a width is a guess that holds at one resolution.

Flex centring reads the real canvas width at layout time and places the child against it. The child stays centred when the player resizes the window or runs a different aspect ratio.

Verified on engine 26.07.22: seen in a real project.
s&box moves fast; an undated fix is a liability. Spot a stale detail?
changelog
  • Published.

Want to know when new guides or fixes drop? Join the community to help build this out. Report gotchas, flag outdated fixes, or just lurk.

Join the Discord