On Safari Mobile 10.3 sticky footer can be scrolle

2019-03-23 07:20发布

问题:

Our mobile web application has sticky bottom navigation like the one you often find in iOS applications, and after Safari 10.3 release on landscape only it is possible to scroll sticky navigation (footer) off the screen. Even though it is position: fixed and set bottom: 0 it also wasn't possible on older Safari versions.

Styles for sticky nav / footer are following:

footer {
  position: fixed;
  height: 50px;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(255, 0, 0, 0.7);
}

DEMO to try on phone

In portrait mode it is always visible:

In landscape mode you can scroll it off screen for the size of top address bar:

Has anyone come across such issue? I would appreciate any help to make footer stay on the screen. Thanks

回答1:

There is nothing you can do about it. Safari's landscape mode makes the container with your content going off the screen. This is not detectable and therefore not to solve. I tried to illustrate what happens:

The blue bar = Safari's navigation bar

The yellow bar = Your app's navigation bar

Instead of shrinking the container's height, Safari lets it go off the screen.



回答2:

This is more a workaround than a real solution. However position: fixed has been a problem for mobile devices for years and the best way to overcome this problem is to use position: sticky.

sticky behaves like position: relative within its parent, until a given offset threshold is met in the viewport.

From: Stick your landings! position: sticky lands in WebKit

However position: sticky is not fully supported yet, so I would suggest to use also:

position: sticky; /* currently in development for MS Edge */
position: -webkit-sticky;
position: -moz-sticky;
position: -o-sticky;

See status here for MS Edge sticky support status (thank you Frits)


html,
body {
  height: 200%;
}

body {
  background-image: linear-gradient(180deg, #ededed 0px, #ededed 9px, #000000 9px, #000000 10px);
  background-size: 100% 10px;
}

footer {
  position: sticky; /* currently in development for MS Edge */
  position: -webkit-sticky;
  position: -moz-sticky;
  position: -o-sticky;
  height: 50px;
  top: 80%;
  background: rgba(255, 0, 0, 0.7);
}
<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>

<body>
  <footer>
  </footer>
</body>

</html>



回答3:

There is another way of creating a fixed element at the bottom of the page:

Set the <body> element (or whatever wraps your header, content and footer) to display: flex; height: 100vh. Then you take the footer and set it to margin-top: auto.

HTML:

<body>
    <header>
    </header>
    <main>
    <main>
    <footer>
    </footer>
</body>

CSS:

html {
    height: 100%;
}

body {
    height: 100%;
    display: flex;
    flex-direction: column;
}

main {
    flex: 1;
}

A different solution with the same markup would be to use CSS Grid:

html {
    height: 100%;
}

body {
    height: 100%;
    display: grid;
    grid-template-rows: auto 1fr auto;
}

In order to get the best of both worlds you can wrap the CSS Grid styles in an @supports(display: grid){} wrapper. If Grid is supported the browser will take that and otherwise will fallback to Flexbox.

The best thing using this technique is that you won't run into overlapping contents, into zooming-issues and it is fully responsive from the get-go.

There is an article on CSS Tricks about the subject: https://css-tricks.com/couple-takes-sticky-footer/



回答4:

Try this on the fixed position element in your css:

transform:translate3d(0px, 0, 0);
-webkit-transform:translate3d(0px, 0, 0);


回答5:

I had the same problem and I fixed it in a way that my tester is happy. Not a perfect solution but doing its job.

Add an empty element with some padding or margin.

const _userAgent = navigator.userAgent.toLowerCase();
if (_userAgent.indexOf('safari') != -1) {
    if (_userAgent.indexOf('chrome') == -1) {
        $('.myelem').append('<div class="my-5"></div>');
    }
}


回答6:

Something that does happen on the switch to landscape mode, and the switch to and from safari's 'minimal UI' is a window resize event. You can check the getBoundingClientRect().bottom of the fixed element to see if it is greater than window.innerHeight (This means the fixed element is off of the bottom of the window). If so, you can set the css property bottom of the fixed element to element.getBoundingClientRect().bottom - window.innerHeight. This will maintain to position of the fixed element. It appears to be a little jank to the user, but this is better than the element going off of the bottom of the screen.