I want to apply a transform using the height of the screen as a variable in a calculation:
.rotated {
--viewport-width: 100dvw;
--viewport-height: 100dvh;
transform-origin: top right;
transform: rotate(90deg) scale(calc(var(--viewport-height) / var(--viewport-width))) translateX(100%);
bottom: calc(-1 * var(--viewport-width) * var(--viewport-width) / var(--viewport-height) - var(--viewport-height));
}
But macOS Safari 18 doesn't give the correct values for vh-style units after pointerlock has been activated.
When you activate pointerlock, macOS Safari 18 shows a banner:
Your mouse pointer is hidden. Press Esc (Escape) once to dismiss this banner. Press Esc again to reveal your mouse pointer.
When you press escape (or, in my demo, click to end pointerlock mode) the banner disappears, but CSS values like 100vh still report the height that the viewport was when the banner was there. So there is a white bar along the bottom of the page the same height that the banner was.
Here's a singlepage HTML file that demonstrates the issue:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<style>
* {
margin: 0;
padding: 0;
}
#container {
height: 100dvh;
width: 100dvw;
background-color: blue;
}
</style>
</head>
<body>
<div id="container"></div>
<script>
document.addEventListener('click', () => {
if (document.pointerLockElement === document.body) {
document.exitPointerLock();
} else {
document.body.requestPointerLock();
}
});
</script>
</body>
</html>
How can I use the CSS/JavaScript/HTML I have control of to solve this issue?
Using top and bottom instead of vh makes the div always draw full-screen:
#container {
/* height: 100dvh; */
position: absolute;
top: 0;
bottom: 0;
width: 100dvw;
background-color: blue;
}
But I don't know how to work around the browser issue, for example if I could get the distance between the y-coordinate bottom: 0 represents and the y-coordinate top: 0 represents, I guess I could put that in the calculation instead, but I don't know how to do that.
That pointerlock banner fires a resize event which can be used to change CSS variables.
This version fixes the problem to the naked eye:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<style>
:root {
--viewport-height: 100vh;
}
* {
margin: 0;
padding: 0;
}
#container {
height: var(--viewport-height);
width: 100vw;
background-color: blue;
}
</style>
</head>
<body>
<div id="container"></div>
<script>
document.addEventListener('click', () => {
if (document.pointerLockElement === document.body) {
document.exitPointerLock();
} else {
document.body.requestPointerLock();
}
});
function updateVh() {
document.documentElement.style.setProperty('--viewport-height', `${window.innerHeight}px`);
window.setTimeout(() => {
document.documentElement.style.setProperty('--viewport-height', '100vh');
}, 10);
}
window.addEventListener('resize', updateVh);
</script>
</body>
</html>