> For the complete documentation index, see [llms.txt](https://wiki.playgama.com/playgama/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://wiki.playgama.com/playgama/guides/game-development/responsive-layout.md).

# Responsive layout

Scaling strategies, safe areas, resizing and rotation, page setup and engine settings, and a size matrix to test against.

A web game runs in windows of every shape: a phone in portrait, a phone in landscape with the address bar showing, a tablet, a small iframe on a desktop page, a 4K monitor in full screen. Layout problems — cut-off or overlapping interface, empty bars, stretched art — are among the most common reasons a game is sent back. The rules are in section 1.6 of the [Technical Requirements](/playgama/game-requirements/technical-requirements.md); this guide is about meeting them.

## Pick a scaling strategy

Decide how the game maps its design resolution onto the real window before you build any screen.

* **Expand (recommended).** Design the important content inside a fixed safe rectangle — for example 16:9 for a landscape game or 9:16 for a portrait one — scale that rectangle to fit the window, and let the world and the background extend into the extra space on the long side. The player sees more of the level on a wide screen, nothing is cropped, and there are no bars.
* **Fit with a background (letterbox).** Scale the whole design resolution to fit and fill the remaining space with a styled background that belongs to the game — never plain black or white bars. Use it when the game field has a fixed size by design, such as a board or a puzzle grid.
* **Stretch.** Never stretch the image to the window: it deforms the art and breaks item 1.6.1.

Whatever the strategy, the game field fills the window at every aspect ratio, including a square one (item 1.6.8).

## Anchor the interface to the screen, not to the world

* Pin interface elements to the edges and corners of the screen: score top-left, pause top-right, controls along the bottom. They must stay in place and in view however the window changes.
* Size interface elements relative to the short side of the window, so they stay usable on a phone and do not become huge on a monitor.
* Keep the interface inside the safe area the Bridge reports. [`device.safeArea`](/playgama/bridge-sdk/api/device.md#safe-area) gives the insets in pixels covered by the notch, rounded corners, the home indicator and platform UI — read it at startup and again on every resize and rotation, and add the game's own small margin on top. Never hard-code offsets for a particular phone or platform: the next device or the next version of the platform UI breaks them. In engines whose plugin does not expose `safeArea`, set `game.adaptToSafeArea` to `true` in the [config](/playgama/bridge-sdk/config.md) and the Bridge pads the page for you.
* Backgrounds and the game world may extend under the safe-area insets; only interactive and informative elements stay inside.
* Leave room for sticky banners if the game shows them, so they never cover interactive elements (item 2.3.2).
* Keep text readable at every size (item 1.6.7): set a minimum font size in screen pixels and test it on the smallest phone in the matrix below.
* Make touch targets at least about 44×44 CSS pixels, with space between them.

## Handle resizing and rotation

* Size the canvas from its container, not from `window` at load time, and recalculate the layout on every change. In plain JS use a `ResizeObserver` on the container or `window.visualViewport`; the Bridge also reports [`SCREEN_SIZE_CHANGED`](/playgama/bridge-sdk/api/device.md#screen-size) and [`ORIENTATION_STATE_CHANGED`](/playgama/bridge-sdk/api/device.md#orientation).
* Rotation and resizing must never restart the scene or lose state (items 1.7.1, 3.2.3). Re-layout in place.
* Support both orientations when the game design allows it: the game reaches more players and more partner platforms.
* If the game supports only one orientation, select it in the publication request: the platform shows its own "rotate the device" placeholder in the other one (item 1.4.3). Do not build your own.
* Do not try to lock the orientation from code: `screen.orientation.lock()` is not available in most mobile browsers, including Safari on iOS.

## Page setup for plain HTML5 games

* Add a viewport meta tag: `<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, viewport-fit=cover">`.
* Make the page exactly the size of the window and never scrollable (item 1.6.3): `html, body { margin: 0; width: 100%; height: 100%; overflow: hidden; }`.
* Use `100dvh` or `100%` rather than `100vh` for full-height elements: on mobile Safari `100vh` includes the area under the address bar.
* Remove the tap highlight and accidental zoom: `touch-action: none` on the game canvas, `-webkit-tap-highlight-color: transparent`.
* Prevent text selection, the context menu and the iOS magnifier on long press (item 1.4.5): `user-select: none; -webkit-user-select: none; -webkit-touch-callout: none;` on the game area, and `contextmenu` → `preventDefault()`.
* Cap the rendering resolution: use `Math.min(window.devicePixelRatio, 2)` for the canvas back buffer. Higher ratios cost memory and frame rate without a visible difference; on weak devices 1–1.5 is often enough.
* Do not depend on the Fullscreen API: it is not available for page elements on iPhone. The platform provides full screen where it can.

## Engine settings

| Engine        | Where to start                                                                                                                                                                                                    |
| ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Unity         | Match the WebGL canvas to its container (`matchWebGLToCanvasSize` in the WebGL template), set the UI Canvas Scaler to **Scale With Screen Size** with *Match* around 0.5, and anchor UI elements to screen edges. |
| Cocos Creator | Use the **Fit Width** / **Fit Height** design resolution policy that matches the orientation, and the **Widget** component to pin UI to screen edges and safe areas.                                              |
| Construct 3   | Set **Fullscreen mode** to **Scale outer**, and position the HUD on a layer anchored to the viewport edges.                                                                                                       |
| Godot         | Set the stretch mode to `canvas_items` and the aspect to `expand`; anchor UI `Control` nodes to the edges.                                                                                                        |
| Phaser        | Use the Scale Manager with `Phaser.Scale.EXPAND` (or `FIT` with a background) and `autoCenter`, and listen to its `resize` event.                                                                                 |
| Defold        | Choose the HTML5 scale mode in `game.project` and use GUI node anchors and *adjust mode* for the interface.                                                                                                       |
| GameMaker     | Resize the application surface and the camera on browser resize, and draw the GUI layer at the window size.                                                                                                       |

## Test with a fixed matrix

Check every screen of the game, not only the gameplay, at fixed sizes instead of resizing the window by eye:

| Case                | Sizes (CSS pixels)             |
| ------------------- | ------------------------------ |
| Phone, portrait     | 360×640, 390×844, 430×932      |
| Phone, landscape    | 844×390, 915×412               |
| Tablet              | 768×1024, 1024×768             |
| Square              | 640×640                        |
| Desktop iframe      | 800×450, 1280×720              |
| Desktop full screen | 1366×768, 1920×1080, 2560×1440 |
| Extremes            | 9:21 and 21:9                  |

Then resize and rotate the window in the middle of a level and on a popup. Open the game on at least one real iPhone and one Android phone: browser bars, notches and touch behave differently from desktop emulation. The QA Tool — the **Test Game** button in the developer console (see [Submitting a game](/playgama/submitting-a-game.md)) — runs the game in the Bridge environment at preset sizes, including 1:1.
