Output settings globals

The output settings preview your page under other conditions without changing the authored source: a fixed viewport with zoom and Auto-fit, a forced colour scheme, native prefers-* overrides, text direction, language, root font size and animation speed. The Output settings dialog (Output settings) sets them with controls. The globals on this page set the same things from code, in the playground's console or in io.eval.js.

Geometry and zoom getters are synchronous. The getters of the colour scheme, the native preferences, the text settings and the animation speed return Promises, so read them with await. Setters validate at once. To confirm a change, assign it and then await the getter: orm = 'reduce'; await orm. Every setting is saved in the URL and applied again after each output reload.

Syntax

js
ovp = [390, 844]            // an exact CSS viewport; media queries see 390 × 844
ovfit = true                // refit the zoom whenever the panel resizes
fitOVP()                    // fit the viewport into the panel once
oz = 0.75                   // zoom; turns Auto-fit off
await setOAR(16, 9)         // move the split so that the output is 16:9
ocs = 'dark'; await ocs     // force dark mode in the output
orm = 'reduce'; await orm   // native prefers-reduced-motion
odir = 'rtl'; olang = 'ar'  // text direction and language
ofs = 20; oas = 0.5         // root font size in px; animation speed

Summary

GlobalYou assignYou readResetURL key
ovp[width, height], positive integersThe array, or undefined for the responsive Panelovp = undefinedovp=WxH
ovfitA booleanA booleanovfit = falseovfit=1
fitOVP()A functionAn object, synchronously
ozA number of 0.1 or moreThe numberoz = 1oz
oar[w, h], a ratio or "W:H"[w, h]
setOAR()A functionA Promise of a result
ocs'light' or 'dark'A Promise of 'light', 'dark' or undefinedocs = undefinedocs
orm'reduce' or 'no-preference'A Promise of the value or undefinedorm = undefinedorm
opc'more', 'less' or 'no-preference'A Promise of the value or undefinedopc = undefinedopc
ort'reduce' or 'no-preference'A Promise of the value or undefinedort = undefinedort
ord'reduce' or 'no-preference'A Promise of the value or undefinedord = undefinedord
odir'ltr' or 'rtl'A Promise of the value or undefinedodir = undefinedodir
olangA language tagA Promise of the tag or undefinedolang = undefinedolang
ofsA number of pixels, 0 or moreA Promise of the number or undefinedofs = undefinedofs
oasA number, 0 or moreA Promise of the numberoas = 1oas

Viewport and zoom

ovp

The fixed viewport of the output, in CSS pixels. Reading returns a copy, [width, height], or undefined for the responsive Panel.

Assigning [w, h] sizes the output frame to exactly w × h CSS pixels, so media queries, innerWidth and innerHeight in the output see that size. The stage is scaled by oz, and the output pane becomes scrollable. Both numbers must be safe integers greater than 0, or the setter throws TypeError('Output viewport requires [width, height] in positive integer CSS pixels, or null for Auto.'). null or undefined restores the Panel and turns Auto-fit off. If the browser cannot honour the size, the setting reports Browser viewport is W × H CSS px; requested W × H.

Changing ovp aborts a running setOAR() and cancels a pending pin image capture. It is stored in the URL as ovp=WxH, for example ovp=390x844. See Viewport presets.

ovfit

A boolean value: Auto-fit. While it is true and a viewport is set, the zoom is fitted again on the next animation frame whenever the output panel changes size. Assigning oz turns it off. It is false by default, and stored in the URL as ovfit=1.

fitOVP()

Fits the viewport into the panel once, and returns an object at once: { ok, reason?, viewport, available: { width, height }, requiredZoom, minimumZoom: 0.1, previousZoom, zoom }. It sets oz to floor(min(availableWidth / w, availableHeight / h) × 100) / 100 and does not turn Auto-fit off. When ok is false, reason says why:

'auto-viewport'

There is no fixed viewport: ovp is undefined.

'empty-pane'

The output panel has no usable space.

'viewport-size'

The browser could not apply the requested viewport size.

'minimum-zoom'

The viewport would need a zoom below 0.1.

oz

The zoom factor of the output: 1 when unset. Assigning a number stores Math.max(0.1, Math.round(n × 100) / 100): two decimals, a minimum of 0.1 and no maximum. Assigning it turns Auto-fit off and shows a zoom badge, such as .5, unless the zoom is 1. Reset it with oz = 1. Stored in the URL as oz.

In Panel mode the frame is sized to the panel divided by the zoom, so zooming out gives the output a larger CSS viewport, like browser zoom. With a fixed viewport only the displayed size changes. o.getDimensions() includes the zoom.

Note: null and undefined are not resets for oz. oz = null is treated as 0 and zooms to 0.1. Assign a number. The zoom keys, such as Alt+Ctrl+=, are listed in Keyboard shortcuts.

Viewport presets

