Have a <div> fixed at a height only when scrolling down - javascript

So I have this sidebar:
<div class="col-md-3">
<h4 style="color: #404040; font-weight: bold;">
Guides:
</h4>
<div class="sidebar">
<!--auto-generated <ul>...-->
</div>
</div>
And I want it to follow the user as he scrolls down. I know that you can do it with position: fixed; in the styles. But I have a header, so if the div is fixed it remains in that height even if I scroll down.
But if I scroll down, it remains at that fixed point. Here's how it looks like when I scroll down it would look like this:
I want it to remain at the top. I read that I'm supposed to use javascript scroll functions, but I have no clue how, exactly.

You can use position: sticky for an easy "sticky" element. It's a new property, so it doesn't have the best browser support, but easy to use and works well.
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<style>
.row {
height: 200vh;
}
.row:nth-child(odd) {
background: #eee;
}
.sticky-column {
position: sticky;
top: 1em;
}
</style>
<div class="container">
<div class="row">
<div class="col-lg-12">
scroll down
</div>
</div>
<div class="row">
<div class="col-md-3 sticky-column">
<h4 style="color: #404040; font-weight: bold;">
Guides: (look it's sticky!)
</h4>
<div class="sidebar">
<!--auto-generated <ul>...-->
</div>
</div>
</div>
<div class="row"></div>
</div>

try using position: fixed; in style as well as margin-top: -30px; or what ever amount away from top you want:
something like this
<body>
<div class="sidebar" onscroll="dynamicheight()">
</div>
<script>
function dynamicheight() {
var sidebar = document.getElementById("sidebar");
var y = sidebar.scrollTop;
document.getElementById('random').style.height = y;
}
</script>

try something like this
var yOffset = $("#sidebar").offset().top;
$(window).scroll(function() {
if ($(window).scrollTop() > yOffset) {
$("#sidebar").css({
'top': 0,
'position': 'fixed'
});
} else {
$("#sidebar").css({
'top': yOffset + 'px',
'position': 'absolute'
});
}
});
Try this too
position:sticky;

Related

Trigger a scrolling event in a different div when a user scrolls using jQuery

I have two div elements:
When a user scrolls div #element-A and #header-one-target reaches the top of the containing div the last element (#animate-hd-b) in #element-B should scroll to the top of the containing div with a nice animation .
Here's the code that I'm working with to start. The code below does something when the window is scrolled not the div.
$(window).scroll(function() {
var offsetTop = $('#animate-hd-b').offset().top,
outerHeight = $('#animate-hd-b').outerHeight(),
windowHeight = $(window).height(),
scrollTop = $(this).scrollTop();
console.log((offsetTop-windowHeight) , scrollTop);
if (scrollTop > (offsetTop+outerHeight-windowHeight)){
alert('you have scrolled to the top!');
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="element-A" style="background: orange; overflow: auto;">
<div class="content" style="padding-bottom: 300px;">
<p>content</p>
<p>content</p>
<p>content</p>
<p>content</p>
<h1 id="header-one-target">Header One</h1>
</div>
</div>
<div id="element-B" style="background: yellow; overflow: auto;">
<div class="content" style="padding-bottom: 300px;">
<p>content</p>
<p>content</p>
<p>content</p>
<p>content</p>
<h1 id="animate-hd-b">Animate This Header</h1>
</div>
</div>
Is there a way to do this in jQuery?
This is really pretty simple. You just keep track of #header-one-target and animate
#animate-hd-b when #header-one-target reaches at the top.
(function($) {
let $elementA = $('#element-A');
let $elementB = $('#element-B');
let $headerOneTarget = $('#header-one-target');
let $animateHdB = $('#animate-hd-b');
let isScrollAtTop = true;
$elementA.scroll(function() {
if (isScrollAtTop && $headerOneTarget.offset().top < 5) {
isScrollAtTop = false;
$elementB.animate({
scrollTop: $elementB.scrollTop() + $animateHdB.offset().top
});
} else if ($elementA.scrollTop() < 5) {
isScrollAtTop = true;
$elementB.animate({
scrollTop: 0
});
}
});
})(jQuery);
#element-A {
background: orange;
overflow: auto;
height: 100vh;
width: 60vw;
position: fixed;
top: 0;
left: 0;
}
#element-B {
position: fixed;
top: 0;
right: 0;
height: 100vh;
width: 40vw;
background: yellow;
overflow: auto;
}
.content {
padding: 10px;
}
.content-vh100 {
height: 100vh;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="element-A">
<div class="content">
<p>Scroll</p>
<p>to</p>
<p>header</p>
<p>one</p>
<h1 id="header-one-target">Header One</h1>
<div class="content-vh100"></div>
</div>
</div>
<div id="element-B">
<div class="content">
<p>to</p>
<p>animate</p>
<p>following</p>
<p>content</p>
<h1 id="animate-hd-b">Animate This Header</h1>
<div class="content-vh100"></div>
</div>
</div>
Some conditions were added that should prevent unnecessary animations and queueing (which tends to happen when listening for scroll and animating scrollTop). It keeps track of the scroll direction and won't start animating when the element on the right has already reached its position.
Codepen demo
var sin = $('#element-A'),
dex = $('#element-B'),
peg = sin.scrollTop();
sin.scroll(function() {
var way = sin.scrollTop(),
rate = Math.round(sin.find('h1').position().top),
area = dex.scrollTop(),
turf = Math.round(dex.find('h1').position().top),
down = way > peg;
peg = way;
// conditions for scrolling down
if (rate < 0 && down && turf) {
dex.not(':animated').animate({scrollTop: area+turf}, 700);
}
// scrolling up
if (!down && area) {
dex.not(':animated').animate({scrollTop: 0}, 700);
}
});
body {
margin: 0;
}
body > div {
width: 50%;
height: 100vh;
float: left;
overflow: auto;
}
#element-A {
background: orange;
}
#element-B {
background: yellow;
}
.content {
padding-bottom: 100vh;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="element-A">
<div class="content">
<p>content</p>
<p>content</p>
<p>content</p>
<p>content</p>
<h1 id="header-one-target">Header One</h1>
</div>
</div>
<div id="element-B">
<div class="content">
<p>content</p>
<p>content</p>
<p>content</p>
<p>content</p>
<h1 id="animate-hd-b">Animate This Header</h1>
</div>
</div>
In case the elements are differently positioned in the target environment, using position() is a more straightforward approach than offset() because the latter is relative to the document. The former (used here) is relative to its own parent element and should work independent of its position.

Scrolling fixed header not showing on mobile device

I have a fixed header that changes to a sticky header on scroll using JS.
The dropdown menu works when in mobile view showing on Google Dev Tools and Firefox Responsive Design Mode, however it doesnt work on actual mobile devices.
I've tried changing the Z-index and webkit-backface-visibility.
The HTML:
<header id="myHeader" class="site-header" role="banner">
<div class="nav-container">
<nav id="top-bar">
<div class="row" id="top-bar">
<div class="top-bar-text">
</div>
</div>
</nav>
<nav id="site-navigation" class="main-navigation" role="navigation">
<div class="container nav-bar">
<div class="row">
<div class="module left site-title-container">
<?php shapely_get_header_logo(); ?>
</div>
<div class="module widget-handle mobile-toggle right visible-sm visible-xs">
<i class="fa fa-bars"></i>
</div>
<div class="module-group right">
<div class="module left">
<?php shapely_header_menu(); // main navigation ?>
</div>
<!--end of menu module-->
</div>
<!--end of module group-->
</div>
</div>
</nav><!-- #site-navigation -->
</div>
</header>
header {
height: 85px;
left: 1em;
position: fixed;
z-index: 10000;
right: 1em;
top: 40px;
}
JS changes the header on scroll to:
.sticky {
position: fixed;
top: 0;
left: 0;
width: 100%;
background: #f8b836;
z-index: 999;
height: 90px;
overflow: hidden;
-webkit-transition: height 0.3s;
-moz-transition: height 0.3s;
transition: height 0.3s;
}
The CSS for the menu in mobile view:
#media (min-width:300px) and (max-width:480px){
#site-navigation .module.left {
padding-left: 0px;
position: fixed;
left: 0;
}
}
The JS:
window.onscroll = function() {myFunction()};
var header = document.getElementById("myHeader");
var sticky = header.offsetTop;
function myFunction() {
if (window.pageYOffset > sticky) {
header.classList.add("sticky");
} else {
header.classList.remove("sticky");
}
}
I'd like the dropdown menu to actually show when the page has been scrolled and the sticky heading is showing.
Does the dropdown not open on mobile devices?
Your .sticky css class has overflow: hidden; which is keeping the dropdown hidden. If you put it there to avoid horizontal scrolling, use overflow-x: hidden; instead. Then it won't cut the dropdown off.
Generally you want overflow-y set to scroll when you have a fixed element with a dropdown on mobile. In case the menu extends beyond the bottom of the screen.

Get the end of window.scrollby

I want to implement a page that continuously scrolls, such that when it gets to the bottom on the page, it goes back to the top and scrolls back to the end. So far I have implemented the page
$(document).ready(function() {
var scroll = setInterval(function() {
window.scrollBy(0, 1);
}, 20);
});
.content {
height: 500px;
width: 100%;
background-color: #cccccc;
}
.inner-content {
height: 80px;
width: 100%;
margin: 10px 0 10px 0;
background-color: #ff00ff;
}
h1 {
text-align: center;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<div class="row content">
<div class="col-md-12 inner-content">
<h1>One</h1>
</div>
<div class="col-md-12 inner-content">
<h1>Two</h1>
</div>
<div class="col-md-12 inner-content">
<h1>Three</h1>
</div>
<div class="col-md-12 inner-content">
<h1>Four</h1>
</div>
<div class="col-md-12 inner-content">
<h1>Five</h1>
</div>
</div>
Now, what I am trying to figure out is how to listen in to JS to when it gets to the bottom of the page, so that I can reintialize the autoscrolling from top again. Kindly help.
You can test if the window is at the bottom with the following:
$(window).scroll(function() {
if ( $(window).scrollTop() + $(window).height() == $(document).height() ) {
$(window).scrollTop(0);
}
});
On scroll, we test if the page is at the bottom, then reset the scroll position to 0 (top)
https://jsfiddle.net/qjvkgx9t/

Ignore all relative positioned parent divs wrapped arround absolute positioned div?

I know it's not possible with css, but I was trying to find some jQuery solution, so far no luck with answers on stack.
Anyway, the HTML order looks like this, and it needs to stay like this:
<div class="wrapper">
<div style="position:relative;">
<div style="position:relative;">
<div class="dont-want-parents" style="position:absolute;">
</div>
</div>
</div>
</div>
So the question is how to position div with class "dont-want-parents" to the right-bottom of the wrapper div, ignoring all the relative positioned parents.
Thanks to everyone who tried to help, eventually I figured out a solution:
$(window).on("load resize",function(e){
var parentoffset = $('.dont-want-parents').parent();
var elwidth = $('.dont-want-parents').width();
var offset = parentoffset.offset();
$('.dont-want-parents').css('right', -offset.left + elwidth);
});
here's a working fiddle
You can set them all back to static so that the one with absolute ignores them. Also, top and left are needed, as position:absolute only removes the element from the layout but not from its original position.
$('.wrapper > div, .wrapper > div > div').css('position', 'static');
div{
padding: 50px;
background: rgba(255, 0, 0, 0.5);
}
.wrapper{
position: relative;
background: green;
}
.dont-want-parents{
background: blue;
top: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper">
<div style="position:relative;">
<div style="position:relative;">
<div class="dont-want-parents" style="position:absolute;">
</div>
</div>
</div>
</div>
Another way is to just yank out the element from wherever it is and put it somewhere that is safe to be absolute.
$('.dont-want-parents').appendTo('.wrapper');
div{
padding: 50px;
background: rgba(255, 0, 0, 0.5);
}
.wrapper{
position: relative;
background: green;
}
.dont-want-parents{
background: blue;
top: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper">
<div style="position:relative;">
<div style="position:relative;">
<div class="dont-want-parents" style="position:absolute;">
</div>
</div>
</div>
</div>

Javascript to slide invisible div from top of the window

So i've been trying to replicate the functionality of the How it works button of airbnb. I'm new to stackoverflow, so I don't know the policies to link the website.
What I have tried:
My HTML mockup
<div class="how-it-works">
<div class="container">
<div class="row">
<div class="col-lg-12">
<span class="pull-right">
<span class="glyphicon glyphicon-remove" ng-click="hideHowItWorks()"></span>
</span>
</div>
<div class="col-lg-12">
<div class="row">
<div class="col-lg-3">
<div class="hiw-container hiw-step-one"></div>
</div>
<div class="col-lg-3">
<div class="hiw-container hiw-step-two"></div>
</div>
<div class="col-lg-3">
<div class="hiw-container hiw-step-three"></div>
</div>
<div class="col-lg-3">
<div class="hiw-container hiw-step-four"></div>
</div>
</div>
</div>
</div>
</div>
<div class="main-class">
...some content....
</div>
My CSS:
.how-it-works{
position: absolute
width: 100%
top: -663px
padding-top: 40px
min-height: 663px
}
I'm using JQuery to slide the entire div down instead of using the standard slideDown procedure.
$('.btn').on('click', function(){
$('.how-it-works').css('height', $(window).height());
$('.how-it-works').animate({top: '0px'});
$('.main-class').animate({marginTop: '663px'});
})
If I use this method or the method of slideDown, the frame while sliding, stutters and gives an effect thats far from pleasing. How do I make the effect that's similar to the above mentioned website?
Slide an overlay on canvas from the top. This uses vanilla javascript and css animations. jQuery animations always seems jerky in my opinion.
var overlay = document.getElementById('overlay');
document.getElementById('open').onclick = function() {
overlay.style.top = 0;
}
document.getElementById('close').onclick = function() {
overlay.style.top = '-100%';
}
html, body {
height: 100%;
margin: 0;
}
#overlay {
background: red;
height: 100%;
width: 100%;
position: absolute;
top: -100%;
transition: top 1s ease-in-out;
}
<div id="overlay">
close
</div>
Open

Categories

Resources