Don't use sticky if element is larger than screen height
Hope this pen helps
Some explanations:
- in js we use
.offsetHeight
&.clientHeight
to get height we check weather this height(493px
) +50px
offset is more than screen height or not. - When screen size is small we set position to
static
- Also we set
margin-top: 50px
instead oftop: 50px
becausetop
works only forsticky
andmargin-top
works forstatic
position: sticky not working after some amount of scroll
One way to solve this:
.slider {
overflow: auto;
display: grid; /* main element as grid */
grid-auto-columns: 20%; /* width of the items */
}
.header,
.body {
display: contents; /* remove the parent boundary to make sticky works */
}
.header > * {
grid-row: 1; /* all header elements in first row */
}
.body > * {
grid-row: 2; /* all body elements in second row */
}
.item {
height: 100px;
background: yellow;
border: 1px solid black;
}
.sticky-item-left {
position: sticky;
left: 0;
background: red;
}
.sticky-item-right {
position: sticky;
right: 0;
background: green;
}
<div class="slider">
<div class="header">
<div class="item sticky-item-left"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item sticky-item-right"></div>
</div>
<div class="body">
<div class="item sticky-item-left"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item sticky-item-right"></div>
</div>
</div>
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>
How to stop DIV larger than viewport from scrolling?
There is probably no way to really - in a more natural kind of way - prevent a div
which uses position: fixed
- or even position: sticky
(which uses relative positioning at first and later when it sticks fixed positioning) - and has a larger size than viewport from scrolling when you want it to at a certain point.
Still, the goal of my question (stop scrolling to fade some div
elements) I can answer myself with some lines of code. In summary: use marginTop
of a div
to pull up some div
child elements of a div
which uses fixed positioning.
I do have at least one other question (maybe two) relating to this code (but not to the prevention of scrolling). But that are other questions which I can ask as new questions.
I will accept my own answer for now. If someone has a better or more 'natural' idea concerning this question - which I somehow doubt - I will happily change my acceptance to that answer.
var $window = $(window);var $document = $(document);// Element which needs to fade in and out.var $fadingblack = $("#fadingblack");var $scrolldistract = $("#scrolldistract");var $scrollsviascrolldistract = $("#scrollsviascrolldistract");// Pulls up the child divs of #scrollsviascrolldistract, under it.var $puller = $("#puller");
// Start of fading area (Y-value).var scrollTopStart = $fadingblack.position().top;// And of course the Y-value of the end of the fading area.var scrollTopEnd = scrollTopStart + $fadingblack.height();
// Maximum scrollTop-value (when scrollbar is at 100%).var lastScrollTop = $document.height() - $window.height();
// Amount of scrolled pixels (vertically) including amount scrolled while// the fading element is fading.var scrollAmountWithFadeAmount = $document.height + $fadingblack.height();// Setting height does not quite work for an empty div,// so we are using some padding.$scrolldistract.css("paddingTop", scrollAmountWithFadeAmount);// Percentage of which we have scrolled (1 = 100%).var currentScrollTopP;// Current scrollTop value.var realCurY;
$(function() { // Off you go code...
function doScrollOrFade() { currentScrollTopP = Math.ceil($window.scrollTop() / lastScrollTop * 100) / 100; realCurY = currentScrollTopP * lastScrollTop;
if (realCurY >= scrollTopStart && realCurY <= scrollTopEnd) { // Current realCurY dictates we are in fade area. // So scroll the fading area into view at top of browser viewport. $puller.css("marginTop", -scrollTopStart); // Determine opacity percentage. var fadePercent = (realCurY - scrollTopStart) / (scrollTopEnd - scrollTopStart); // Fade to current opacity immediately. $fadingblack.fadeTo(0, fadePercent); } else { // We are outside of the fading area and in scroll-mode. if (realCurY < scrollTopStart) { // We are somewhere before the fading area, so set opacity to 0. $fadingblack.fadeTo(0, 0); } else { // We are somewhere after the fading area, so set opacity to 1. $fadingblack.fadeTo(0, 1); }
if (realCurY > scrollTopEnd) { // We have passed the fading area. So we have an amount // of pixels we wasted on the opacity changes. // Correct it here. $puller.css("marginTop", -realCurY + $fadingblack.height()); } else { $puller.css("marginTop", -realCurY); } } window.requestAnimationFrame(doScrollOrFade); }
window.requestAnimationFrame(doScrollOrFade);
$window.on('resize orientationchange', function(e) { // On resize or orientation change recalculate some stuff. lastScrollTop = $document.height() - $window.height(); scrollAmountWithFadeAmount = $document.height + $fadingblack.height(); $scrolldistract.css("paddingTop", scrollAmountWithFadeAmount); window.requestAnimationFrame(doScrollOrFade); });});
body { background-color: whitesmoke;}
#scrollsviascrolldistract { position: fixed; left: 0px; top: 0px; width: 100%;}
#scrolldistract { position: absolute; left: 0px; top: 0px; width: 100%; padding-top: 2100px; height: 0px;}
#puller { position: relative; margin-top: 0px; left: 0px; top: 0px;}
img { display: block;}
.black,.red,.blue { border: solid 1px yellow; font-size: 32pt; position: relative; width: 100%; height: 300px;}
.red { background-color: red;}
.blue { background-color: blue;}
.black { background-color: black;}
<!--For mobile support use viewport meta-tag inside <head>:<meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=yes">-->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><div id="scrolldistract"></div>
<div id="scrollsviascrolldistract"> <!-- For pulling up the red, blue and fading area --> <div id="puller"></div> <div class="red">BEGIN</div> <div class="blue">Fading black area is ahead...</div> <div id="fadingblack" class="black"> </div> <div class="blue"> </div> <div class="red"> </div> <div class="blue">END</div></div>
Related Topics
JavaScript Invalidcharactererror When Modifying a CSS Name with a Space
Jquery/Js:Detect User's Scroll Attempt Without Any Window Overflow to Scroll To
How to Change the Viewport Meta Tag in Mobile Safari on the Fly
Using Cookies to Retain Stylesheet Preference Across Website
Background Image Resizing to Fit
Laravel 8 + Nginx - App.CSS and App.Js Resources from Public/ Not Loading - 404 Not Found
Animationend Event Not Firing on :After Element
Detect Support for Background-Size: Cover
Enabling Line Wrap with React-Syntax-Highlighter
Make the Change of "Active" Class in the Menu More Reliable When Scrolling
Primefaces Dialog with Modal=True Not Working Properly
React Animation for Moving an Element from One Parent to Another
Jquery Calendar Time Selection Suggestion
Variable in JavaScript Statement
Get Actual Value Specified in CSS Using Jquery
Creating a CSS Linear Gradient Based on Two Points Relative to a Rectangle