How to get the value of phone notches/environment variables `env()` in JavaScript (from CSS)
Since Apple introduced the iPhone X there have been a number of further devices that also make use of a ‘notched’ display; a cut out that stops a uniform rectangle canvas for us to work with.
To aid working with this notch, Apple promoted the use of environment variables in CSS. I’ve covered that before.
Brief overview
Much like the syntax of custom properties you can obtain the value of environment variables using env()
in CSS like this:
margin-top: env(safe-area-inset-top);
It’s worth knowing that, where supported, you can also use make use of max
to get minimum value. For example,
@supports(margin: max(0px)) {
margin-top: max(env(safe-area-inset-top), 20px);
}
More on that on the WebKit blog.
So, problems in CSS are largely solved and well documented. Not so much in JavaScript.
The problem: how to access environment variables in JavaScript
I was building something where I needed to access the value of the environment variable/notch size in JavaScript. I was using translateY
on an element to move it up the page and needed to factor in phone notches. I wanted to use the full device canvas but make allowances for the safe area when positioning an element.
At first I thought I could do something like this to get the value and then factor it into calculations accordingly:
getComputedStyle(element).getPropertyValue('env(safe-area-inset-top)');
But to no avail. I read the specification and noted there was an issue filed for this very situation: https://drafts.csswg.org/css-env–1/#issues-index
I also posted on the GitHub issues: https://github.com/w3c/csswg-drafts/issues/2732 and tried the suggestion there: https://github.com/w3c/csswg-drafts/issues/2732#issuecomment–525414818 but to no avail.
Thankfully, Dean Jackson of WebKit (one of the specification authors) came through with a lovely clean solution that seems so obvious once you hear it!
The solution
You can set the values of an environment variable to a CSS Custom Property and then just read that value in with JavaScript. To exemplify, we can add them in the CSS here:
:root {
--sat: env(safe-area-inset-top);
--sar: env(safe-area-inset-right);
--sab: env(safe-area-inset-bottom);
--sal: env(safe-area-inset-left);
}
And then in script read them back like this:
getComputedStyle(document.documentElement).getPropertyValue("--sat")
Brilliant! It’s almost like someone had thought this through originally! 😉
Argh!!! I want this to work so bad! All I’m getting returned is 0px, no matter what device/orientation I test with. Does this still work now (Sept. 2020) in iOS 13 and 14?