Claude
Skills
Sign in
Back

scale-and-responsive

Included with Lifetime
$97 forever

Use this skill when making a Phaser 4 game responsive or handling display scaling. Covers ScaleManager, scale modes (FIT, RESIZE, EXPAND, ENVELOP), auto-center, fullscreen, and browser resize handling. Triggers on: ScaleManager, responsive, resize, fullscreen, FIT, scale mode.

General

What this skill does


# Scale and Responsive Design
> How to use the ScaleManager for scaling, centering, fullscreen, orientation handling, and responsive resize in Phaser 4.

**Key source paths:** `src/scale/ScaleManager.js`, `src/scale/const/`, `src/scale/events/`, `src/core/typedefs/ScaleConfig.js`
**Related skills:** ../game-setup-and-config/SKILL.md

## Quick Start

Scale-to-fit with centering -- the most common setup for responsive games:

```js
const config = {
    type: Phaser.AUTO,
    scale: {
        parent: 'game-container',
        mode: Phaser.Scale.FIT,
        autoCenter: Phaser.Scale.CENTER_BOTH,
        width: 800,
        height: 600
    },
    scene: MyScene
};

const game = new Phaser.Game(config);
```

The `scale` config object is parsed into a `Phaser.Core.Config` instance which the `ScaleManager` reads during boot. The ScaleManager sets the canvas element size and applies CSS scaling to fit it within its parent.

## Core Concepts

### ScaleManager (src/scale/ScaleManager.js)

The ScaleManager is created during the Game boot sequence and is accessible at `game.scale` or `this.scale` from within a Scene. It extends `EventEmitter`.

**Three internal Size components drive all calculations:**

| Component | Property | Purpose |
|-----------|----------|---------|
| `gameSize` | `game.scale.gameSize` | The unmodified game dimensions from config. Used for world bounds, cameras. Read via `game.scale.width` / `game.scale.height`. |
| `baseSize` | `game.scale.baseSize` | The auto-rounded gameSize. Sets the actual `canvas.width` and `canvas.height` attributes. |
| `displaySize` | `game.scale.displaySize` | The CSS-scaled canvas size after applying scale mode, parent bounds, and zoom. Sets `canvas.style.width` / `canvas.style.height`. |

Scaling works by keeping the canvas element dimensions fixed (baseSize) and stretching it via CSS properties (displaySize). This is equivalent to CSS `transform-scale` but without browser prefix issues.

The `displayScale` property (`Phaser.Math.Vector2`) holds the ratio `baseSize / canvasBounds` and is used internally for input coordinate transformation.

### Scale Modes (src/scale/const/SCALE_MODE_CONST.js)

All modes are on `Phaser.Scale.ScaleModes` and are set via `scale.mode` in config:

| Constant | Value | Behavior |
|----------|-------|----------|
| `NONE` | 0 | No automatic scaling. Canvas uses config width/height. You manage sizing yourself. If you resize the canvas externally, call `game.scale.resize(w, h)` to update internals. |
| `WIDTH_CONTROLS_HEIGHT` | 1 | Height adjusts automatically to maintain aspect ratio based on width. |
| `HEIGHT_CONTROLS_WIDTH` | 2 | Width adjusts automatically to maintain aspect ratio based on height. |
| `FIT` | 3 | Scales to fit inside parent while preserving aspect ratio. May leave empty space (letterbox/pillarbox). Most commonly used mode. |
| `ENVELOP` | 4 | Scales to cover the entire parent while preserving aspect ratio. May extend beyond parent bounds (content gets cropped). |
| `RESIZE` | 5 | Canvas element itself is resized to fill parent. No CSS scaling -- 1:1 pixel mapping. The `gameSize`, `baseSize`, and `displaySize` all change to match parent. Beware of GPU fill-rate on large displays. |
| `EXPAND` | 6 | Hybrid of RESIZE and FIT. The visible area resizes to fill the parent, and the canvas scales to fit inside that area. Added in v3.80. |

**Shorthand constants** are also available directly on `Phaser.Scale`: `Phaser.Scale.FIT`, `Phaser.Scale.RESIZE`, etc.

### Center Modes (src/scale/const/CENTER_CONST.js)

Set via `scale.autoCenter` in config. Centering is achieved by setting CSS `marginLeft` and `marginTop` on the canvas:

| Constant | Value | Behavior |
|----------|-------|----------|
| `NO_CENTER` | 0 | No auto-centering (default). |
| `CENTER_BOTH` | 1 | Center horizontally and vertically within parent. |
| `CENTER_HORIZONTALLY` | 2 | Center horizontally only. |
| `CENTER_VERTICALLY` | 3 | Center vertically only. |

