I'm trying to make some of my element fixed for vertical and horizontal scrolling and looked up some examples on stackoverflow but I could not figure out why they work, therefore I cannot use it for a different purpose:
This is the code that everybody gives, and it works:
$(window).scroll(function() {
$('#header').css({
'top': $(this).scrollTop() + 15,
'left': $(this).scrollLeft() + 15 // top, left = 15px in css
});
}
So what it is doing is set the position of top and left of the header id tag so everytime window is scrolled, it goes to the position relative to window?
$(this).scrollTop() always print out 0 in my test however, if I do the below instead, it stop working:
function test() { /* Original code example, keeping this unmodified so some answers doesn't seem strange */
$('#header').css({
'top': 15,
'left': 15 // hardcode 15 just for example
});
}
What is the purpose of $(this).scrollTop() here that makes or breaks the functionality?
Lastly, I'm not allowed to use JQuery so I use javascript and none of these variations are working. Could you tell me what I'm doing wrong?
function test() {
var header = getElementById('header');
header.style.top = header.scrollTop + 15;
header.style.left = header.scrollLeft + 15;
}
also tried few others such as: using '15px', 15 + 'px'.
edit: modified first code example to the correct original code from stackoverflow
The getElementById function is not global on its own -- it is under the global document object. So you must use var header = document.getElementById('header');
Next, the browser's native scrollTop and scrollLeft functions used on a DOM element will tell you the scroll inside that element. For instance, for scrollTop is the measurement from the top of the element (which may be hidden because of scroll) to the top visible edge (In other words, it is the distance above the visible part of the element -- the part that's been hidden because of internal scrolling). If the top of the header element is always completely visible (and the header doesn't have it's own scrollbar), then this distance will always be zero.
To position the header relative to the scroll of the browser window, you may want to get the pageYOffset and pageXOffset on the window element instead, and then position the header based on that. For instance, window.pageYOffset + 15.
Here is a safer alternative that checks various possible places for the page's scroll (helps with browser compatibility).
var scrollTop = function(){
return (window.pageYOffset !== undefined) ? window.pageYOffset : (document.documentElement || document.body.parentNode || document.body).scrollTop;
}
var scrollLeft = function(){
return (window.pageXOffset !== undefined) ? window.pageXOffset : (document.documentElement || document.body.parentNode || document.body).scrollLeft;
}
The last thing is that element.style.top should be given a string value that is like "10px", so you will need to do the calculation first and then add + 'px' at the end.
eg. header.style.top = window.scrollTop + 15 + "px";
Putting that all together:
var scrollTop = function(){
return (window.pageYOffset !== undefined) ? window.pageYOffset : (document.documentElement || document.body.parentNode || document.body).scrollTop;
}
var scrollLeft = function(){
return (window.pageXOffset !== undefined) ? window.pageXOffset : (document.documentElement || document.body.parentNode || document.body).scrollLeft;
}
function test() {
var header = document.getElementById('header');
header.style.top = scrollTop() + 15 + 'px';
header.style.left = scrollLeft() + 15 + 'px';
}
Good luck! Hope that helps!
top and left property of css not going to work in this condition if you do not
add position property ..
function test() {
$('#header').css({
'position':'absolute',
'top': $(this).scrollTop() + 215,
'left': $(this).scrollLeft() + 15 // top, left = 15px in css
});
}
LIVE http://jsfiddle.net/mailmerohit5/t45ktx4r/
Related
I'm creating a parallax effect and I've made it so that (almost) every element has a different scroll speed.
I've also made it so that elements down the page don't trigger their scroll speed until they've reached the viewport.
Here's the JS for trigger commands on reveal:
function isElementInViewport (el) {
if (typeof jQuery === "function" && el instanceof jQuery) {
el = el[0];
}
var rect = el.getBoundingClientRect();
return (
rect.bottom >= 0 &&
rect.left >= 0 &&
rect.top <= (window.innerHeight || document.documentElement.clientHeight) &&
rect.right <= (window.innerWidth || document.documentElement.clientWidth)
);
}
My scroll speed code is:
$(window).scroll(function(){
var wScroll = $(this).scrollTop();
if (isElementInViewport($('#computer'))) {
$('#computer').css({
transform' : 'translate(0px, '+ wScroll /12 +'%)'
});
}
OR for elements already at the top of page:
$(window).scroll(function(){
var wScroll = $(this).scrollTop();
$('#shape-2').css({
'transform' : 'translate(0px, -'+ wScroll /8 +'%)'
});
The issue here is that when I add function isElementInViewport to the scroll speed.
It makes the element jump out of view when revealed, THEN it scrolls how I want it.
So, then it's out of place with the layout of the page.
I've tried compensating it by changing the position of the element so that when it's revealed it jumps to its original spot then starts scrolling, but this didn't prove helpful since the position varied from different screen sizes and resolutions.
Any way I can make it so it doesn't jump when revealed?
Make sure your base CSS declares a translation transform of zero, or add it from script before the element is in view; adding the attribute later may be causing the jump.
I need to retrieve the visible height of a div within a scrollable area. I consider myself pretty decent with jQuery, but this is completely throwing me off.
Let's say I've got a red div within a black wrapper:
In the graphic above, the jQuery function would return 248, the visible portion of the div.
Once the user scrolls past the top of the div, as in the above graphic, it would report 296.
Now, once the user has scrolled past the div, it would again report 248.
Obviously my numbers aren't going to be as consistent and clear as they are in this demo, or I'd just hard code for those numbers.
I have a bit of a theory:
Get the height of the window
Get the height of the div
Get the initial offset of the div from the top of the window
Get the offset as the user scrolls.
If the offset is positive, it means the top of the div is still visible.
if it's negative, the top of the div has been eclipsed by the window. At this point, the div could either be taking up the whole height of the window, or the bottom of the div could be showing
If the bottom of the div is showing, figure out the gap between it and the bottom of the window.
It seems pretty simple, but I just can't wrap my head around it. I'll take another crack tomorrow morning; I just figured some of you geniuses might be able to help.
Thanks!
UPDATE: I figured this out on my own, but looks like one of the answers below is more elegant, so I'll be using that instead. For the curious, here's what I came up with:
$(document).ready(function() {
var windowHeight = $(window).height();
var overviewHeight = $("#overview").height();
var overviewStaticTop = $("#overview").offset().top;
var overviewScrollTop = overviewStaticTop - $(window).scrollTop();
var overviewStaticBottom = overviewStaticTop + $("#overview").height();
var overviewScrollBottom = windowHeight - (overviewStaticBottom - $(window).scrollTop());
var visibleArea;
if ((overviewHeight + overviewScrollTop) < windowHeight) {
// alert("bottom is showing!");
visibleArea = windowHeight - overviewScrollBottom;
// alert(visibleArea);
} else {
if (overviewScrollTop < 0) {
// alert("is full height");
visibleArea = windowHeight;
// alert(visibleArea);
} else {
// alert("top is showing");
visibleArea = windowHeight - overviewScrollTop;
// alert(visibleArea);
}
}
});
Calculate the amount of px an element (height) is in viewport
Fiddle demo
This tiny function will return the amount of px an element is visible in the (vertical) Viewport:
function inViewport($el) {
var elH = $el.outerHeight(),
H = $(window).height(),
r = $el[0].getBoundingClientRect(), t=r.top, b=r.bottom;
return Math.max(0, t>0? Math.min(elH, H-t) : Math.min(b, H));
}
Use like:
$(window).on("scroll resize", function(){
console.log( inViewport($('#elementID')) ); // n px in viewport
});
that's it.
jQuery .inViewport() Plugin
jsFiddle demo
from the above you can extract the logic and create a plugin like this one:
/**
* inViewport jQuery plugin by Roko C.B.
* http://stackoverflow.com/a/26831113/383904
* Returns a callback function with an argument holding
* the current amount of px an element is visible in viewport
* (The min returned value is 0 (element outside of viewport)
*/
;(function($, win) {
$.fn.inViewport = function(cb) {
return this.each(function(i,el) {
function visPx(){
var elH = $(el).outerHeight(),
H = $(win).height(),
r = el.getBoundingClientRect(), t=r.top, b=r.bottom;
return cb.call(el, Math.max(0, t>0? Math.min(elH, H-t) : Math.min(b, H)));
}
visPx();
$(win).on("resize scroll", visPx);
});
};
}(jQuery, window));
Use like:
$("selector").inViewport(function(px) {
console.log( px ); // `px` represents the amount of visible height
if(px > 0) {
// do this if element enters the viewport // px > 0
}else{
// do that if element exits the viewport // px = 0
}
}); // Here you can chain other jQuery methods to your selector
your selectors will dynamically listen to window scroll and resize but also return the initial value on DOM ready trough the first callback function argument px.
Here is a quick and dirty concept. It basically compares the offset().top of the element to the top of the window, and the offset().top + height() to the bottom of the window:
function getVisible() {
var $el = $('#foo'),
scrollTop = $(this).scrollTop(),
scrollBot = scrollTop + $(this).height(),
elTop = $el.offset().top,
elBottom = elTop + $el.outerHeight(),
visibleTop = elTop < scrollTop ? scrollTop : elTop,
visibleBottom = elBottom > scrollBot ? scrollBot : elBottom;
$('#notification').text(`Visible height of div: ${visibleBottom - visibleTop}px`);
}
$(window).on('scroll resize', getVisible).trigger('scroll');
html,
body {
margin: 100px 0;
}
#foo {
height: 1000px;
background-color: #C00;
width: 200px;
margin: 0 auto;
}
#notification {
position: fixed;
top: 0;
left: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<div id="foo"></div>
<div id="notification"></div>
The logic can be made more succinct if necessary, I've just declared separate variables for this example to make the calculation as clear as I can.
Here is a version of Rory's approach above, except written to function as a jQuery plugin. It may have more general applicability in that format. Great answer, Rory - thanks!
$.fn.visibleHeight = function() {
var elBottom, elTop, scrollBot, scrollTop, visibleBottom, visibleTop;
scrollTop = $(window).scrollTop();
scrollBot = scrollTop + $(window).height();
elTop = this.offset().top;
elBottom = elTop + this.outerHeight();
visibleTop = elTop < scrollTop ? scrollTop : elTop;
visibleBottom = elBottom > scrollBot ? scrollBot : elBottom;
return visibleBottom - visibleTop
}
Can be called with the following:
$("#myDiv").visibleHeight();
jsFiddle
Here is the improved code for jquery function visibleHeight: $("#myDiv").visibleHeight();
$.fn.visibleHeight = function() {
var elBottom, elTop, scrollBot, scrollTop, visibleBottom, visibleTop, height;
scrollTop = $(window).scrollTop();
scrollBot = scrollTop + $(window).height();
elTop = this.offset().top;
elBottom = elTop + this.outerHeight();
visibleTop = elTop < scrollTop ? scrollTop : elTop;
visibleBottom = elBottom > scrollBot ? scrollBot : elBottom;
height = visibleBottom - visibleTop;
return height > 0 ? height : 0;
}
I am trying to determine if the user has scrolled up or down and I found some code in a different answer that seems to help me out. My one problem with this code is that I cannot wrap my head around how to capture last_scroll_position. I have a function set up to that returns scrollTop so getting the value for the variable current_position is not a problem, but getting the value for last_scroll_position seems a bit tricky.
Here is the answer I found...
Keep a variable, say, last_scroll_position, and when you have a scroll, if last_scroll_position - current_position > 0, the user scrolled up, and down if it's less than 0.
Differentiate between scroll up/down in jquery?
I recommend that check out this example: stackoverflow.com/a/24815216...
The scroll event behaves oddly in Firefox, it is fired a lot of times because of the smoothness scrolling, but it works, here are an example:
//creates an element to print the scroll position
$("<p id='test'>").appendTo("body").css({
padding: "5px 7px",
background: "#e9e9e9",
position: "fixed",
bottom: "35px",
left: "35px" });
//binds the "scroll" event
$(window).scroll(function (e) {
var target = e.currentTarget,
scrollTop = target.scrollTop || window.pageYOffset,
scrollHeight = target.scrollHeight || document.body.scrollHeight,
lastScrollTop = $(target).data("lastScrollTop") || 0,
scrollText = "";
if (scrollTop > lastScrollTop) {
scrollText = "<b>scroll down</b>";
} else {
scrollText = "<b>scroll up</b>";
}
$("#test").html(scrollText +
"<br>scrollTop: " + scrollTop +
"<br>lastScrollTop: " + lastScrollTop);
if (scrollHeight - scrollTop === $(target).innerHeight()) {
console.log("► End of scroll");
}
//saves the current scrollTop
$(target).data("lastScrollTop", scrollTop);
});
Using jQuery, how do I determine the height/distance between the very top of the browser window to the bottom of a div, such as a header. I'm using the following code:
$(window).resize(function() {
$totalHeight = $(window).height();
$headerHeight = $('header').height();
$('#portfolio-info').css('height',($totalHeight - $headerHeight - 105) + 'px');
});
And I want to make sure that $headerHeight isn't always the same value, as you scroll away from the header it should decrease all the way down to zero.
Thanks!
This should work out for you.
$(window).resize(function() {
var top = $(this).scrollTop(),
bottomDiv = $('div').offset().top + $('div')[0].offsetHeight,
distance = Math.max(0, (top - bottomDiv) * -1);
});
In a web application, I have a page that contains a DIV that has an auto-width depending on the width of the browser window.
I need an auto-height for the object. The DIV starts about 300px from the top screen, and its height should make it stretch to the bottom of the browser screen. I have a max height for the container DIV, so there would have to be minimum-height for the div. I believe I can just restrict that in CSS, and use Javascript to handle the resizing of the DIV.
My javascript isn't nearly as good as it should be. Is there an easy script I could write that would do this for me?
Edit:
The DIV houses a control that does it's own overflow handling (implements its own scroll bar).
Try this simple, specific function:
function resizeElementHeight(element) {
var height = 0;
var body = window.document.body;
if (window.innerHeight) {
height = window.innerHeight;
} else if (body.parentElement.clientHeight) {
height = body.parentElement.clientHeight;
} else if (body && body.clientHeight) {
height = body.clientHeight;
}
element.style.height = ((height - element.offsetTop) + "px");
}
It does not depend on the current distance from the top of the body being specified (in case your 300px changes).
EDIT: By the way, you would want to call this on that div every time the user changed the browser's size, so you would need to wire up the event handler for that, of course.
What should happen in the case of overflow? If you want it to just get to the bottom of the window, use absolute positioning:
div {
position: absolute;
top: 300px;
bottom: 0px;
left: 30px;
right: 30px;
}
This will put the DIV 30px in from each side, 300px from the top of the screen, and flush with the bottom. Add an overflow:auto; to handle cases where the content is larger than the div.
Edit: #Whoever marked this down, an explanation would be nice... Is something wrong with the answer?
document.getElementById('myDiv').style.height = 500;
This is the very basic JS code required to adjust the height of your object dynamically. I just did this very thing where I had some auto height property, but when I add some content via XMLHttpRequest I needed to resize my parent div and this offsetheight property did the trick in IE6/7 and FF3
If I understand what you're asking, this should do the trick:
// the more standards compliant browsers (mozilla/netscape/opera/IE7) use
// window.innerWidth and window.innerHeight
var windowHeight;
if (typeof window.innerWidth != 'undefined')
{
windowHeight = window.innerHeight;
}
// IE6 in standards compliant mode (i.e. with a valid doctype as the first
// line in the document)
else if (typeof document.documentElement != 'undefined'
&& typeof document.documentElement.clientWidth != 'undefined'
&& document.documentElement.clientWidth != 0)
{
windowHeight = document.documentElement.clientHeight;
}
// older versions of IE
else
{
windowHeight = document.getElementsByTagName('body')[0].clientHeight;
}
document.getElementById("yourDiv").height = windowHeight - 300 + "px";
With minor corrections:
function rearrange()
{
var windowHeight;
if (typeof window.innerWidth != 'undefined')
{
windowHeight = window.innerHeight;
}
// IE6 in standards compliant mode (i.e. with a valid doctype as the first
// line in the document)
else if (typeof document.documentElement != 'undefined'
&& typeof document.documentElement.clientWidth != 'undefined'
&& document.documentElement.clientWidth != 0)
{
windowHeight = document.documentElement.clientHeight;
}
// older versions of IE
else
{
windowHeight = document.getElementsByTagName('body')[0].clientHeight;
}
document.getElementById("foobar").style.height = (windowHeight - document.getElementById("foobar").offsetTop - 6)+ "px";
}
Simplest I could come up...
function resizeResizeableHeight() {
$('.resizableHeight').each( function() {
$(this).outerHeight( $(this).parent().height() - ( $(this).offset().top - ( $(this).parent().offset().top + parseInt( $(this).parent().css('padding-top') ) ) ) )
});
}
Now all you have to do is add the resizableHeight class to everything you want to autosize (to it's parent).
inspired by #jason-bunting, same thing for either height or width:
function resizeElementDimension(element, doHeight) {
dim = (doHeight ? 'Height' : 'Width')
ref = (doHeight ? 'Top' : 'Left')
var x = 0;
var body = window.document.body;
if(window['inner' + dim])
x = window['inner' + dim]
else if (body.parentElement['client' + dim])
x = body.parentElement['client' + dim]
else if (body && body['client' + dim])
x = body['client' + dim]
element.style[dim.toLowerCase()] = ((x - element['offset' + ref]) + "px");
}