Consider the snippet below, where I've created a basic chat window.
The issue: When you focus the input on a mobile device, the entire page is shifted up, pushing the header and messages out of view.
The goal: When you focus the input on a mobile device, the #messages
section shrinks to accommodate the keyboard (similar to how the page behaves on desktop when reducing the window height).
(Images included below)
My attempts to resolve it: I've tried using height: 100%
instead of 100dvh
, I've tried moving the height declaration to the <body>
instead of the <html>
.
html,
body {
padding: 0;
margin: 0;
}
html {
height: 100dvh;
width: 100dvw;
}
body {
height: 100%;
width: 100%;
background-color: white;
}
#content {
height: 100%;
display: flex;
flex-direction: column;
}
#header {
padding: 20px;
background-color: #ccc;
}
#messages {
margin: -10px 0;
flex-grow: 1;
flex-shrink: 1;
overflow: auto;
}
.message {
padding: 20px;
}
#footer {
display: block;
background-color: #aaa;
padding: 20px;
}
input {
padding: 5px;
width: 100%;
display: block;
}
button {
border: 0;
margin: 4px 0;
padding: 4px;
background-color: orange;
font-weight: bold;
}
<div id="content">
<div id="header">Header</div>
<div id="messages">
<div class="message"><b>John:</b> Lorem ipsum dolor sit amet.</div>
</div>
<form id="footer">
<input>
<button type="button">Send Message</button>
</form>
</div>
EDIT: Firefox on mobile handles this perfectly. Almost seems like Chrome and Safari are not accounting for the on-screen keyboard when calculating dvh
.
Turns out the code in the question is fine.
The solution is to add interactive-widget=resizes-content
to your <meta name="viewport">
tag, like so:
<meta name="viewport" content="width=device-width, initial-scale=1, interactive-widget=resizes-content">
Why:
dvh
units are determined using the size of the Layout Viewport. As of Chrome 108 (Nov 2022), the on-screen keyboard affects the Visual Viewport, but not the Layout Viewport.
The interactive-widget=resizes-content
forces Chrome to use the previous behavior, where both the Visual and Layout viewports are resized.
Sources:
Chrome for Developers: Prepare for viewport resize behavior changes coming to Chrome on Android
In November 2022, with the release of Chrome 108, Chrome will make some changes to how the Layout Viewport behaves when the on-screen keyboard (OSK) gets shown [...] and instead resize only the Visual Viewport.
If you want your website to use the pre-108 resize behavior, fear not. Also shipping in Chrome 108 is an extension to the viewport meta tag.
Through the
interactive-widget
key, you can tell Chrome which resize behavior you want.Accepted values for interactive-widget are:
resizes-visual
: Resize only the Visual Viewport but not the Layout
resizes-content
: Resize both the Visual Viewport and Layout
overlays-content
: Do not resize any viewport.