Safari position:sticky not working in an overflow:auto element
I got this solution from someone else:
http://cssdeck.com/labs/bu0nx69w
Basically, instead of position:sticky
, use position:fixed
for the right panel. The key is to also you will-change:transform
in a parent div (in the above example, in .modal-content
) so position:fixed
becomes fixed relative to that parent, and not the viewport. It's a neat little trick
Position sticky not working in IE or Safari
Changing the position of #nb to relative fixes the issue.
#nb {
position: relative;
width: 280px;
height: 450px;
margin: 0 auto;
overflow: hidden;
text-align: center;
}
Why is my position:sticky not working on iOS?
I feel like an idiot for answering my own question, but I figured out what is causing the problem.
I hope this will help developers facing the same problem because I could not find anywhere defining this behavior.
As you can see, in my code, there is a wrapper (specifically a link) around the element, on which I use my position:sticky:
<a href="#" class="jobAlertToggle">
<div id="jobalarm_mobile">
<i class="fa fa-bell"></i>
<span>Jobalarm aktivieren</span>
<label class="switch">
<input type="checkbox">
<span class="slider round"></span>
</label>
</div>
</a>
For some reason, this is not a problem for Chrome or Firefox on Desktop as well as Android, as they seem to ignore this container, probably because it doesn't define any positioning behavior. This is why it works on other devices. However, iOS does not ignore the container and therefor positions the div relative to its parent container, which is the link. After removing the link for test purposes, it worked on all devices.
Workaround for a Safari position: sticky (-webkit-sticky) bug
I think I've figured it out. The trick is to put the entire children of the scrollable container (that is, the header and the content) into a wrapper div - then the bug isn't triggered.
How does the position: sticky; property work?
Sticky positioning is a hybrid of relative and fixed positioning. The element is treated as relative positioned until it crosses a specified threshold, at which point it is treated as fixed positioned.
...
You must specify a threshold with at least one oftop
,right
,bottom
, orleft
for sticky positioning to behave as expected. Otherwise, it will be indistinguishable from relative positioning.
[source: MDN]
So in your example, you have to define the position where it should stick in the end by using the top
property.
html, body {
height: 200%;
}
nav {
position: sticky;
position: -webkit-sticky;
top: 0; /* required */
}
.nav-selections {
text-transform: uppercase;
letter-spacing: 5px;
font: 18px "lato", sans-serif;
display: inline-block;
text-decoration: none;
color: white;
padding: 18px;
float: right;
margin-left: 50px;
transition: 1.5s;
}
.nav-selections:hover {
transition: 1.5s;
color: black;
}
ul {
background-color: #B79b58;
overflow: auto;
}
li {
list-style-type: none;
}
<nav>
<ul align="left">
<li><a href="#/contact" class="nav-selections" style="margin-right:35px;">Contact</a></li>
<li><a href="#/about" class="nav-selections">About</a></li>
<li><a href="#/products" class="nav-selections">Products</a></li>
<li><a href="#" class="nav-selections">Home</a></li>
</ul>
</nav>
Why does changing the height of a 'position:sticky' element alter the scroll position on Chrome but not Safari?
Why is this behaviour different on these two browsers?
To understand this, you first need to understand how a sticky element takes up space on a page. As you scroll past the sticky element, the rendered part of the sticky element follows the top of your viewport, but the element still physically takes up space where it was originally placed:
This puts the browser in a bit of a weird situation when you resize the header, because it's actually an element that you have already scrolled past. There are two approaches to solving this. You can do like Safari and Firefox and always keep the same distance to the top of the document, or you can do like Chromium and move the viewport so that it follows the element you are currently looking at:
I believe Safari and Firefox do it their way, because it's the easiest solution, and that's just how every browser has always done it.
I believe Chromium has changed it's approach recently because it has a distinct advantage when a user is reading articles with slow loading ads that change size after they've loaded:
As you can see above, when the ad loads in Safari and Firefox, it causes a major shift in the page content, which annoys and disorients the user. This can especially be bad if there are several ads that load shortly after one another.
With the Chromium approach, the viewport is adjusted so that the user doesn't even notice that anything has happened.
I was not able to find any spec or discussion to back up my claims, but i'm pretty sure that this is the reasoning behind. I am not sure if Firefox or Safari has had a reason to not implement Chromiums approach, or if they just didn't feel it was that important.
Which one, if any, is "correct"?
Which solution is best is probably a very complicated and somewhat subjective discussion that i won't go into, although the benefits of Chromiums approach is undeniable.
Is there any way to make both browsers behave identically (either way)?
When you press the Grow/Shrink
button, you can always detect if the scroll height changes, and then set it back right after it was changed. You can also do the opposite and change the scroll height yourself so all browsers behave like Chromium. Here is an old article from someone who did exactly that:
https://simonerescio.it/en/2017/03/chrome-changes-its-center-of-gravity-reference-is-not-the-document-but-the-viewport
Sticky HTML element gets hidden below the Mobile navigation bar in chrome / Firefox mobile browser. How to fix this? [ UPDATED ]
As a workaround, setting the top most layout component position to fixed
solves the problem.
.layout {
display: block;
position: fixed;
height: 100vh;
width: 100vw;
max-height: 100%;
top: 0;
left: 0;
bottom: 0;
right: 0;
overflow-x: hidden;
}
working codepen ( open in mobile browser - Debug mode ):
https://codepen.io/sparkeplug/pen/WNzwerE
Related Topics
CSS Positioning 70-30 with Inline-Block
Change Background Colour as Page Scroll Without Jquery
How to Create a Box with a Left Arrow and Border
How to Add Background Image in CSS
Flexbox Does Not Work in Safari, Striked Out in Web Inspector
Javafx Tab Fit Full Size of Header
Chrome Is Now Blurring Text When Using Transform Translatey with Percent
Add Ancestor Selector in Current SASS Nesting
Build a Repetitive Selector Within a Less Loop
Create Loading Messages That Will Change Based on Loading Time of Plot in a Shiny App
CSS Text Padding Difference Firefox Vs Chrome and Others
Fade Background Images with CSS3
How to Align One Item in The Ol to The Right While The Others Are on The Left