Keep div at top of window while content expands above it? - javascript

var divPos;
$('div').click(function() {
$(this).addClass('open');
$('div').not(this).addClass('close');
divPos = $(this).offset().top;
});
$('button').click(function(){
$('div').removeClass('open close');
$('html, body').animate({
scrollTop: divPos
}, 1000);
})
html, body {height:100%; padding:0; margin:0;}
div {height:25%; transition:height 1s;}
div.open {height:400px;}
div.close {height:0;}
div:nth-of-type(1) {background:red;}
div:nth-of-type(2) {background:blue;}
div:nth-of-type(3) {background:green;}
div:nth-of-type(4) {background:yellow;}
button { margin-bottom:100%;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div></div>
<div></div>
<div></div>
<div></div>
<button>close</button>
I have a stack of divs and when the user clicks one it expands it's height, while the ones that weren't clicked get zero height. All heights are transitioned by css.
When a close button is clicked, all divs go back to the original size.
How can I have the window scroll position keep the previously opened div at the top of the screen while the divs above it are expanding?
I have tried getting the position of the clicked div at it's original state and using:
$('html, body').animate({
scrollTop: divPos
}, 500);
Which basically works but it doesn't keep time with the css transition so it moves down before scrolling back up into position.
Here is a mockup of the problem: https://jsfiddle.net/0n6mxdt4/1/
The bounce back gets worse the lower the div it is.

If I correctly understand your problem, I think this is your answer. You need to add this line before animating to position:
$("html, body").scrollTop(divPos);
It is the working answer
var divPos;
$("div").click(function() {
$(this).addClass("open");
$("div")
.not(this)
.addClass("close");
divPos = $(this).offset().top;
clickedPos = $(this);
});
$("button").click(function() {
$("div").removeClass("open close");
$("html, body").scrollTop(divPos);
$("html, body").animate({
scrollTop: divPos
},
1000
);
});
html,
body {
height: 100%;
padding: 0;
margin: 0;
}
div {
height: 25%;
transition: height 1s;
}
div.open {
height: 400px;
}
div.close {
height: 0;
}
div:nth-of-type(1) {
background: red;
}
div:nth-of-type(2) {
background: blue;
}
div:nth-of-type(3) {
background: green;
}
div:nth-of-type(4) {
background: yellow;
}
button {
margin-bottom: 100%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div></div>
<div></div>
<div></div>
<div></div>
<button>close</button>

Related

CSS: How to account for the lost space when converting item from static to fixed/absolute

Here's my jsfiddle: https://jsfiddle.net/vd2vstoy/1/
HTML:
<div class="content">
<div class="top-banner">
<h1>
Some<body> Once Told Me
</h1>
</div>
<div class="fixedElement">
the <i>HelloWorld</i> is gonna roll me
</div>
<h1>
I ain't the C-sharp-est tool<br>
In the shed.
</h1>
</div>
CSS:
.content {
height:1000px;
}
.top-banner {
background-color:yellow;
height:200px;
}
.fixedElement {
background-color: #c0c0c0;
padding:15px;
position:static;
top:0;
width:100%;
z-index:100;
}
Javascript:
$(window).scroll(function(e){
var $el = $('.fixedElement');
var isPositionFixed = ($el.css('position') == 'fixed');
if ($(this).scrollTop() > 220 && !isPositionFixed) {
$('.fixedElement').css({'position': 'fixed', 'top': '0px'});
}
if ($(this).scrollTop() < 220 && isPositionFixed) {
$('.fixedElement').css({'position': 'static', 'top': '0px'});
}
});
The point of this is so that the fixedElement sticks to the top when it reached that 200 pixel mark. Unfortunately, the space that the fixedElement was taking up goes away when it turns fixed position.
Is there anyway that I can preserve the space that was there so that as soon as the element becomes fixed, the rest of the content doesn't shift up and become unseen?
To see what's happening, just scroll down in the example jsfiddle and see what happens when the fixedElement div reaches the top of the screen.
What I normally do is wrap the item that is going to be fixed to the top in a div that has a fixed height and remains relative. That way, when the fixed element is moved out of the regular flow by setting its position: absolute (in the scroll event), the space will be retained by the containing div, and no page-jumping occurs.
So you wrap the .fixed-element in a div of a matching height, but do not make that one change to a position: absolute
Here's a working snippet:
$(window).scroll(function(e) {
var $el = $('.fixedElement');
var isPositionFixed = ($el.css('position') == 'fixed');
if ($(this).scrollTop() > 220 && !isPositionFixed) {
$('.fixedElement').css({
'position': 'fixed',
'top': '0px'
});
}
if ($(this).scrollTop() < 220 && isPositionFixed) {
$('.fixedElement').css({
'position': 'static',
'top': '0px'
});
}
});
.content {
height: 1000px;
}
.top-banner {
background-color: yellow;
height: 200px;
}
.fixedElement {
background-color: #c0c0c0;
padding: 15px;
position: static;
top: 0;
width: 100%;
z-index: 100;
height: 25px;
}
.fixedElementWrapper {
/* Match the height of the elements to prevent shifting */
height: 25px;
}
h1 {
/* Adding some space to make the effect more visible */
margin-top: 40px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="content">
<div class="top-banner">
<h1>
Some<body> Once Told Me
</h1>
</div>
<div class="fixedElementWrapper">
<!-- we add this because this is gonna preserve our space -->
<div class="fixedElement">
The <i>HelloWorld</i> is gonna roll me
</div>
</div>
<h1>
I ain't the C-sharp-est tool<br> In the shed.
</h1>
</div>
Hope it helps!
Here is an updated version of your fiddle with the fix.
I wrapped your fixed element in a parent wrapper, then on fixed, set the height of the parent, changing
if ($(this).scrollTop() > 220 && !isPositionFixed) {
$('.fixedElement').css({'position': 'fixed', 'top': '0px'});
}
to
if ($(this).scrollTop() > 220 && !isPositionFixed) {
$('.fixedElement').parent().height($('.fixedElement').outerHeight(true))
$('.fixedElement').css({'position': 'fixed', 'top': '0px'});
}

How to animate transitions triggered by links

I found this useful jQuery for a navigation that highlights as linked content scrolls. I think I understand how this works, however I'm having trouble including transitions / animations for clicked items. I want the sections to smoothly transition when triggered by the navigation.
I have tried adding this to the CSS
.section {
transition: transform .5s ease-in-out;
}
and also to jQuery
$('#navigation').click(function(){
$('.section').animate('slow');
});
I'd really appreciate an explanation of what I am doing wrong in this particular example.
Here is the code and https://jsfiddle.net/r040p7oa/
<div id="navigation">
<ul>
<li>Section 1</li>
<li>Section 2</li>
</ul>
</div>
<div id="sections">
<div id ="section1" class="section">I'm section 1</div>
<div id ="section2" class="section">I'm section 2
</div>
#sections {
position: absolute;
top: 0;
left: 120px;
}
#navigation {
position: fixed;
top: 0;
left: 0;
}
.active {
background: red;
}
.section {
padding-bottom: 400px;
}
-
$(window).scroll(function() {
var position = $(this).scrollTop();
$('.section').each(function() {
var target = $(this).offset().top;
var id = $(this).attr('id');
if (position >= target) {
$('#navigation > ul > li > a').removeClass('active');
$('#navigation > ul > li > a[href=#' + id + ']').addClass('active');
}
});
});
https://jsfiddle.net/r040p7oa/
$('a').click(function(){
$('html, body').animate({
scrollTop: $( $.attr(this, 'href') ).offset().top
}, 500);
return false;
});
Working fiddle :) Code from here
This should do it:
$('a').click(function(e) {
e.preventDefault();
$('body, html').animate({scrollTop:$($(this).attr("href")).offset().top});
});
Here is the JSFiddle demo

