1. resize Event + devicePixelRatio Change
Code:
let lastPixelRatio = window.devicePixelRatio;
function checkResizePixelRatio() {
let currentPixelRatio = window.devicePixelRatio;
if (currentPixelRatio !== lastPixelRatio) {
resizeDprLog.textContent =
'The page zoom has changed. DPR: ' + currentPixelRatio;
}
lastPixelRatio = currentPixelRatio;
}
window.addEventListener('resize', checkResizePixelRatio);
resizeDprButton.addEventListener('click', checkResizePixelRatio);
Result:
Current DPR-
Previous DPR-
Resize events0
StatusWaiting
Zoom the page with Ctrl+/Ctrl- or use the buttons to inspect the current value.
2. Estimating Zoom from a Stored Baseline
Code:
// Initial zoom ratio
let originPixelRatio = localStorage.devicePixelRatio;
if (!originPixelRatio) {
originPixelRatio = window.devicePixelRatio;
if (Number.isInteger(originPixelRatio)) {
localStorage.devicePixelRatio = originPixelRatio;
}
}
let storedLastPixelRatio = originPixelRatio;
function estimateStoredZoom() {
let currentPixelRatio = window.devicePixelRatio;
let zoom = Math.round(1000 * (currentPixelRatio / originPixelRatio)) / 10;
storedZoomResult.textContent = 'The zoom ratio is: ' + zoom + '%';
storedLastPixelRatio = currentPixelRatio;
}
window.addEventListener('resize', estimateStoredZoom);
storedZoomButton.addEventListener('click', estimateStoredZoom);
Result:
Stored baseline-
Current DPR-
Estimated zoom-
Storage-
Waiting for a zoom or manual check.
3. matchMedia with a dppx Resolution Query
Code:
let mediaOriginPixelRatio = window.devicePixelRatio;
let mediaQueryList;
function mediaPixelRatioChanged() {
let currentPixelRatio = window.devicePixelRatio;
let zoom = Math.round(1000 * (currentPixelRatio / mediaOriginPixelRatio)) / 10;
matchMediaResult.textContent = 'The zoom ratio is: ' + zoom + '%';
mediaQueryList.removeEventListener('change', mediaPixelRatioChanged);
mediaQueryList = matchMedia('(resolution: ' + currentPixelRatio + 'dppx)');
mediaQueryList.addEventListener('change', mediaPixelRatioChanged);
}
mediaQueryList = matchMedia('(resolution: ' + mediaOriginPixelRatio + 'dppx)');
mediaQueryList.addEventListener('change', mediaPixelRatioChanged);
matchMediaButton.addEventListener('click', mediaPixelRatioChanged);
Result:
Watched query-
Matches now-
Current DPR-
Change events0
A resolution media query is watching for DPR changes.
4. outerWidth / innerWidth Ratio
Code:
function calculateOuterInnerZoom() {
let zoom = Math.round(1000 * (window.outerWidth / window.innerWidth)) / 10;
outerInnerResult.textContent =
'The current page zoom ratio should be: ' + zoom + '%';
}
window.addEventListener('resize', calculateOuterInnerZoom);
outerInnerButton.addEventListener('click', calculateOuterInnerZoom);
Result:
outerWidth-
innerWidth-
Ratio-
RiskSidebar sensitive
This estimate changes when browser chrome, sidebars, or docked developer tools affect innerWidth.
5. visualViewport and Gesture Zoom
Code:
function showGestureZoom() {
if (!window.visualViewport) {
visualViewportResult.textContent = 'visualViewport is not supported.';
return;
}
visualViewportResult.textContent =
'Gesture zoom ratio: ' + window.visualViewport.scale;
}
if (window.visualViewport) {
window.visualViewport.addEventListener('resize', showGestureZoom);
}
visualViewportButton.addEventListener('click', showGestureZoom);
Result:
visualViewport.scale
-
Checking support...
On desktop browser zoom this usually stays at 1. On mobile pinch zoom it can change.
6. Final Summary
Code:
const methods = [
{ name: 'resize + devicePixelRatio', bestFor: 'Desktop zoom change detection' },
{ name: 'matchMedia resolution query', bestFor: 'Targeted desktop DPR change detection' },
{ name: 'outerWidth / innerWidth', bestFor: 'Rough desktop cross-checks' },
{ name: 'visualViewport.scale', bestFor: 'Mobile gesture zoom' }
];
summaryResult.innerHTML = methods.map(method =>
'<li><strong>' + method.name + '</strong>' + method.bestFor + '</li>'
).join('');
Result: