androidhtmlgoogle-chromeprogressive-web-appsvirtual-keyboard

PWA does not resize window when virtual keyboard is active on fullscreen display mode


I am developing a PWA, primarily targeting mobile users. The default behavior for the web, as far as I know it that, when the virtual keyboard is active, the window size adjusts accordingly. This works fine for mobile on the web and in standalone display mode. In fullscreen mode the window size does not change when the keyboard is active. That results in inputs beeing hidden behind the keyboard. Does anyone now why that is the case or if there is a hack to get around that? (Like getting the height of the keyboard manually, etc.) The issue only occurs on android chrome as far as I know, ios safari works as expected.


Solution

  • When the PWA Display is set to fullscreen, the API doesn't allow the viewport to adjust upon input events, so the virtual keyboard will always overlay the app. For more details see Progressive Web-App Soft-Keyboard and Nav Bar overlaps in Fullscreen

    Simplest solution is to set it to standalone. Otherwise:

    One generic CSS workaround you can do to enforce viewport updates is use :focus-within, for example (note, not broadly tested):

    @media only screen and (orientation: landscape) and (hover: none) {
        body:focus-within,
        body:focus-within .an-absolutely-positioned-input-ancestor {
            max-height: 53vh;
            overflow: auto;
        }
    }
    

    A more specific workaround we used was to use Javascript to add an input_focus class to the body tag for specific applicable form elements only on the focus event, then select that with CSS and style that element (absolute/fixed) to float above the keyboard. Brief example of this with jQuery:

    JS

    var inputs = jQuery('input[type="text"]').add('textarea');
    inputs.each((index, input) => {
        input.on('focus', e => {
            jQuery('body').addClass('input_focus');
        }).on('blur', e => {
            jQuery('body').removeClass('input_focus');
        });
    }
    

    CSS

    body.input_focus :is(
        input[type="text"],
        textarea
        ):focus {position: fixed;} /* position as you need */
    

    Note: if areas of the DOM are loaded dynamically with AJAX, wrap the JS in a function & run each time the AJAX has finished loading.