0

I have a section of my web application that has vertical scrolling. It does scroll on iOS, but there is a small part on the bottom where the scrolling pops up when I try to scroll down. When I drag, I see the content at the bottom, but when I release, it pops up so that the bottom part of the scroll-area becomes unavaliable. The scrollable area is positioned absolute inside a flex grid container.

<html>
<head>
<title>Test</title>
<meta name="viewport" content="width=device-width, height=device-height, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0, shrink-to-fit=no">
</head>
<body style="overflow:hidden;margin:0;">
<div style="display:flex;height: 100vh;background-color:yellow;">
<div style="background-color:silver;">Left
</div>
<div style="flex-grow: 1;background-color:lime;position:relative;">

<div style="position:absolute;top:0;left:0;bottom:0;right:0;overflow-y:auto; -webkit-overflow-scrolling: touch;">

<div>Line 0</div>
<div>Line 1</div>
<div>Line 2</div>
<div>Line 3</div>
<div>Line 4</div>
<div>Line 5</div>
<div>Line 6</div>
<div>Line 7</div>
<div>Line 8</div>
<div>Line 9</div>

<div>Line 10</div>
<div>Line 11</div>
<div>Line 12</div>
<div>Line 13</div>
<div>Line 14</div>
<div>Line 15</div>
<div>Line 16</div>
<div>Line 17</div>
<div>Line 18</div>
<div>Line 19</div>

<div>Line 20</div>
<div>Line 21</div>
<div>Line 22</div>
<div>Line 23</div>
<div>Line 24</div>
<div>Line 25</div>
<div>Line 26</div>
<div>Line 27</div>
<div>Line 28</div>
<div>Line 29</div>

<div>Line 30</div>
<div>Line 31</div>
<div>Line 32</div>
<div>Line 33</div>
<div>Line 34</div>
<div>Line 35</div>
<div>Line 36</div>
<div>Line 37</div>
<div>Line 38</div>
<div>Line 39</div>

</div>
</div>
</body>
</html>

When scrolling to bottom here on an iOS device, the bottom 4 lines are not visible. They appear if you drag to scroll further, but the scroll position pops back to hide the 4 lines at the bottom.

What is this? How can I solve it without adding extra empty space at the bottom?

awe
  • 21,938
  • 6
  • 78
  • 91

1 Answers1

2

OK, I found out the source of the problem.

The issue here is that the flex container have height: 100vh. On iOS device, this is actually larger than the visible area in the browser, due to mechanics that cause the address bar etc. to be hidden when you scroll the main page etc. Mobile browsers use different apporaches on how this is handled, but it basically ends up with that it is a mess when using the vh unit.

I found a hint on this here, and the solution to this problem seems to be quite simple. There is a webkit specific value you can use for the available space in the browser, so in addition to height:100vh, we can try to set it like this:

<div style="height:100vh;height:-webkit-fill-available;">

There is a big problem with this, though - because this breaks the 100vh on most other browsers (that are not iOS...)
This is because most browsers "support" the height:-webkit-fill-available, so this is applied instead of height: 100vh, only that it doesn't work as intended. I'm not sure how non-iOS browsers try to do with that value, but it is NOT what we want...

With some more research. I have found that using height: 100% is a better solution, but that also requires to set height: 100% on the <body>.

If you still need to use height: 100vh on an element, there is a trick to get it to work on iOS. You can add this piece of CSS that targets only iOS, because -webkit-touch-callout is something that is only supported on Safari Mobile:

body {
  margin:0;
}
.vh100 {
  height: 100vh;
}

@supports (-webkit-touch-callout: none) {
  /* CSS specific to iOS devices */
  .vh100 {
    height: -webkit-fill-available;
  }
}
<div style="background:lime;" class="vh100">
TEST
</div>
awe
  • 21,938
  • 6
  • 78
  • 91