The parent element must have calculable bounds. If the parent has no defined width/height, centering will not work correctly.

### Zoom (src/scale/const/ZOOM_CONST.js)

Set via `scale.zoom` in config. Multiplies the display size:

| Constant | Value | Behavior |
|----------|-------|----------|
| `NO_ZOOM` | 1 | No zoom (default). |
| `ZOOM_2X` | 2 | 2x zoom -- good for pixel art at low base resolution. |
| `ZOOM_4X` | 4 | 4x zoom. |
| `MAX_ZOOM` | -1 | Automatically calculates the largest integer zoom that fits in the parent. |

You can also pass any numeric value. The zoom affects CSS display size but not the canvas resolution.

### Orientation (src/scale/const/ORIENTATION_CONST.js)

Read via `game.scale.orientation`. Values are strings:

- `Phaser.Scale.Orientation.LANDSCAPE` = `'landscape-primary'`
- `Phaser.Scale.Orientation.LANDSCAPE_SECONDARY` = `'landscape-secondary'`
- `Phaser.Scale.Orientation.PORTRAIT` = `'portrait-primary'`
- `Phaser.Scale.Orientation.PORTRAIT_SECONDARY` = `'portrait-secondary'`

Convenience booleans: `game.scale.isPortrait`, `game.scale.isLandscape` (device orientation), `game.scale.isGamePortrait`, `game.scale.isGameLandscape` (game dimensions).

## Common Patterns

### FIT Mode with Centering (Most Common)

```js
scale: {
    parent: 'game-container',
    mode: Phaser.Scale.FIT,
    autoCenter: Phaser.Scale.CENTER_BOTH,
    width: 1280,
    height: 720
}
```

The game maintains its 16:9 aspect ratio and centers within the parent. Empty space appears as letterbox/pillarbox bars. Style the parent's background color to control bar appearance.

### Responsive Resize (Dynamic Canvas Size)

```js
scale: {
    parent: 'game-container',
    mode: Phaser.Scale.RESIZE,
    width: '100%',
    height: '100%'
}
```

```js
// In your scene -- respond to size changes:
create() {
    this.scale.on('resize', this.handleResize, this);
}

handleResize(gameSize, baseSize, displaySize) {
    this.cameras.resize(gameSize.width, gameSize.height);
    // Reposition UI elements based on new dimensions
}
```

Width/height accept percentage strings (e.g., `'100%'`) which resolve against the parent size. If the parent has no size, they fall back to `window.innerWidth` / `window.innerHeight`.

### Fullscreen Toggle

```js
// Must be called from a pointerup gesture (not pointerdown)
this.input.on('pointerup', () => {
    if (this.scale.isFullscreen) {
        this.scale.stopFullscreen();
    } else {
        this.scale.startFullscreen();
    }
});

// Or use the convenience method:
this.input.on('pointerup', () => {
    this.scale.toggleFullscreen();
});
```

- `startFullscreen(fullscreenOptions)` -- requests browser fullscreen. Default options: `{ navigationUI: 'hide' }`.
- `stopFullscreen()` -- exits fullscreen mode.
- `toggleFullscreen(fullscreenOptions)` -- toggles between the two.
- `isFullscreen` -- read-only boolean for current state.

If no `fullscreenTarget` is configured, Phaser creates a temporary `<div>`, moves the canvas into it, and sends that div fullscreen. The div is removed when leaving fullscreen.

For iframes, the `allowfullscreen` attribute is required.

### Mobile Orientation Handling

```js
create() {
    this.scale.on('orientationchange', (orientation) => {
        if (orientation === Phaser.Scale.LANDSCAPE) {
            // Show game UI
        } else {
            // Show "rotate device" message
        }
    });

    // Lock orientation (mobile browsers only, limited support):
    this.scale.lockOrientation('landscape');
}
```

### Fixed Size (No Scaling)

```js
scale: {
    mode: Phaser.Scale.NONE,
    width: 800,
    height: 600
}
```

In NONE mode, if you change the canvas size externally you must call `game.scale.resize(newWidth, newHeight)` to update all internal components including input coordinates.

### Pixel Art with Max Zoom

```js
scale: {
    mode: Phaser.Scale.FIT,
    autoCenter: Phaser.Scale.CENTER_BOTH,
    width: 320,
    height: 240,
    zoom: Phaser.Scale.MAX_ZOOM
},
pixelArt: true
```

`MAX_ZOOM` calculat
Files: 1
Size: 18.1 KB
Complexity: 23/100
Category: General

Related in General