A website can start in a determinate div when load?

A website can start in a determinate div when load?
I make three divs like this.
and I want to start on the second div when the website load.
How I can do it?
html,body {
height:100%;
margin:0;
}
.content {
height:100%;
min-height:100%;
}
html>body .content {
height:auto;
}
#one {
background: #ff4444;
}
#two {
background: #ff5555;
}
#three {
background: #ff6666;
}
<div class='content' id='one'></div>
<div class='content' id='two'></div>
<div class='content' id='three'></div>
You need to use #two (id of the second div) in the url.
like this
You can use smooth animation to scroll to the div using animate:
$('html,body').animate({
scrollTop: $("#two").offset().top
}, 'slow');
Demo.
EDIT
Without Animation:
document.location.href="#two";
Demo
Use this to scroll the second div into view on load:
$(function() {
$("#two")[0].scrollIntoView();
});

jQuery scrollTop - Issue with wrong hash

I am trying to do scrollTop animation to an anchor that resides inside of a fullscreen <section>, but does not scroll to right anchor at first click. Here's my code.
<nav id="scroller"> Scroll me to sub 1
Scroll me to sub 2
Scroll me to sub 3
</nav>
<section id="boxTop"></section>
<section id="boxMaster">
<section id="subBox1">
<p>Hello. I am the Sub 1!</p>
</section>
<section id="subBox2">
<p>Hello. I am the Sub 2!</p>
</section>
<section id="subBox3">
<p>Hello. I am the Sub 3!</p>
</section>
</section>
$("#scroller a").click(function () {
$('#boxMaster').animate({
scrollTop: $(this.hash).offset().top
}, 700);
$("#scroller a").removeClass("active");
$(this).addClass("active");
});
fiddle
$("#scroller a").click(function() {
$('#boxMaster').animate({
scrollTop: $(this.hash).offset().top
}, 700);
$("#scroller a").removeClass("active");
$(this).addClass("active");
});
html,
body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
overflow: hidden;
}
#scroller {
position: fixed;
top: 0;
height: 30px;
text-align: center;
}
#scroller a {
color: #fff;
margin: 0 20px;
text-decoration: none;
}
#scroller a.active {
font-weight: bold;
text-decoration: underline;
}
#boxTop {
width: 100%;
height: 100%;
background: red;
}
#boxMaster {
width: 100%;
height: 100%;
background: blue;
overflow: hidden;
}
#boxMaster #subBox1,
#boxMaster #subBox2,
#boxMaster #subBox3 {
width: 100%;
height: 100%;
display: table;
}
p {
color: #fff;
text-align: center;
display: table-cell;
vertical-align: middle;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<nav id="scroller"> Scroll me to sub 1
Scroll me to sub 2
Scroll me to sub 3
</nav>
<section id="boxTop"></section>
<section id="boxMaster">
<section id="subBox1">
<p>Hello. I am the Sub 1!</p>
</section>
<section id="subBox2">
<p>Hello. I am the Sub 2!</p>
</section>
<section id="subBox3">
<p>Hello. I am the Sub 3!</p>
</section>
</section>
Add the current scroller value to the offset().top(), the latter beeing relative to the top of frame, and get rid of this.hash. Use this.href instead.
$("#scroller a").click(function () {
var y=$('#boxMaster').scrollTop()
$('#boxMaster').animate({
scrollTop: $(this.href).offset().top + y
}, 100);
});
You need to scroll the #boxMaster element relative to the link's position within the element and relative to the #boxMaster element's top position within the body element.
You can do this by adding the #boxMaster element's scrollTop() value with its top position, and then subtracting that from the link's offset top value:
$(this.hash).offset().top - $('#boxMaster').position().top + $('#boxMaster').scrollTop()
Updated Example
var $boxMaster = $('#boxMaster');
$boxMaster.animate({
scrollTop: $(this.hash).offset().top - $boxMaster.position().top + $boxMaster.scrollTop()
}, 700);
You may also need to prevent the link element's default behavior using e.preventDefault(), and then manually scroll the html/body element to the #boxMaster element:
Updated Example
$('html, body').animate({
scrollTop: $boxMaster.offset().top
}, 700);
I have a fixed header. I started with w3school's code. However, I've been struggling with this same problem for so long, finally found a workaround for the "first click incorrect" issue:
Just before (outside) of my click event, I simply created a variable "x", initialized:
var x=1;
Then I have a conditional statement inside the click event checking for x:
if (x==1) {
console.log("x is now: " + x);
x=0;
console.log("x is now: " + x);
jQuery("html, body").animate({
scrollTop: jQuery("div.class-of-element-i-am-scrolling-to" + hash).position().top - jQuery("div.header-container").outerHeight(true) - jQuery("h3.another-element-in-my-way").outerHeight(true)
}, 2000, function(){
return false;
});
} else {
jQuery("html, body").animate({
scrollTop: jQuery("div.class-of-element-i-am-scrolling-to" + hash).position().top
}, 2000, function(){
return false;
});
}
In other words, using "x" as a flag to check if it is the first time the code is run.
If it is, then I am kind of cheating by subtracting the fixed header and the other elements that are pulling my desired div up. Remember to make "x=0" to "drop" the flag.
If it isn't, then it works fine anyway.

JQuery Animation

It's simple slide up animation. The problem is when I change "top" parameter of myDiv class, animation is working incorrectly, instead of sliding up, it slides down from top. It only works incorrectly when I click button for the first time. When I change myDiv's top parameter to a bigger number there is no more problem. Can you please help me to find what is wrong with the code.
<style>
.box {
position:relative;
width: 200px;
height: 500px;
}
.myDiv {
position: absolute;
width:100%;
overflow: hidden;
bottom:0px;
top:10px;
left:500;
}
</style>
<script>
var swt = 0;
$(document).ready(function () {
$(".b1").click(function () {
var div = $(".myDiv");
if (swt == 0) {
div.animate({
top: '300px',
opacity: '1'
}, "slow");
// div.animate({height:'300px', opacity:'1'},"slow");
swt++;
} else {
div.animate({
top: '500px',
opacity: '1'
}, "slow");
// div.animate({height:'0px', opacity:'1'},"slow");
swt--;
}
});
});
</script>
</head>
<body>
<button class="b1">Start Animation</button>
<p>posds</p>
<div class="box">
<div class="myDiv" style="background:#7549B1; width:200px;"></div>
</div>
</body>
</html>
I'm not really sure whay effect do you want, but maybe it's changing the bottom value instead of top:
if(swt==0){
div.animate({bottom:'500px', opacity:'1'}, "slow");
swt++;
} else {
div.animate({bottom:'300px', opacity:'1'}, "slow");
swt--;
}
http://jsbin.com/ixigaf/1/edit
Do not use bottom and top on a same element, it will create a conflict. Define height and animte top with negative value:
Here is jsFiddle.
if(swt==0){
div.animate({top:'-300px', opacity:'1'}, "slow");
swt++;
}else{
div.animate({top:'-500px', opacity:'1'}, "slow");
swt--;
}
http://jsfiddle.net/Cyberek/yLBeK/
This is as I understand buggy, but if You change in css top from 10px to 100px (same as top in js) everything should be ok.
.myDiv {
position: absolute;
width:100px;
height: 100px;
overflow: hidden;
top:100px;
left:100px;
background: red;
}
$(".b1").click(function () {
var div = $(".myDiv");
if (swt == 0) {
div.animate({
top: '100px',
opacity: '1'
}, "slow");
// div.animate({height:'300px', opacity:'1'},"slow");
swt++;
} else {
div.animate({
top: '200px',
opacity: '1'
}, "slow");
// div.animate({height:'0px', opacity:'1'},"slow");
swt--;
}
});

Categories