4

How to get the dimensions of the fullscreen (minimal-ui) view when not in fullscreen?

This is what the screen properties report:

window.screen.height; // 568 (Thats the screen height)
window.screen.availHeight; // 548  (???; Unknown dimension. Note, that is it not reporting the available space as per the spec.)
window.document.documentElement.clientHeight; // 460 (Thats the window size when not in fullscreen.)

When in fullscreen, the window.innerHeight is 529, which is the number I am trying to derive prior to entering the fullscreen mode.

Image illustrates the state of the screen I am referring to:

in fullscreen

In iOS 8, it is entered with a "touch-drag down" gesture.

Gajus
  • 69,002
  • 70
  • 275
  • 438
  • What does `window.innerHeight` report when not in fullscreen? – Martin Ernst Nov 07 '14 at 13:22
  • Reports the current viewport size, which is 460, ie. equivalent to `window.document.documentElement.clientHeight`. – Gajus Nov 07 '14 at 13:23
  • 2
    `availHeight` is the portion of the screen that can be used, the 20 pixels deducted there should be height of the status line. Your problem is that "full screen" isn't really full screen - there is still the address bar and it seems to occupy the 19 pixels you are missing. – Wladimir Palant Nov 11 '14 at 13:39
  • That is what `availHeight` is supposed to report. Though, if you test it, the real `availHeight` is greater than reported. I have written an entire library that uses iOS spec inspection to determine the "fullscreen" dimensions. https://github.com/gajus/scream The library does its job, though it relies on hardcoded values, which is something I'd like to avoid. – Gajus Nov 11 '14 at 15:10
  • Testing on iphone 6 plus with IOS 8.0.2 ```window.screen.availWidth = window.screen.height = 667``` and ```window.screen.availHeight = window.screen.width = 375``` no matter what the screen orientation is or view is full or minimal. – svassr Feb 06 '15 at 20:45
  • Testing on iphone 6 plus with IOS 8.0.2 ```window.screen.availWidth```, ```window.screen.height```, ```window.screen.availHeight```, ```window.screen.width``` also don't consider scale – svassr Feb 06 '15 at 20:55
  • ```window.document.documentElement.clientHeight ``` and ```window.innerHeight``` both consider scale and orientation – svassr Feb 06 '15 at 20:56
  • ```window.innerHeight``` only is considering ui view ```minimal```or ```full```. – svassr Feb 06 '15 at 20:59

1 Answers1

1

To clarify, the window.screen.availHeight reflects the maximum height the browser window, including all the toolbars, can have. If you look at the picture below, you see that 548 is just the height of the whole browser, without the iOS menubar. So, the availHeight property is not supposed to show the available space for the content, but the whole browser. It's used for desktop browsers, to detect things like the browser is maximized or not, by checking window.outerHeight against window.screen.availHeight.

iPhone Dimensions

But about getting the minimal UI height, right before getting into it. There's no standard property in the spec for it, as it's just a iOS only behavior. Apple could have put some non-standard properties to expose these information. But as I have checked the window and window.screen objects, there's nothing related. That's for the feasiblity, for now.

As a sidenote, what is the difference between knowing the new viewport size with resize event and knowing the would-be size in advance? The amount of work that can be done, prior to the resize event, should always be minimal, and if a layout change should happen, it should happen after the resize. So, knowing the numbers in advance, shouldn't help that much.

Consider this scenario that a user opens a webpage, and starts scrolling immediately. If we know the numbers before, there's nothing that we can do for the initial render of the screen, as it's not a minimal UI. Whatever that should be done, must begin rightaway after the user starts scrolling.

Now besides this, there's one other resize event that just looks like the minimal ui. On the iPad, when you have more than one tab, the height shrinks a bit more, to show the tabs. So, when the user closes the only other tab, the current page, gets a bit taller, and triggers a resize event too. But this new height is different from the height of the minimal UI. This suggests that this minimal ui, is just another boost in the height, not a Fullscreen-API-like mode.

So, if a page is dependent on the height, there's just too many possible changes to bear in mind. Hard-coding would be just a short-term solution, one day you won't be able to test all those devices.

But, I also should say that there's a downside to the resize event, it triggers after getting into the minimal ui, which may be too late. So, when the height starts to grow, there's no event to know about it. That's where I believe some custom fluid UIs may need to start an animation to change the sizes. In this case, to know about the beginning of this event, one may use an interval checking on the innerHeight, which will start to change immediately.

Anyway, if there is a necessary usecase for knowing the numbers beforehand any scrolling, I believe it's not available through the CSSOM, yet.

Edit:

Detecting minimal-ui is another thing, that still knowing the dimensions is not needed. Using Touch events, you can detect if the view has entered the minimal UI or not.

