If you've ever tried sticky positioning, then you have probably wondered why CSS position: sticky is not working for your web design. It's because an ancestor element has one of the following values for the overflow property: hidden, scroll, or auto.
That's disappointing, because you really needed that overflow-x: hidden on the <body>
-tag or on any other wrapper, to prevent horizontal scrolling due to overflowing content..
How to make position: sticky work with an ancestor's or parent's overflow: hidden?
Some articles claim that the solution to this is to make sure that the ancestor or parent element has a specified height. However, that's not what you want to do (right?), because you don't want to set a fixed height on the sticky element's ancestor or parent element.
There is, however, a rather new value for the overflow-property - it's called: clip.
This new value completely solves this problem. Unfortunately, there is a but to this one.
Browser support for CSS declaration overflow: clip
Let me tell you, at the time of writing this (October 2021), the support for this new CSS property is 73.09% globally. Which is not enough to implement this without a fallback.
Who are the evildoers, you ask me?
- Safari on iOS (13.83%)
- Safari (4.07%)
- Google Chrome versions 4 - 89 (3.1%)
- Samsung Internet versions 4 - 14.0 (1.14%)
- Internet Explorer (0.93%)
- Opera versions 10 - 75 (0.47%)
- Android Browser versions 2.1 - 4.4.4 (0.28%)
- Opera Mobile (0.01%)
Source: https://caniuse.com/mdn-css_properties_overflow_clip
There is, however, another rather new CSS property: contain. If you use contain: paint, then all the descendants that overflow the container, will get clipped to the border-box.
Sadly, this CSS property is also not supported by Safari. It has been around in Google Chrome since version 52, though. So that's a slight improvement compared to overflow.
Also, contain is a CSS property that is used for improving performance, not necessarily for controlling overflow of content. It has no way to determine whether to clip on the x-axis or the y-axis, unlike you can with overflow-x and overflow-y with value clip.
If you are interested in improving the performance of your web design, consider reading a post about lazy-rendering using content-visibility: auto and contain-intrinsic-size.
Overflow: clip vs overflow: hidden
The clip value does the same as the hidden value, except for that it completely disables any form of scrolling. The hidden value only disables scrolling for the user, while keeping the option for programmatic scrolling, thus making it a scroll container.
Since it is now a scroll container, it needs a specified height in order for position: sticky to work. You did not specify a height to the scroll container, and why would you?
Mozilla Firefox versions 80 and lower have a non-standard name for value clip, which perfectly describes what it actually does: -moz-hidden-unscrollable.
It hides the overflowing content, but does not turn the element into a scroll container.
So, the clip value does not make it a scroll container, so the window is still the scroll container. Your viewport, that is the default scroll container. It has a specified height too.
What am I supposed to do now?
If you really want position: sticky to work on all modern browsers, then you should consider not using overflow: hidden on the <body>
or any wrapper surrounding the main content, but rather put a wrapper around elements that will overflow the viewport.
Then, those wrappers should use overflow: hidden. If those wrappers contain elements that use position: sticky, then I feel sorry for you; I guess it's time to wait for support.
Use overflow: hidden as a fallback for overflow: clip
If you do not feel like wrapping every single element that overflows the viewport, and you find it okay if sticky elements won't work on some specific modern browsers, then I suggest using hidden as a fallback for browsers that do not support overflow: clip.
Elements with position: sticky will, in this case, not work for browsers that do not support overflow: clip. If this is something that you prefer over manually wrapping all elements that overflow the viewport, then that is completely understandable.
If some sticky elements won't work on Safari for iOS (13.83%) then that's not that big of a deal, since it's uncommon to use sticky elements on mobile devices anyways (except for maybe the header). Of course, there are tablet devices that could use sticky elements at some places, but tablet devices are rarely used (2.52% as of September 2021).
So, we could add like 13.83% (Safari for iOS) to the 73.09% of global support to get a more likeable percentage of users who won't be affected by the lack of browser support for the new value clip for CSS property overflow: 86.92%. That's more like it!
Source: https://gs.statcounter.com/platform-market-share/desktop-mobile-tablet
Luckily the global use of the desktop version of Safari is only 4.07%, so if a sticky element doesn't work on that browser, then that shouldn't be the end of the world.
Provide a prefixed version of sticky for older Safari browsers
It is necessary to provide a prefixed version of position: sticky for Safari browser versions 6.1 - 12.1 (0.2%) and Safari for iOS versions 6 - 12.5 (1.35%): -webkit-sticky.
.sticky {
position: -webkit-sticky;
position: sticky;
}
CSS position: sticky not working; is it a big deal?
If CSS position: sticky doesn't work on some browsers, does it hurt your web design's UX?
Sticky elements are handy, sure, but is the element still usable on browsers that do not support position: sticky at all? It is often still usable, but if you use elements with position: absolute within them, then it's parent's position is no longer sticky, it's static.
This is far fetched, since you probably don't care about browsers that don't even support position: sticky; browsers like Internet Explorer and very outdated modern browsers.
If you do care about those older browsers, then it's a good practice to provide position: relative as a fallback and apply properties top, right, bottom, and left on the sticky element only if the browser supports either sticky or -webkit-sticky for position.
Otherwise, if the element is relatively positioned instead of sticky, it will move because of the CSS properties top, right, bottom, and left. This is an example:
.sticky {
position: relative;
position: -webkit-sticky;
position: sticky;
}
@supports (position: sticky) or (position: -webkit-sticky) {
.some-sticky-element {
bottom: 30px;
}
}
Now, for browsers that do support position: sticky, but do not support overflow: clip, the sticky element will just not be sticky. So the web page should work just fine.
It's time to wrap it up. I hope I didn't overflow you with too much information. Do you want to learn more about unique CSS solutions every once in a while? Then do stick around!
Random fact: RSS is (coming) back to Google Chrome, so follow us if you'd like!