The presets of the dialog are plain values of ovp. They are CSS layout reference sizes, not device emulation: the device pixel ratio, browser controls, safe areas, touch and device posture are not emulated, and the Duo and Samsung sizes are approximate.

Presetovp
og:image[1200, 630]
iPhone 18 Pro Max[440, 956]
iPhone Duo, cover and inner[466, 678] and [890, 626]
Galaxy S26 Ultra[384, 832]
Fold8 Ultra, cover and inner[412, 960] and [860, 954]
Fold8, cover and inner[500, 789] and [980, 740]

Aspect ratio

oar

The aspect ratio of the output frame as reduced integers, [w, h]. It comes from the CSS size of the frame when ovp is set, and from o.getDimensions() otherwise. It is undefined on error.

Assigning Experimental accepts [w, h] with both greater than 0, a positive number r (meaning r:1), or a string such as "W:H", "W/H" or a numeric string. It starts setOAR(w, h) and does not wait for it: an abort is ignored, other errors are logged, and an invalid value is ignored without a message.

setOAR()

await setOAR(w, h, options) moves the split between the input and the output until the aspect ratio of the output is as close to w:h as the panes allow. It clears the fixed viewport and Auto-fit first: use ovp when you need exact dimensions. w and h are positive numbers, and the only option is signal, an AbortSignal.

It measures the output at the current position and at both extremes, 0 and 100. When the target is at or beyond the reachable range, it jumps to the nearer extreme (method: 'extreme'). Otherwise it bisects, with at most 32 steps, and then probes positions around the best one (method: 'search'). Every probe waits two animation frames.

It returns a Promise of a result:

js
{ ok, aborted, reason, diff,
  desired:  { ratio, w, h },
  achieved: { ratio, w, h },
  attempts,
  position: { start, best, end, max },
  bracket:  { inc, min, max, method },
  epsilon:  { pos, rel },
  durationMs }

ok is true when the call was not aborted and both ratios are finite. diff is the achieved ratio minus the desired one. achieved.w and achieved.h are the reduced integers of the aspect ratio of the output, not pixels. The other members record the search.

Failures that resolve

ok: false with reason: 'invalid:args' when w or h is not a finite positive number, or reason: 'busy' when another setOAR() is running.

Aborts

An abort rejects with the result object, not with an Error: aborted: true, and a reason that starts with aborted:, such as aborted:pre, aborted:init, aborted:bisection, aborted:refine or aborted:final. The signal aborting, for example AbortSignal.timeout(2000), or a change of ovp during the run triggers it. Use .catch(r => r) to get the partial result. An uncaught abort is written to io.eval.json as [object Object].

No embedded output

Every call rejects with a TypeError, even one with invalid arguments.

Browsers pause animation frames in background tabs, so keep the playground tab visible while setOAR() runs.

Appearance and preferences

ocs

The colour scheme of the output. Reading returns a Promise of 'light', 'dark' or undefined for System, read from the inline color-scheme of the root of the output document, ignoring an only keyword. Always await ocs.

Assigning 'light', 'dark' or undefined writes an inline color-scheme on the output frame and on the root of every connected output document. null and undefined write light dark, which is System. In the inline output, both prefers-color-scheme and light-dark() follow it; in output tabs and popups there is no frame, so only the root of the document is set. The setter does not check the value, so assign only those three. The stored value is applied again after every full output load, and it is stored in the URL as ocs. Output: Color Scheme (Alt+Ctrl+C / Alt+⌘+C) cycles System, dark and light.

orm

Native prefers-reduced-motion: 'reduce' or 'no-preference'.

opc

Native prefers-contrast: 'more', 'less' or 'no-preference'.

ort

Native prefers-reduced-transparency: 'reduce' or 'no-preference'.

ord

Native prefers-reduced-data: 'reduce' or 'no-preference'. It does not throttle the network or change Save-Data.

The four native preferences call navigator.preferences.reducedMotion, contrast, reducedTransparency and reducedData in the output, with requestOverride(value) or clearOverride(). They change real media queries and matchMedia(); the CSS and scripts of the page decide what changes, and nothing is simulated. They need native preference support: in Chrome 152, the version tested, that means the Experimental Web Platform features flag. Elsewhere the apply fails with This browser does not support this preference override. and the getter rejects with it.

Assigning undefined is System: it clears the override, so the real browser setting applies again. 'no-preference' is different: it overrides the browser to say that the user has no preference. How far an override reaches differs between browsers; in the tested playground it affected the output and not the editor.

Text and animation

odir

The text direction: 'ltr' or 'rtl'. It sets the dir attribute of the output's <html>. Resetting restores the authored attribute, but only if the page has not changed it since.

olang

A language tag, such as 'en' or 'ar': any trimmed string. It sets the lang attribute of the output's <html> and restores the authored one on reset. Nothing is translated.

ofs

