If you do not know what position:sticky is, watch this 20 second long video: https://www.youtube.com/watch?v=jA67eda5i-A .
This CSS feature was in talks in W3 and implemented in gecko I believe. But that is besides the point, the point is that not all browsers support it and I really want that functionality.
Is there any way I can get this using a mix of CSS and/or javascript and/or jquery?
There is an easy jquery plugin for this:: http://stickyjs.com/
To avoid using a plugin, i have created the following javascript method using jquery 1.8+.
The first argument is the element that you want to set sticky.
The second argument is optionnal and is a boolean to enhance the browser performance by setting a small timeout of 300ms.
function simulateSticky(elt, timeout) {
var move = function() {
var scrollTop = $(window).scrollTop();
var scrollBottom = $(document).height() - scrollTop - $(window).height();
var eltTop = elt.parent().offset().top;
var eltBottom = $(document).height() - eltTop - elt.parent().outerHeight();
if (scrollTop < eltTop) { // Top case
elt.css({
position: "absolute",
width: "100%",
top:"auto",
right: "0px",
bottom: "auto",
left: "0px",
});
}
else if (scrollTop >= eltTop && scrollBottom >= eltBottom) { // Middle case
elt.css({
position: "fixed",
width: elt.parent().outerWidth(),
top:"0px",
right: "auto",
bottom: "auto",
left: "auto",
});
}
else { // Bottom case
elt.css({
position: "absolute",
width: "100%",
top:"auto",
right: "0px",
bottom: "0px",
left: "0px",
});
}
};
// Use of a timeout for better performance
if (timeout) {
var timeoutId;
$(window).scroll(function() {
clearTimeout(timeoutId);
timeoutId = setTimeout(function() {
move();
}, 300);
});
}
else {
$(window).scroll(move);
}
// Initial call
move();
}
Related
I've created a sticky sidebar function which works perfectly in chrome and safari but not in Firefox. From what I can tell it's not returning properly when it should be.
Consider a snippet of the code in question:
if (scrolling_down && bottom_offset <= bottom_padding) {
$item.css({
position: 'absolute',
top: 'auto',
bottom: bottom_padding
});
console.log(1);
return false;
console.log(2);
}
console.log(3);
The console in Chrome logs 3 until it hits the bottom of the page then logs 1 for the rest of the scroll.
In Firefox however, the console logs 3 until it hits the bottom then alternates between 3 and 1.
I'm pretty sure it should be ignoring 3 (because of the return false) once it's hit the bottom, like Chrome.
Full Javascript:
// Sticky Sidebars
stickyAsides: function() {
var $item = $('.js-sticky'),
$parent = $item.parent(),
last_scroll = 0,
scrolling_down = false;
function setStyles() {
$item.css({
width: $item.outerWidth()
});
}
function stick() {
var parent_rect = $parent.get(0).getBoundingClientRect(),
parent_top = parent_rect.top,
parent_bottom = parent_rect.bottom,
item_rect = $item.get(0).getBoundingClientRect(),
item_top = item_rect.top,
item_bottom = item_rect.bottom,
bottom_offset = parent_bottom - item_bottom,
bottom_padding = parseInt($parent.css('padding-bottom'));
scrolling_down = (last_scroll < w.scroll) ? true : false;
setStyles();
if (scrolling_down && bottom_offset <= bottom_padding) {
$item.css({
position: 'absolute',
top: 'auto',
bottom: bottom_padding
});
console.log(1);
return false;
console.log(2);
}
console.log(3);
if (item_top <= -10 || parent_top <= 0) {
$item.css({
position: 'fixed',
top: '0',
bottom: 'auto'
});
}
if (!scrolling_down && parent_top > 0) {
$item.css({
position: 'relative',
top: '0',
bottom: 'auto'
});
}
last_scroll = w.scroll;
}
$(window).on('scroll', function(){
w.scroll = $doc.scrollTop();
if (Modernizr.mq('(min-width: 1024px)') && Modernizr.flexbox) {
stick();
}
});
}, // End stickyAsides()
EDIT: Codepen Example: http://codepen.io/jhealey5/pen/JGLjPN - However this seems to work okay, so there is something else interfering on the page. I don't expect anyone to solve it but there might be some advice. I'm unable to link to the live page at this time I'm afraid.
Seems Firefox wasn't doing calculations correctly. Adding +20px to the bottom padding calculation seems to fix it.
i have a function to stick the nav sidebar to the top after some scrolling.but when my screen minimizes the logo on the top shortens and the position of the nav changes.so i wrote another 'if' function inside the first one to solve the problem.now the position is correct but the nav side bar is fixing on the top while scrolling.can you please help me....the function is as below....
$(function() {
var stickyHeaderTop = $('#myScrollspy').offset().top;
var yy = document.getElementById("cor").clientHeight;
$(window).scroll(function() {
if ($(window).scrollTop() > stickyHeaderTop) {
$('#myScrollspy').css({
position: 'fixed',
top: '8px',
left: '0px'
});
$('#my').css({
position: 'absolute',
right: '0px'
});
} else {
setInterval(function() {
if (yy < '490') {
var yu = '500' - yy;
$('#myScrollspy').css({
position: 'absolute',
top: ''
700 '-yy',
left: '0px'
});
$('#my').css({
position: 'absolute',
right: '0px'
});
}
}, 30);
}
});
});
You have some syntax issues, have mentioned them in the comments below.
if (yy < 490) { //syntax issue here
var yu = 500 - yy; //syntax issue here
$('#myScrollspy').css({
position: 'absolute',
top: (700 - yy)+'px', //syntax issue here
left: '0px'
});
$('#my').css({
position: 'absolute',
right: '0px'
});
}
document.getElementById("cor").clientHeight will return an int(number).
Check element.clientHeight
Note: This property will round the value to an integer. If you need a fractional value, use element.getBoundingClientRect().
I have a table on the right of my page( with id="efficacia"). I wrote this JS script in order to shift left/right clicking on it
JavaScript
$("#efficacia").click(function() {
var posizione = $("#efficacia").position();
if(posizione.right != 0) {
$(this).animate({
right: '0'
}, 1000);
} else {
$(this).animate({
right: '-202'
}, 1000);
}
});
CSS
#efficacia {
position: fixed;
right: -202px;
top: 200px;
cursor: pointer;
z-index: 100;
}
My script works well for the first "click", then when I click again it does not shitf on the right of 202px. It looks like that function does not enter in else statemet.
position().right does not exist. Only top and left.
http://api.jquery.com/position/
Base your condition on left attribute and it will work
position doesn't return a right property.
You can get the right css property so:
$("#efficacia").click(function() {
var right = parseInt($(this).css('right'));
if(right != 0) {
$(this).animate({
right: '0'
}, 1000);
} else {
$(this).animate({
right: '202'
}, 1000);
}
});
See the DEMO.
If you want get position of all corners then you can use getBoundingClientRect(). It will returns bottom, right, left, top, width and height of your div. But, of course, it will return values that starts from left corner.
var boundingBox = $(this).get(0).getBoundingClientRect();
console.log(boundingBox.right);
Read about getBoundingClientRect()
There's an error in your code at right: '-202'. You have to specify right: '-202px'.
Here's the updated code:
$("#efficacia").click(function() {
var right = $(this).css('right');
if(right != "0px") {
$(this).animate({
right: '0px'
}, 1000);
} else {
$(this).animate({
right: '-202px'
}, 1000);
}
});
That's it
jQuery.position() doesn't return value for style.right. It returns only
Object{top: somVal, left: somVal}
so if u want to get the value of right then get it from style attribute
Eg-
$("#efficacia").click(function() {
// var posizione = $("#efficacia").position();//here right is undefined
var right=this.style.right.replace("px", "") * 1;//fetch value of right from style
if(right != 0) {
$(this).animate({
right: '0'
}, 1000);
} else {
$(this).animate({
right: '202'
}, 1000);
}
});
This example I've found is exactly what I was looking for: http://jsfiddle.net/sg3s/RZpbK/
Thx to the author sg3s
jQuery(function($) {
$('a.panel').click(function() {
var $target = $($(this).attr('href')),
$other = $target.siblings('.active'),
animIn = function () {
$target.addClass('active').show().css({
right: -($target.width())
}).animate({
left: 0
}, 500);
};
if (!$target.hasClass('active') && $other.length > 0) {
$other.each(function(index, self) {
var $this = $(this);
$this.removeClass('active').animate({
left: -$this.width()
}, 500, animIn);
});
} else if (!$target.hasClass('active')) {
animIn();
}
});
});
But I got a little problem with it. I would like the panels to "open" and "close" from the right. I'm not familiar with javascript and I'm not able to tweak it properly.
Can anyone help me with this ?
Like this?
http://jsfiddle.net/RZpbK/845/
All I did was modify the animIn to:
animIn = function () {
$target.addClass('active').show().css({
left: +($target.width())
}).animate({
left: 0
}, 500);
};
Just replace the left: -($target.width()) with left: $target.width() in both places
Based on your previous comment, this is more what you want?
http://jsfiddle.net/RZpbK/847/
Just changed it so animIn executed right away instead of as a callback after the fadeout was done.
$this.removeClass('active').animate({
left: -$this.width()
}, 500);
animIn();
I would like to have a google map on my page in its own column, that will slide up and down to match the scroll height of the browser window. I've seen this functionality on a few sites (yelp comes to mind). Does anyone know a good jQuery plugin that implements this functionality? I am not even sure how to search for such a plugin because I'm not exactly sure what to call it.
Edit: Using Alley's solution, I came up with this as the final answer:
$(function() {
$(window).scroll(function() {
var $map = $('#mymap');
var locMin = 0;
var locMax = $map.parent().height() - $map.height()
var dif = $(window).height() / 2 - $map.height() / 2;
var loc = dif + $(window).scrollTop() - $map.parent().offset().top;
if (loc > locMax)
loc = locMax;
if (loc < locMin)
loc = locMin;
$map.css('top', loc);
})
make sure to use CSS to make the #mymap element to be position: relative.
Just wrote one quickly for you:
$(function() {
$(window).scroll(function() {
if($('#map').offset().top <= 0) {
$('#map').css({ position: 'fixed', top: 0, left: '50%', 'margin-left': YOUR PAGE WIDTH / 2 - $('#map').width() })
} else {
$('#map').css({ position: 'relative', top: 'auto', left: 'auto', margin:0 })
}
})
})