Checking the innerHeight in touchstart, touchmove and touchend events can help to detect the minimal ui. The naive approach is to check if at the end of the touch the innerHeight has increased or not. This will work for most of the cases, but it has a problem, if the user stops touching right in the middle of minimal-ui transition, we cannot be sure if we will enter the minimal UI. Checking against the last reported height by touchmove can help to check if we will revert to the default view.

Anyway, You may check the code below to see how it works. It has bugs and can be improved, but you'll get the idea. I didn't put it on codepen, as you couldn't scroll the entire page there.

<!doctype html>
<html>
    <head>
        <meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=no">
        <style>
        div {
            position: fixed;
            left: 10px;
        }
        #dd1 {
            top: 10px;
        }
        #dd2 {
            top:30px;
        }
        #dd3 {
            top: 50px;
        }
        </style>
    <body>
        <div id="dd1">Start: <span id="d1"></span></div>
        <div id="dd2">Move: <span id="d2"></span></div>
        <div id="dd3">End: <span id="d3"></span></div>
        <section style="position:relative;height:3000px;"></section>
        <script>
        var d1 = document.querySelector("#d1");
        var d2 = document.querySelector("#d2");
        var d3 = document.querySelector("#d3");
        var start_height=window.innerHeight;
        var cur_height;
        var end_height;
        var normal_state=true;
        var entered_minimal_ui=false;
        //window.addEventListener("touchstart", start_handler, false);
        window.addEventListener("touchmove", move_handler, false);
        window.addEventListener("touchend", end_handler, false);
        document.ontouchstart = control_touching;
        d1.textContent=start_height;

        function move_handler() {
            if(cur_height>start_height) {
                // we *may* enter the minimal-ui, but it's not final yet
                d2.textContent="I detected minimal-ui faster. (Current: "+cur_height+")";
                normal_state=false;
            }
            cur_height=window.innerHeight;
        }
        function end_handler() {
            end_height=window.innerHeight;

            if(end_height>start_height && end_height>=cur_height) {
                d3.textContent="Hello minimal-ui. (End: "+end_height+")";
                normal_state=false;
                entered_minimal_ui=true;
            }
            else if(!entered_minimal_ui) {
                d3.textContent="We didn't enter minimal-ui. Reverting.";
                normal_state=true;
            }
        }
        function control_touching() {
            document.ontouchstart = function(e){ 
                if(normal_state) {
                    return true;
                }
                else // just for testing
                    e.preventDefault();
            }
        }
        </script>
    </body>
</html>

References:

Kamyar Infinity
  • 2,711
  • 1
  • 21
  • 32
  • Test `window.screen.availHeight` variable. You will see that it returns neither of the values that you refer to. As I have mentioned in the comments, these dimensions can be derived using proportions (https://github.com/gajus/scream). The problem with this approach is that it relies on device inspection and hardcoded values. At the end, iOS implementation of the `window.screen.availHeight` is flawed. Therefore, whatever the solution is, it must not rely on this variable. – Gajus Nov 12 '14 at 06:06
  • Yes, I've checked `window.screen.availHeight` on iOS8. I checked on iPad2, it gives 748px, which is the 768px screen height minus the 20px menubar. It doesn't take the orientation into account. Anyway, that's right, availHeight won't be a solution at all. – Kamyar Infinity Nov 12 '14 at 11:39
  • This will explain why I need to calculate these dimensions prior to user entering the minimal-ui, http://stackoverflow.com/a/26884561/368691 – Gajus Nov 12 '14 at 12:35
  • I see, that's an interesting usecase. But again I can say, knowing the dimensions is not needed. You may check my new edit to see why. – Kamyar Infinity Nov 12 '14 at 18:03
  • The script cannot rely on innerHeight/innerWidth properties because these (as you have illustrated yourself) are dynamic properties. There is no way (using method of comparison) to deduct if page is loaded in minimal view or full view using these variables because you do not have a fixed offset. The importance of this is highlighted in the description of the bounty. – Gajus Nov 12 '14 at 18:22
  • Actually, there's no way to load a page in minimal-ui on iPhone or iPad with iOS8. Reloading requires going back to the full view. Also, reopening Safari just loads the page in full view, I tested your demo with Brim, too. Anyway, you're right my answer relies on innerHeight. – Kamyar Infinity Nov 13 '14 at 00:56
  • If you navigate from one page to another using Brim, the minimal-ui persists. If you change the orientation, the minimal-ui persists. – Gajus Nov 13 '14 at 05:01
  • Changing orientation persists minimal-ui, iOS does that itself. So, my snippet works there, too. Loading a new page, resets Safari to full view, that's what happens with Brim, too. The only resort could be ajax-loading the content. As minimal-ui is browser-wide, you can't even keep it when switching back from another full-view tab. Also you may try this, go into minimal-ui from another tab, navigate to your Brim demo by pinching. You'll be in minimal-ui, but your demo won't get it and you can escape it. – Kamyar Infinity Nov 13 '14 at 14:21