This is a documentation for Board Game Arena: play board games online !
Your game mobile version: Difference between revisions
(Remove the part suggesting to hack the framework) |
(clarify game_interface_width.autoscale and overall polish) |
||
| Line 3: | Line 3: | ||
__TOC__ | __TOC__ | ||
Board Game Arena | Board Game Arena supports mobile phones and tablets. Most games are already playable on touch devices, but their layout and interactions still need to work on narrow screens. | ||
== Declare your interface minimum width == | |||
<code>game_interface_width.min</code> is the smallest logical width at which your game remains usable. The default is 740 pixels. | |||
Declare it in '''gameinfos.jsonc''': | |||
"game_interface_width": { | |||
// Smallest usable width. Default: 740 | |||
"min": 540, | |||
// Default: true | |||
"autoscale": true | |||
} | |||
The declared width must actually work. If you declare 540 pixels, the complete interface must remain usable at 540 pixels. | |||
Keep the minimum as low as reasonably possible. Large values require stronger scaling on phones, make content smaller, and increase rendering work. Use fluid layouts and CSS media queries instead of declaring a large fixed width. | |||
Below 490 pixels, player panels may no longer use a two-column mobile layout. | |||
Examples: | |||
* In '''Can't Stop''', the dice are moved below the board on narrow screens: | |||
@media only screen and (max-width: 990px) { | |||
#dicechoices { | |||
left: 180px; | |||
top: 530px; | |||
} | |||
#cantstop_wrap { | |||
height: 900px; | |||
width: 550px; | |||
} | |||
} | |||
} | |||
* In '''Seasons''', panels normally displayed to the right of the board are moved below it: | |||
@media only screen and (max-width: 970px) { | |||
#board { | |||
float: none; | |||
margin: auto; | |||
} | |||
.seasons_rightpanel { | |||
margin-left: 0; | |||
} | |||
} | |||
On mobile, BGA moves player panels above the game and adds <code>mobile_version</code> to <code>#ebd-body</code>. The desktop layout uses <code>desktop_version</code>. Use these classes for layout-specific CSS. | |||
=== Autoscale === | |||
<code>game_interface_width.autoscale</code> controls what happens when the available width is smaller than <code>min</code>. It accepts <code>true</code>, <code>false</code>, or <code>"viewport"</code>. The default is <code>true</code>. | |||
The examples below use a 740-pixel game displayed in 390 pixels of available space. | |||
==== <code>autoscale: true</code> ==== | |||
BGA applies CSS <code>zoom</code> to the game content. In the example, the scale is approximately 53%. | |||
The game content scales independently from the surrounding BGA interface: | |||
* the top bar and tableview chat keep their normal size; | |||
* the action bar and player panels use separate framework scaling on very narrow screens; | |||
* standard BGA dialogs and tooltips generally keep their normal size; | |||
* overlays inside the game area inherit the game zoom. | |||
This is the default mode and should suit most fixed-width games. | |||
===== Coordinates and animations ===== | |||
Browsers do not return consistent geometry for elements using CSS zoom. For custom positioning inside the zoomed game area, use: | |||
const rect = this.getBoundingClientRectIgnoreZoom("my-element"); | |||
It returns logical, unscaled coordinates. BGA animation and positioning helpers already account for framework zoom. | |||
Use the native <code>getBoundingClientRect()</code> when you need the visual position in the browser viewport, such as for an overlay outside the zoomed game area. | |||
==== <code>autoscale: false</code> ==== | |||
BGA does not scale the game area. | |||
Use this for responsive games or games with their own scaling system, such as [[BgaZoom]]. A fixed 740-pixel layout displayed in 390 pixels will otherwise overflow horizontally and may require scrolling. | |||
==== <code>autoscale: "viewport"</code> ==== | |||
This mode scales the whole game document through a wider logical viewport. | |||
Previously, when game pages were opened directly, BGA set the document viewport width and let the mobile browser fit it to the screen. | |||
Games are now normally opened through <code>/tableview</code>. The game runs in an iframe, and its viewport cannot resize that iframe. Tableview emulates the same result by laying out the iframe at the requested width and applying <code>transform: scale(...)</code> to it. | |||
In the example, the iframe is laid out at 740 pixels and displayed at approximately 53% scale. The game area and the BGA controls inside the iframe are scaled together. | |||
CSS <code>zoom</code> participates in layout. <code>transform: scale(...)</code> scales after layout and usually creates a composited layer. Transforming a large iframe can be expensive on mobile devices. | |||
Prefer <code>autoscale: true</code> or a responsive layout unless viewport scaling is required for compatibility. | |||
=== | ==== Legacy <code>default_viewport</code> ==== | ||
Some older games contain code such as: | |||
this.default_viewport = "width=740"; | |||
<code>default_viewport</code> started as internal framework state. Games later used it as an undocumented viewport override before <code>game_interface_width.autoscale</code> existed. | |||
It remains supported to avoid breaking published games. In tableview, it enables the same iframe scaling as <code>autoscale: "viewport"</code> and takes precedence over the configured autoscaling mode. | |||
Do not use it in new code. Existing games should test removing it and use <code>game_interface_width</code> instead. | |||
==== Mobile rendering performance ==== | |||
Large transformed interfaces can crash iOS browsers during pinch zoom. See [https://boardgamearena.com/bug?id=229359 BGA bug #229359] and [https://bugs.webkit.org/show_bug.cgi?id=172206 WebKit bug #172206]. | |||
Reduce the risk: | |||
* keep interface dimensions reasonable; | |||
* reduce image pixel dimensions and file sizes; | |||
* avoid unnecessarily large sprite sheets; | |||
* limit large fixed or transformed elements; | |||
* avoid unnecessary animation, canvas, and WebGL rendering; | |||
* test through <code>/tableview</code>, including pinch zoom on iOS. | |||
== Touchscreen compatibility == | |||
BGA adds <code>touch-device</code> to <code>#ebd-body</code> when it detects a touchscreen, and <code>notouch-device</code> otherwise. | |||
'''CSS :hover''' | '''CSS <code>:hover</code>''' | ||
Touch devices have no persistent mouse cursor. Some emulate <code>:hover</code> after a short touch, which can block the intended interaction. Prefix hover-only rules with <code>.notouch-device</code> when they should not apply to touchscreens. | |||
'''Tooltips''' | '''Tooltips''' | ||
Do not make required information available only through hover. Provide a touch-accessible alternative. | |||
'''Mouse events''' | '''Mouse events''' | ||
Do not rely only on mouse-specific events such as <code>mouseover</code>. Prefer the [https://developer.mozilla.org/en-US/docs/Web/API/Pointer_events Pointer Events API], which supports mouse, touch, and pen input. | |||
'''Drag | '''Drag and drop''' | ||
Common approaches: | |||
* | * [https://developer.mozilla.org/en-US/docs/Web/API/Pointer_events Pointer Events API] | ||
** | ** Example: https://codepen.io/VictoriaLa/pen/MWOgYYZ | ||
** | ** Game example: Century | ||
* | * [https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API Native HTML drag and drop] | ||
** | ** Example: https://codepen.io/VictoriaLa/pen/rNGXKxj | ||
** | ** Game example: Patchwork | ||
Add <code>touch-action: none</code> only to elements where you handle touch or pointer gestures and need to suppress native scrolling or zooming. | |||
[[Category:Studio]] | [[Category:Studio]] | ||
Revision as of 16:20, 23 July 2026
Board Game Arena supports mobile phones and tablets. Most games are already playable on touch devices, but their layout and interactions still need to work on narrow screens.
Declare your interface minimum width
game_interface_width.min is the smallest logical width at which your game remains usable. The default is 740 pixels.
Declare it in gameinfos.jsonc:
"game_interface_width": {
// Smallest usable width. Default: 740
"min": 540,
// Default: true
"autoscale": true
}
The declared width must actually work. If you declare 540 pixels, the complete interface must remain usable at 540 pixels.
Keep the minimum as low as reasonably possible. Large values require stronger scaling on phones, make content smaller, and increase rendering work. Use fluid layouts and CSS media queries instead of declaring a large fixed width.
Below 490 pixels, player panels may no longer use a two-column mobile layout.
Examples:
- In Can't Stop, the dice are moved below the board on narrow screens:
@media only screen and (max-width: 990px) {
#dicechoices {
left: 180px;
top: 530px;
}
#cantstop_wrap {
height: 900px;
width: 550px;
}
}
- In Seasons, panels normally displayed to the right of the board are moved below it:
@media only screen and (max-width: 970px) {
#board {
float: none;
margin: auto;
}
.seasons_rightpanel {
margin-left: 0;
}
}
On mobile, BGA moves player panels above the game and adds mobile_version to #ebd-body. The desktop layout uses desktop_version. Use these classes for layout-specific CSS.
Autoscale
game_interface_width.autoscale controls what happens when the available width is smaller than min. It accepts true, false, or "viewport". The default is true.
The examples below use a 740-pixel game displayed in 390 pixels of available space.
autoscale: true
BGA applies CSS zoom to the game content. In the example, the scale is approximately 53%.
The game content scales independently from the surrounding BGA interface:
- the top bar and tableview chat keep their normal size;
- the action bar and player panels use separate framework scaling on very narrow screens;
- standard BGA dialogs and tooltips generally keep their normal size;
- overlays inside the game area inherit the game zoom.
This is the default mode and should suit most fixed-width games.
Coordinates and animations
Browsers do not return consistent geometry for elements using CSS zoom. For custom positioning inside the zoomed game area, use:
const rect = this.getBoundingClientRectIgnoreZoom("my-element");
It returns logical, unscaled coordinates. BGA animation and positioning helpers already account for framework zoom.
Use the native getBoundingClientRect() when you need the visual position in the browser viewport, such as for an overlay outside the zoomed game area.
autoscale: false
BGA does not scale the game area.
Use this for responsive games or games with their own scaling system, such as BgaZoom. A fixed 740-pixel layout displayed in 390 pixels will otherwise overflow horizontally and may require scrolling.
autoscale: "viewport"
This mode scales the whole game document through a wider logical viewport.
Previously, when game pages were opened directly, BGA set the document viewport width and let the mobile browser fit it to the screen.
Games are now normally opened through /tableview. The game runs in an iframe, and its viewport cannot resize that iframe. Tableview emulates the same result by laying out the iframe at the requested width and applying transform: scale(...) to it.
In the example, the iframe is laid out at 740 pixels and displayed at approximately 53% scale. The game area and the BGA controls inside the iframe are scaled together.
CSS zoom participates in layout. transform: scale(...) scales after layout and usually creates a composited layer. Transforming a large iframe can be expensive on mobile devices.
Prefer autoscale: true or a responsive layout unless viewport scaling is required for compatibility.
Legacy default_viewport
Some older games contain code such as:
this.default_viewport = "width=740";
default_viewport started as internal framework state. Games later used it as an undocumented viewport override before game_interface_width.autoscale existed.
It remains supported to avoid breaking published games. In tableview, it enables the same iframe scaling as autoscale: "viewport" and takes precedence over the configured autoscaling mode.
Do not use it in new code. Existing games should test removing it and use game_interface_width instead.
Mobile rendering performance
Large transformed interfaces can crash iOS browsers during pinch zoom. See BGA bug #229359 and WebKit bug #172206.
Reduce the risk:
- keep interface dimensions reasonable;
- reduce image pixel dimensions and file sizes;
- avoid unnecessarily large sprite sheets;
- limit large fixed or transformed elements;
- avoid unnecessary animation, canvas, and WebGL rendering;
- test through
/tableview, including pinch zoom on iOS.
Touchscreen compatibility
BGA adds touch-device to #ebd-body when it detects a touchscreen, and notouch-device otherwise.
CSS :hover
Touch devices have no persistent mouse cursor. Some emulate :hover after a short touch, which can block the intended interaction. Prefix hover-only rules with .notouch-device when they should not apply to touchscreens.
Tooltips
Do not make required information available only through hover. Provide a touch-accessible alternative.
Mouse events
Do not rely only on mouse-specific events such as mouseover. Prefer the Pointer Events API, which supports mouse, touch, and pen input.
Drag and drop
Common approaches:
- Pointer Events API
- Example: https://codepen.io/VictoriaLa/pen/MWOgYYZ
- Game example: Century
- Native HTML drag and drop
- Example: https://codepen.io/VictoriaLa/pen/rNGXKxj
- Game example: Patchwork
Add touch-action: none only to elements where you handle touch or pointer gestures and need to suppress native scrolling or zooming.