8

Disclaimer - I understand there exists questions around fixed elements in safari, and fixed elements weren't supported, but now are and so forth. However I can't find a question that addresses this exact question.

Given the simplest of fixed sidebars, something like:

.sidebar {
    position: fixed;
    top: 10px;
    right: 10px;
}

And a relatively long page, with input elements.

When an input element is focused, any fixed element becomes absolute - I understand the why, safari is trying to declutter the viewport - thats fine, but not always appropriate. I ask that I get to choose the best experience for the user (i know best naturally).

So the Question..

Is there any way to leave fixed elements as fixed even when input elements are focused?

I have attempted to do a bit of $(window).on('scroll', magic and position elements manually on scroll, but its quite jittery on the ipad.

Chris
  • 54,599
  • 30
  • 149
  • 186
  • 1
    If you want to provide a MCV example of your specific scenario we can play around. This is a known issue, and as of today pretty much the best solutions are to switch that element to position absolute by yourself and set it with JavaScript exactly as where it should be if Safari wouldn't have broken it: it may also work to hide overflow if we're on a field on the very top of the page, but I find this second one way too hacky. – Juan Ferreras Aug 21 '16 at 00:51
  • 1
    I will try to put together a small scenario this evening. I agree about the known issue bit - I fear that the final might be simple, manually intervene and position absolutely when required – Chris Aug 21 '16 at 01:28
  • Possible duplicate of several SO questions. See https://gist.github.com/avesus/957889b4941239490c6c441adbe32398#gistcomment-2193547 for details. – Brian Cannard Sep 04 '17 at 23:35

2 Answers2

3

Safari has supported position: fixed since at least version 9.2, but if you're seeing difficult issues, you can fully create the fixed position effect by making the document element and body full screen and then using absolute positioning. Scrolling then occurs in some main container element rather than the body. Your "fixed" elements can exist anywhere in the markup using this method.

jsfiddle here

html,
body,
.mainContainer {
  height: 100%;
  width: 100%;
  overflow: hidden;
  margin: 0;
}

.mainContainer {
  overflow: auto;
}

.fixed {
  position: absolute;
  bottom: 20px;
  left: 20px;
}
cage rattler
  • 1,587
  • 10
  • 16
  • 2
    The question specifies "on input focus", but your example provides no text input controls which can activate virtual keyboard. Things will look perfectly until user taps on a text input control. – Brian Cannard Sep 04 '17 at 17:07
0

In order to achieve the effect you desire you need to change your approach to the layout. Instead of positioning the sidebar with position:fixed you need to use position:absolute within a position:relative container that is set to the height of the viewport within that position:relative container you need another div that uses overflow-y: scroll and -webkit-overflow-scrolling : touch

Caveat: I generally avoid using position fixed on tablet & mobile if possible although the browser support is there, in my experience it'll be janky and javascript solutions leave a lot to be desired, my first response would be to challenge the pattern with the designer. If I'm given designs that include a position fixed element when there are input elements, I'm more likely to seek a design solution than a development one as the focus issues you're describing are difficult to circumvent and maintain a quality user experience.

THE MARKUP:

<div class="outer">
   <div class="sidebar">
    <ul>
       <li>Dummy list nav or something</li>

     </ul>
  </div>
  <div class="container">
       <input type="text" />
  <!-- I added 10000 inputs here as a demo -->
 </div>
</div>

THE CSS:

html,body{
-webkit-overflow-scrolling : touch !important;
overflow: auto !important;
height: 100% !important;
}
.outer {
  position: relative;
  overflow: hidden;

/* I'm using Viewport Units here for ease, but I would more likely check the height of the viewport with javascript as it has better support*/
  height: 100vh;
}
.sidebar {
    position: absolute;
    top: 10px;
    right: 10px;
  /*added bg colour for demo */

  background: blue;
}
.container {
  height: 100vh;
  overflow-y: scroll;
  -webkit-overflow-scrolling: touch
}
input {
  display: block;
}

Here's a CodePen for you to open in your simulator (presentation view): https://codepen.io/NeilWkz/full/WxqqXj/

Here's the editor view for the code: https://codepen.io/NeilWkz/pen/WxqqXj

NeilWkz
  • 245
  • 1
  • 8
  • Hi Brian, thanks for your comment, the core mechanic seems to still work in Mobile Safari (I've just changed the pen link to show to editor view. What's the issue you're seeing with the demo? – NeilWkz Aug 29 '17 at 09:39
  • the height of viewport usually needs to be updated after virtual keyboard showing up, rotations, and address bar appearing / disappearing. Only handling resize and focus events, and moving input controls position to the bottom of the screen before activating focus can make WebKit on iOS behave the same way as Google Chrome behaves on Android. Awful Safari. – Brian Cannard Sep 03 '17 at 18:17
  • I'm not sure I follow your point Brian, the outer height is set with viewport units, which do not need to be updated. In my demo I'm not seeing the issues you're describing with mobile safari. – NeilWkz Sep 04 '17 at 13:09
  • your "DUMMY LIST NAV OR SOMETHING" is always positioned at random vertical offsets depending on which input control is tapped, so the navigation doesn't behave as fixed positioned. On Android's Chrome, nothing ugly like that even happens - the blue thing always stays at the same vertical offset. The question was formulated as "Is there any way to keep fixed elements as fixed". And your example doesn't keep it as fixed. – Brian Cannard Sep 04 '17 at 17:03
  • please check out https://gist.github.com/avesus/957889b4941239490c6c441adbe32398 for details on how to solve the problem. – Brian Cannard Sep 04 '17 at 23:38
  • Yes I've read your gist, but I'm still not able to see, or replicate the issue you're reporting on Mobile Safari (I've just checked again on on our device lab for the last three versions of IOS). As I'm currently using versions of this technique in production, would you be so kind as to let me know a little more information as to the IOS version, and situation where you can see this bug. – NeilWkz Sep 05 '17 at 09:41
  • The issue is in all versions of Mobile Safari. When user taps on a control receiving focus and virtual keyboard shows up, iOS WebKit scrolls the whole window putting input control in the middle, but moving out all fixed elements. https://techblog.badoo.com/images/fixed-headers-in-mobile-webapps/1.gif https://stackoverflow.com/questions/15273098/how-do-i-stop-my-fixed-navigation-from-moving-like-this-when-the-virtual-keyboar It is NOT solved and never will be. Because the behavior is by design. You have to wrap it into a mud ball of JavaScript fixes. – Brian Cannard Sep 05 '17 at 18:36
  • iOS 10.3.3 in Safari, Chrome Mobile iOS, Facebook Messenger iOS. – Brian Cannard Sep 05 '17 at 18:38