The root font size, in CSS pixels: a number of 0 or more. It adds a style sheet with :root { font-size: Npx !important } to the output and then checks the computed size. It changes relative units such as rem and em, not fixed-pixel text. If the page wins, the apply fails with The document prevents overriding its root font size.

oas

The animation speed: a multiplier of 0 or more, 1 by default. It multiplies the playback rate of CSS animations, CSS transitions and Web Animations that it finds in each animation frame, in the output document, in its open shadow roots and in same-origin iframes. 0 holds animation time and 1 restores the authored rates. The play state and current time are not touched.

Not covered: JavaScript timers, requestAnimationFrame, canvas, video, animated images, SVG animation that is not a Web Animation, closed shadow roots and cross-origin frames. A new animation may advance briefly before it is found. Resetting restores the authored rates, and null or undefined also reset oas to 1.

How the settings behave

The following holds for the eight preview overrides: orm, opc, ort, ord, odir, olang, ofs and oas. ocs shares the Promise getter.

outputSettings and showOutputSettings()

outputSettings Experimental

An object that holds the state behind the eight preview overrides:

values

The values that were requested last.

capabilities

{ orm, opc, ort, ord }, booleans that are true only if every current output supports that override.

errors, status

The error messages per key, and the current status.

set(key, value)

Validates and applies any of the eight keys, or oz, ocs, ovp or ovfit, and returns a Promise that resolves to the confirmed value of the getter or rejects. It is stricter than the globals: set('oz', …) rejects a value that is not a positive, finite number with Zoom requires a positive finite number., and set('ocs', …) rejects anything but 'light', 'dark' and undefined with Color scheme must be light, dark, or undefined.

refresh()

Reads the settings from the outputs again.

showOutputSettings() Experimental

Opens the Output settings dialog, like the command Output: Settings.

Examples

A phone viewport, fitted once, in dark mode

Write this to io.eval.js. fitOVP() is synchronous, and ocs is awaited. The call returns [{ ok, … }, 'dark'].

js
ovp = [390, 844]; ocs = 'dark'; [fitOVP(), await ocs]

A page that reacts to a native preference

Open this page in the playground. Then run orm = 'reduce'; await orm in the console or in io.eval.js. The spinner stops, because the override reaches the page's own media query.

html
<style>
  :root { color-scheme: light dark; font: 1rem/1.5 system-ui; }
  main  { padding: 1rem; min-block-size: 50dvh; background: light-dark(oklch(98% 0 0), oklch(22% .02 250)); }
  .spin { display: inline-block; animation: spin 2s linear infinite; }
  @media (prefers-reduced-motion: reduce) { .spin { animation: none; } }
  @keyframes spin { to { rotate: 1turn; } }
</style>
<main>
  <p id=pref></p>
  <span class=spin>⟳</span>
</main>
<script>
  const q = matchMedia('(prefers-reduced-motion: reduce)');
  const show = () => pref.textContent = `prefers-reduced-motion: ${q.matches ? 'reduce' : 'no-preference'}`;
  q.onchange = show; show();
</script>

Reading a failure instead of throwing

The getter resolves to 'reduce', or to the message when the browser lacks navigator.preferences.

js
orm = 'reduce'; await orm.catch(e => e.message)

A right-to-left preview with a larger root size and slower animations

js
odir = 'rtl'; olang = 'ar'; ofs = 20; oas = .5; [await odir, await olang, await ofs, await oas]

Reset them with:

js
odir = olang = ofs = undefined; oas = 1

Aiming for 16:9 without letting an abort escape

js
await setOAR(16, 9, { signal: AbortSignal.timeout(2000) }).catch(r => r)

The playground applies ovp before ovfit, so this link opens with a 390 × 844 viewport fitted to the panel, and a dark output.

js
const html = `<h1>Hello</h1>`;
const href = `https://rtcode.io/x/#${new URLSearchParams({ '/': html, title: 'Phone preview', ovp: '390x844', ovfit: 1, ocs: 'dark' })}`;
// https://rtcode.io/x/#%2F=%3Ch1%3EHello%3C%2Fh1%3E&title=Phone+preview&ovp=390x844&ovfit=1&ocs=dark

Specifications

Not part of any specification. These globals are RTCode.io playground features. They preview features of the web platform: color-scheme and light-dark(), the prefers-* media features of Media Queries Level 5, the dir and lang attributes, and Web Animations. The native overrides use navigator.preferences, which a browser may not implement.

Availability

FeaturePlaygroundRTEdge.netNotes
ovp, ovfit, fitOVP(), oz, oar, setOAR()YesNoInline output only. They do not apply once the output is in its own tab or popup.
ocs, odir, olang, ofs, oasYesNoStandard platform features: CSS scale and color-scheme, constructed style sheets, Web Animations.
orm, opc, ort, ordPartlyNoNeed navigator.preferences. In Chrome 152 that is the Experimental Web Platform features flag.
outputSettings, showOutputSettings()YesNoExperimental.

See also