I have a layout that is similar to a console where there is a menu bar on top, an input line in the bottom, and in the middle there is a scrolling div with text that gets added as you type.
let pre = $("pre")
for (let i = 0; i < 200; i++) {
pre.append("<span class='line'>line " + i + "</span>")
}
function bottom() {
pre.scrollTop(pre.prop("scrollHeight"));
}
$("#commandline").on('keyup', function (e) {
if(e.which == 13){
pre.append("<span class='line'>" + $("#commandline").val() + "</span>");
bottom();
$("#commandline").val("");
}
});
bottom();
html, body {
top: 0;
right: 0;
left: 0;
bottom: 0;
overflow: hidden;
position: absolute;
}
#container {
position: absolute;
top: 0;
right: 0;
left: 0;
bottom: 0;
display: flex;
flex-direction: column;
overflow: hidden;
}
#toprow, #bottomrow {
flex: none;
background-color: red;
}
#midrow {
flex: 1;
display: flex;
position: relative;
}
pre {
overflow-y: scroll;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: 0;
box-sizing: border-box;
}
.line {
display: block;
}
#commandline {
position: relative;
width: 100%;
border: 1px solid red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<html>
<body>
<div id="container">
<div id="toprow">
Menubar
</div>
<div id="midrow">
<pre>
<span>ton of lines</span>
</pre>
</div>
<div id="bottomrow">
<input type="text" id="commandline">
</div>
</div>
</body>
</html>
It all works fine in a normal browser. And it also renders fine in a mobile browser as long as you don’t focus into the input box. When you do that the onscreen keyboard pops up and shifts the top of the ui outside of the remaining viewport instead of adjusting the height of the window to fill the remaining space.
You can see how that can break everything because there is a scrolling div in the middle, so you cannot scroll up to get to the menubar anymore until you scroll the whole middle pre up to the top.
I need this layout to always fill the remaining space on the screen, not shift up when the keyboard appears.
I tried in the Chrome dev tools by emulating th device Nexus 5, and there it seems to work, but when trying to test this on a Samsung S20 in mobile Chrome it doesn’t.
Can somebody help to figure out a layout that works responsively with the on screen keyboard on a mobile?
Here is the JsFiddle: https://jsfiddle.net/cpzqf9vo/1/
Bonus point: is there a way to remove the adressbar from the mobile browser?
2
Answers
The Problem
As I can see, you are using a new version of Chrome mobile; that is, Chrome v108+. A few days ago, another guy had a similar problem right here…
Fixed elements disappear when keyboard opens in Chrome Mobile
To make things clear, Google made an announcement, you can read it here, that this behavior was problematic to many layouts and that a change is coming. This behavior was well-known in Safari browsers, and probably on Chrome for iOS (CriOS). On other mobile browsers (Opera, Firefox, …etc.) your code will work just fine.
Possible Solutions
In Chrome (Android) you can add the following code to your meta tags…
Probably, your code have a viewport meta tag, so you will only need to add
interactive-widget=resizes-content
to the end of it. This way, it will work on the Android version of Chrome. About CriOS or Safari on iOS, I don’t actually know a viable solution as I haven’t tested any of them. Yet, below are some links that may help you out!Useful Links
https://css-tricks.com/a-couple-changes-coming-in-chrome-108/
https://css-tricks.com/css-fix-for-100vh-in-mobile-webkit/
Is there any fix to iOS, safari and chrome fixed position for when keyboard shows up?
Iphone safari not resizing viewport on keyboard open
screen styling when virtual keyboard is active
Solution
Use
flex-grow
(only for the middle element) property instead offlex
.flex-grow
, your list gets automatic resizing.In mobile browsers where the header disappears upon scrolling down, I encounter a small issue in detecting the resizing, but this is likely due to the browsers. I don’t know yet how to improve this.
However, for the original problem, the solution seems effective: if the keyboard appears,
flex-grow
resizes the list.As an extra, I fixed your overflowing input field. The border should be included in the 100% width as well!