I have a div, absolutely positioned, originally non-visible that is shown at the position of an element being clicked rendering its preview (top position of the preview is lined to the top of the element clicked).
When the element being clicked is positioned low, the preview is render somewhat below the original page border, and scrolling is necessary. I want to move the preview upward to have its bottom edge on the previous page bottom limit. The problem is the code I use doesn't return what is expected for the page height (it is greater than the sum of the preview height and the clicked-element top position).
Here's the code:
file 1:
jQuery('elementClicked').live('click',function(){
...
jQuery("previewDiv").setTopAtClickedElement(jQuery(this));
...
}
file 2:
jQuery.fn.setTopAtClickedElement = function (element) {
//original positioning
this.css('top', element.offset().top + 'px');
// the troublesome part where the eventual correction should be done
if (element.offset().top + this.height() > jQuery(document).height())
{
this.css('top', jQuery(document).height() - this.height() + 'px');
}
}
Similar happens when I use
Math.max(document.body.scrollHeight, document.body.offsetHeight, document.documentElement.clientHeight, document.documentElement.scrollHeight, document.documentElement.offsetHeight)
for the measure of the document height as suggested on a link
Do you have any suggestions on how I should implement this troublesome part of the code?
Please tell if I wasn't clear enough,
Thank you,
Instead of .height() Try using jQuery's outer.height() - api docs, which will take into account any padding (and optionally marign) you have on the page.
A jsfiddle or codepen will help us all out in solving your problem.
Related
I need to know if the end of a div element is currently visible in the users' browser.
I tried something I saw on the web, but scrollTop() always gave me zero in my Browser. I read something about an issue in Chrome, but I didn't understand quite well.
jQuery(
function($) {
$('#flux').bind('scroll', function() {
if ($(this).scrollTop() + $(this).innerHeight() >= $(this)[0].scrollHeight) {
alert('end reached');
}
})
}
);
My idea is the following:
1- User loads page and sees a Bar (sticky div at bottom visible page) with some information.
2- After scrolling a bit, and reaching the end of a div element, this bar will position there, after the div. This is the bar's original position
I wasn't really able to know when I was at the end of the div element. Eventually I found this code:
if ($(window).scrollTop() >= $('#block-homepagegrid').offset().top + $('#block-homepagegrid').outerHeight() - window.innerHeight) {
$('.hero-special-message').removeClass('hero-special-messege-scrolling');
} else {
$('.hero-special-message').addClass('hero-special-messege-scrolling');
}
});
I see that it's working, but I'm having a bit of trouble understanding what it does.
I know the following:
1. $(window).scrollTop();
this gives me the amount of pixels the user has scrolled, pretty self explanatory.
2. $('#block-homepagegrid').offset().top;
I THINK this is the distance between the start of the page and the start of the div. I know it's the current coordinates, but what is top exactly here?
3. $('#block-homepagegrid').outerHeight();
this gives the height of the element, I know there are 3, like
height(), innerHeight() and outerHeight(), if you want to take into
account border, margin, padding, which is the better to use?
4. window.innerHeight;
I understand this is what the user sees, but I'm having troubles understanding why does it matter for my situation.
Thanks!
You may be interested in the native JavaScript IntersectionObserver API. It automatically figures out what percentage of a given element is visible in the window and triggers callbacks based on that. So then you can do this:
function visibleHandler(entries) {
if (entries[0].intersectionRatio >= 1.0) {
// The whole element is visible!
} else {
// Part of it is scrolled offscreen!
}
}
const observer = new IntersectionObserver(visibleHandler, {threshold: 1.0});
observer.observe(document.getElementById('flux'));
Now, whenever the element with ID flux is 100% in view, it will trigger the visibleHandler. It will also trigger again if it's scrolled back out of view; that's why the function checks the ratio of visibility to see if it just hit 100% or just got reduced from 100%. You could be more fancy and use the observer entry's insersectionRect, which gives you the rectangle containing the visible portion of the element, and use that to determine top/bottom visibility.
The issue is as such - I'm using jQuery to set the height of a container. I am using the plugin bgStretcher 3.1.2 to stretch an image to the dimensions of this container. In screenshot 1 the container I am reffering to is the area occupied y the brick wall image.
The problem arises when you resize the browser, every 2nd time the resize fires the calculations for height/width are off by 15px (I have no idea where this number comes from), creating a gap to the right and bottom of the container as visible in Screenshot 2. This screenshot also includes the console readings of the height of the container as returned by Jquery, indicating the issue. So when you resize the container jitters like hell and potentially ends up with the aforementioned gap.
I believe there is some sort of conflict happening between my code and the plugin as they're both bound to window resize.
This is the simple bit of code I'm using on my end:
win.resize(function() {
console.log(win.height());
conH = win.height()-68;
wrapper.css({
height: conH+"px"
})
}).resize();
function init_heght(element) {
var y = $(window).height();
$(element).css('height', y);
};
init_heght('#section-left-menu');
I have been looking into parallax effects for vertical scrolling on my web page, and after some research, I'm not sure that what I want to do is technically a parallax effect.
From what I've seen, most parallax effects assume you want to be able to scroll indefinitely with many background images rolling by, or with huge images that repeat.
What I want to do is have the background of two DIVs be filled with a background image as the scroll bar reaches the bottom of the page. Note that I do not want the background images to stretch. I'm assuming to get the effect I want that these images would have a vertical height bigger than most people's viewport, and then their vertical position would change. When the user's scrollbar is at the top, a certain amount of the background is visible, and then it moves vertically to fill the background space as the user scrolls down.
Please see the image below for a visual explanation of the effect I hope to acheive:
The height of the veiwport will vary depending on the length of content inside the inner DIV.
My trouble is that if what I am trying to do is not exactly a parallax effect, then I don't know what else to call it, and my attempts to search by describing it keep landing me back at pages offering tutorials on parallax effects. So I've been stumped by a lack of terminology.
If someone could direct me to how I can control the vertical position of the background depending on the scrollbar position, that would be much appreciated. If this can be done with just CSS that would be great, but I'm assuming some Javascript would be required. A jQuery solution would also work for me.
Update:
After searching using the terms provided in comments, I've got the background image in the outer DIV to almost do what I want with the following code:
$(window).scroll(function () {
var yPos = $("#outerDiv").height() - ($("#outerDIV").height() * ($(window).scrollTop() / $(window).height()));
document.getElementById('outerDIV').style.backgroundPosition="0px " + yPos + "px";
});
It moves the background image in the right direction relative to the scrolling, but what it lacks is constraining that motion to within the viewport. Getting the right proportions based on the viewport and DIV sizes is proving to be just a little beyond my mathematical abilities.
For your requirement, you have to use a jquery parallax plugin to guide this activity, my best suggest it to use a Superscollorama and play with the elements as your wish...
As far as your question, Try this example,
controller.addTween(
'#examples-background',
(new TimelineLite())
.append([
TweenMax.fromTo($('#parallax-it-left'), 1,
{css:{backgroundPosition:"(0 -54px)"}, immediateRender:true},
{css:{backgroundPosition:"(0 -54px)"}}),
TweenMax.fromTo($('#parallax-it-right'), 1,
{css:{backgroundPosition:"(0 -54px)"}, immediateRender:true},
{css:{backgroundPosition:"(0 54px)"}})
]),
1000 // scroll duration of tween
);
You serial vice change as far as your wish...
Try practice this plugin, hope that works for you...
http://johnpolacek.github.io/superscrollorama/
Thanks...
Turns out what I want to acheive is possible with no special plugins, just some carefully thought out math. I did use a little jQuery syntax, but I don't think it's strictly necessary.
The code below has copious notes, so hopefully it's largely explanatory. In summary, you just need to find the position of the background image when the scroll would be at the top, and the position it would be if the scroll bar was at the bottom, and then you can use the percentage of the scrollbar's movement to work out where you are between those two points. It's a little tricker than just that, of course, in that you have to account for the difference between the total height of the scroll bar and where your DIV appears on the page and a few other adjustments, but the details of what I did are below.
What I've done here is just for the "outer DIV" that I described in my question. To get a background to move like the "inner DIV" I described, you'd have to modify the code, presumeably by reversing a few parameters. I haven't done that yet, but it seems like a straightforward task.
Hope others find this code useful. If anyone has suggestions on how it can be made more efficient or better, please let me know.
function moveBG(){
// imageHeight is not the total height of the image,
// it's the vertical amount you want to ensure remains visible no matter what.
var imageHeight = 300;
// Get the maximum amount within the DIV that the BG can move vertically.
var maxYPos = $("#outerDIV").height() - imageHeight;
// Get the amount of vertical distance from the top of the document to
// to the top of the DIV.
var headerHeight = document.getElementById("outerDIV").offsetTop;
// Calculate the BG Y position for when the scrollbar is at the very top.
var bgTopPos = $(window).height() - headerHeight - imageHeight;
// I don't want the image to wander outside of the DIV, so ensure it never
// goes below zero.
if (bgTopPos < 0)
{
bgTopPos = 0;
}
// Calculate the BG Y position when the scrollbar is at the very top.
var bgBottomPos = $(document).height() - $(window).height() - headerHeight;
// To prevent the BG image from getting cut off at the top, make sure
// its position never exceeds the maximum distance from the top of the DIV.
if (bgBottomPos > maxYPos)
{
bgBottomPos = maxYPos;
}
// Subtract the top position from the bottom, and you have the spread
// the BG will travel.
var totalYSpan = bgBottomPos - bgTopPos;
// Get the scrollbar position as a "percentage". Note I simply left it as a
// value between 0 and 1 instead of converting to a "true" percentage between
// 0 and 100, 'cause we don't need that in this situation.
var scrollPercent = ($(window).scrollTop() / ( $(document).height() - $(window).height()));
// The percentage of spread is added to the top position, and voila!
// You have your Y position for the BG image.
var bgYPos = bgTopPos + (Math.round(totalYSpan * scrollPercent));
// Apply it to the DIV.
document.getElementById('outerDIV').style.backgroundPosition="0px " + bgYPos + "px";
}
// Place the BG image correctly when opening the page.
$(document).ready(function() {
moveBG();
});
// Make it update when the scrollbar moves.
$(window).scroll(function () {
moveBG();
});
My goal is to make a fixed div appear at the top of a page once someone scrolls a certain amount of pixels down the page. Basically once the header section is out of view, this div will appear.
I've looked at code similar to what I want; however, haven't seen anything that would allow me to easily modify the pixel count from the top of the page (if possible).
Here is a piece of code I saw dealing with making divs appear by scrolling.
// Get the headers position from the top of the page, plus its own height
var startY = $('header').position().top + $('header').outerHeight();
$(window).scroll(function(){
checkY();
});
function checkY(){
if( $(window).scrollTop() > startY ){
$('.fixedDiv').slideDown();
}else{
$('.fixedDiv').slideUp();
}
}
// Do this on load just in case the user starts half way down the page
checkY();
I just want to know how to make it appear. If someone knows of a piece of code already in tact with a slide up and slide down animation, that would be greatly appreciated as well but not required.
window.addEventListener("scroll",function() {
if(window.scrollY > 500) {
$('.fixedDiv').slideDown();
}
else {
$('.fixedDiv').slideUp();
}
},false);
Brandon Tilley answered my question in a comment...
You would change the first line, with the startY, to be the specific Y
position you need, rather than calculating based on the header's
position and height. Here's an updated fiddle:
jsfiddle.net/BinaryMuse/Ehney/1
window.addEventListener("scroll",function() {
$('.fixedDiv')[(window.scrollY > 500)?"slideDown":"slideUp"]();
},false);
DEMO: http://jsfiddle.net/DerekL/8eG2A/
I do not know how to solve this situation:
I`ve got the html/css looks like this:
Image showing how my css/html looks like and what is displayed on the screen after landing on page:
The when I scroll down I see green element:
scrolling down ->
After continuing to scrolling down I saw full green element and the if I scroll down I want to have this element like in css language: position fixed bottom 0. See image below:
I ve saw full element -> same link but image called problem3.png
and then I scroll below and I want to have it fixed at the bottom of the page, like on this image:
Fixed element on screen - What I want and I do not know how to do that -> same link but image called problem4.png (stupid spam prevention mechanism)
Is it possible to solve this situation ?
To sum up: I`ve got two divs, one above and second below, Wheen I scroll down I suddenly see another element (green div) and when i continue to scroll down I WANT TO HAVE THIS GREEN DIV FIXED AT THE BOTTOM OF THE PAGE.
Ofcourse, when I scroll up (back on the top) I want to "park" that green div at the top of the second div.
Is there any way to solve this situation with jQuery (Javascript) / html / css ?
Thank you in advance
I think you'll have to show some of your html structure. There are lots of ways to achieve this kind of effect. Fundamentally, in javascript terms you'll be looking to:
Add an event listener to the window scroll that checks whether the green element is fully in view
If it is in view, add a class (or change it's css) that fixes it's position where you want
Change your window scroll method so that it's checking the relative offset of the red div to the top of the screen. If it goes below the position where the green div should be fixed, remove the class you added earlier.
That sounds complicated, but it's not too bad. The javascript would be something like:
$(function() {
$(window).scroll(function() {
if($(".divToFix").hasClass("fixedAtBase")){
if(Utils.underView($(".redDiv"), $(".divToFix").height())) $(".divToFix").removeClass("fixedAtBase");
} else {
if(Utils.inView($(".divToFix"))) $(".divToFix").addClass("fixedAtBase");
}
});
});
Utils = {
underView: function(element, offset) {
return (($(window).height() + $(window).scrollTop() - offset) <= element.offset().top);
},
aboveView: function(element) {
return ($(window).scrollTop() >= element.offset().top + element.height());
},
inView: function(element) {
return (Utils.aboveView(element) !== true && Utils.underView(element, element.height()) !== true);
}
};
Bear in mind I've not tested that or anything.
edit - here's a demo