Responsive Edits
Every edit you save in the Visual Editor can be scoped to a viewport range. The snippet runtime checks the current window.innerWidth on each page load and only applies edits that match.
Viewport presets
The editor ships with four presets plus a custom range. Pick from the Viewport dropdown when editing an element.
- MOBILE: Applies when
window.innerWidthis ≤ 767px. - TABLET: Applies when
window.innerWidthis between768pxand1023pxinclusive. - DESKTOP: Applies when
window.innerWidthis ≥ 1024px. - ALL: Applies on every viewport. This is the default for new edits.
- CUSTOM(min, max): A user-defined range. Set the minimum and maximum in pixels; either bound is optional.
In the edit form, the Viewport dropdown lists the four presets and a Custom range... option. Picking custom opens two numeric inputs labelled Min width (px) and Max width (px). A live indicator at the bottom of the panel shows the current browser width so you can verify your edit will apply.
How the runtime applies viewport-scoped edits
When the snippet runs, it evaluates each change against the current window width. Edits whose viewport scope matches are applied immediately. The runtime also listens for resize events and re-evaluates the change list, so rotating a phone or resizing a desktop window keeps the right edits active.
The conceptual runtime logic looks like this:
type ViewportTarget = 'ALL' | 'MOBILE' | 'TABLET' | 'DESKTOP' | 'CUSTOM'interface ViewportScopedChange { viewport: ViewportTarget customMinWidth: number | null customMaxWidth: number | null}function shouldApply(change: ViewportScopedChange, width: number): boolean { switch (change.viewport) { case 'MOBILE': return width <= 767 case 'TABLET': return width >= 768 && width <= 1023 case 'DESKTOP': return width >= 1024 case 'ALL': return true case 'CUSTOM': { const { customMinWidth: min, customMaxWidth: max } = change return (min === null || width >= min) && (max === null || width <= max) } }}Layering edits across viewports
You can save multiple edits to the same element with different viewport scopes. For example, you might want a short headline on mobile and a long one on desktop. The editor will create two separate changes (one scoped to MOBILE, one scoped to DESKTOP) and the runtime applies whichever matches the current width.
If your site uses bespoke breakpoints (e.g. a redesign at 1280px), switch to CUSTOM(min, max) and match your site's existing breakpoint exactly. Mixing the editor's presets with your CSS breakpoints can leave gaps where no edit applies.
Previewing viewports
The editor's top bar exposes four canvas sizes through a labeled device switcher: a segmented control in the centre of the top bar with Desktop, Tablet, Mobile, and Custom segments. These aren't separate modes: your page always renders inside the same workbench canvas, and picking a size just changes the canvas's dimensions. Desktop fills the available area; Tablet, Mobile, and Custom size the canvas to the device viewport, so media queries fire as they would on the actual device, touch detection behaves like the device, and window.innerWidth reports the canvas dimensions rather than the host window's.
A label at the end of the switcher spells out the active size so you never have to guess from an icon: Tablet 820, Mobile 390. Desktop has no fixed width (it fills whatever space the workbench has), so it reads just Desktop. The segments themselves are compact icons that never change size or move, so you can click from one size straight to the next without the buttons shifting under your pointer. The rotate button sits in the same place for every size and only works for Tablet, Mobile, and Custom.
- Tablet renders an 820 × 1180 pixel canvas.
- Mobile renders a 390 × 844 pixel canvas.
- Custom exposes a width × height input pair: type any width between 320 and 4096 and the canvas resizes after a short debounce.
- The rotate button next to the segmented control swaps width and height, simulating landscape orientation. It appears whenever a non-desktop size is active.
Because there's only one canvas, switching sizes never reloads the page or resets the editor: your selection and unsaved edits carry across every size. Edits are persisted to the same change set no matter which size you captured them at, and there's no "snap back to Desktop" to catch you out.
The "Editing … only" badge
Picking a device size does one more thing beyond resizing the canvas: new edits are scoped to that viewport. So the top bar tells you, right next to the switcher, whenever that's about to happen:
- Editing Tablet only: while the Tablet size is active.
- Editing Mobile only: while the Mobile size is active.
- Editing custom width: while a Custom size is active (custom is a width range, not a single pixel value).
Only new edits pick up the active viewport: existing changes keep whatever scope they were saved with. Switch back to Desktop and the badge disappears: edits made at Desktop apply to all devices. The badge uses the same vocabulary as the viewport chips on the change cards, so a change made under "Editing Mobile only" shows a matching Mobile chip in the changes list.
When the editor launches from the snippet already on your page, the device canvas is a same-origin iframe (your page framing itself), so it loads without any extension or header rewriting. Because the frame and the host share an origin, media queries, touch detection, and window.innerWidth all report the device dimensions correctly. The retained browser extension path additionally strips frame-busting response headers (X-Frame-Options and the frame-ancestors directive of Content-Security-Policy) for un-snippeted or cross-origin pages; that rewrite is scoped to the active tab and removed automatically when you flip back to Desktop or close the editor.
A small number of pages set a strict frame-ancestors 'none' policy or run JavaScript that detects being framed and forces a top-level navigation. When the editor can't mount the device canvas, it automatically falls back to overlay mode: it edits the live page directly and shows a notice explaining why. In overlay mode the device switcher still works: picking Tablet, Mobile, or Custom narrows the live page to a real fixed-width centred column at the exact device width, never a silent snap back to Desktop. Because the page isn't inside a true device frame, its media queries don't re-evaluate at the narrow width, so a persistent notice stays on the canvas while a non-desktop size is active: "Simulated width: this site blocks live device framing, so its layout may not reflow." Use it for width checks, but verify breakpoint-dependent layout on a page that allows framing. The fix on the customer side is to relax the framing policy for the editor origin or remove the legacy frame-bust script.
Changing the viewport scope of an existing edit will not retroactively update sessions that already loaded the page. Visitors who were bucketed under the previous scope will continue to see the variation until they reload. This is rarely a problem for marketing tests, but worth knowing during QA.
Related
- Selectors: pair viewport scoping with a stable selector for the most reliable test.
- Execution order: see where viewport evaluation sits in the snippet lifecycle.