I am running puppeteer with headless mode off in order to automate and remotely control a visible Chromium browser on another computer.
Is there a way to trigger or emulate zooming on the browser just like in the UI menus or ctrl +
/crtl -
commands?
Injecting CSS or using the various documented scale commands does not fully replicate this as, for example, elements defined using vh
/vw
units do not get adjusted.
My current solution
Using viewport scale in Emulation.setDeviceMetricsOverride
works well for zooming out but it seems to be resizing a raster of the page rather than rendering at the target size, resulting in blurry text when zooming in.
Adjusting the viewport size and using Emulation.setPageScaleFactor
works well for zooming in however a pageScaleFactor of less than 1 seems to be ignored in my testing.
An issue with both of these solutions is that it requires knowing the width/height of the browser window in advance and relies on that not changing, rather than having a fluid viewport. I'm also not sure what other features of the standard browser zoom I am missing.
My code for zooming is now:
async applyFrameZoom(page, zoom) {
// page is a puppeteer.Page instance
// zoom is an integer percentage
const session = await page.target().createCDPSession();
let window = await session.send('Browser.getWindowForTarget', {
targetId: page.target()._targetId
});
let width = window.bounds.width;
let height = window.bounds.height;
if (!zoom || zoom === 100) {
// Unset any zoom
await session.send('Emulation.clearDeviceMetricsOverride');
await session.send('Emulation.resetPageScaleFactor');
} else if (zoom > 100) {
// Unset other zooming method
await session.send('Emulation.clearDeviceMetricsOverride');
// Zoom in by reducing size then adjusting page scale (unable to zoom out using this method)
await page.setViewport({
width: Math.round(width / (zoom / 100)),
height: Math.round(height / (zoom / 100))
});
await session.send('Emulation.setPageScaleFactor', {
pageScaleFactor: (zoom / 100)
});
await session.send('Emulation.setVisibleSize', {
width: width,
height: height
});
} else {
// Unset other zooming method
await session.send('Emulation.resetPageScaleFactor');
// Zoom out by emulating a scaled device (makes text blurry when zooming in with this method)
await session.send('Emulation.setDeviceMetricsOverride', {
width: Math.round(width / (zoom / 100)),
height: Math.round(height / (zoom / 100)),
mobile: false,
deviceScaleFactor: 1,
dontSetVisibleSize: true,
viewport: {
x: 0,
y: 0,
width: width,
height: height,
scale: (zoom / 100)
}
});
}
await this.frame.waitForSelector('html');
this.frame.evaluate(function () {
window.dispatchEvent(new Event('resize'));
});
}
Is there a better way to do this?