I have a overlay with empty height and width that covers the whole page once its clicked using a button, this overlay transition from top 0 left 0 all the way down to bottom right. once this over lay is closed I edited the css property using java script so that it transition finished on the bottom right.
The first time opening and close this overlay, it works fine, however the second time I open it, instead of starting from top left, it starts from bottom right and moves all the way to top left. I cant seem to fix this problem. I try resetting the left to 0 and top to 0 but it doesnt work.
document.querySelectorAll(".overlay_background")[0].addEventListener("click", parent);
function parent(event) {
this.style.left = this.clientWidth + "px";
this.style.top = this.clientHeight + "px";
this.style.height = 0;
this.style.width = 0;
}
function child(event) {
event.stopPropagation();
}
function http_request_availability() {
document.getElementById("overlay_background_id").style.left = "0";
document.getElementById("overlay_background_id").style.top = "0";
console.log(document.getElementById("overlay_background_id"));
document.getElementById("overlay_background_id").style.height = "100vh";
document.getElementById("overlay_background_id").style.width = "100vw";
document.getElementById("overlay_background_id").style.backgroundColor = "rgba(0,0,0, 0.5)";
document.body.style.overflow = "hidden";
}
.overlay_background {
position: fixed;
overflow: hidden;
height: 0;
width: 0;
left: 0;
top: 0;
transition: 0.7s ease;
z-index: 1;
}
<div class="overlay_background" id="overlay_background_id">
Hi this is my overlay
</div>
<button class='btn_ws' onclick='http_request_availability();'>Book Work-Shop</button></div>
The problem is your overlay never resets to its original position of top 0 and left 0.
Try adding this to the end of your parent() function:
var self = this;
setTimeout(function() {
self.style.left = 0;
self.style.top = 0;
}, 700);
This will reset the left and top positions to 0 after 700 ms has passed (the duration of the transition).
Related
I'm building a Shopify site, and want an overlay image to cover the top content when you land on the website. Then when you scroll, this overlay image moves up and off the screen revealing the website.
I found some javascript that does this, but the main website scrolls with the overlay image. Is there a way to have it scroll on its own and not scroll the content behind?
Here's what I have so far:
var container = document.getElementById('overlay-container');
var windowHeight = window.innerHeight;
var windowWidth = window.innerWidth;
var scrollArea = 1000 - windowHeight;
var square1 = document.getElementsByClassName('overlay-background-image')[0];
// var square2 = document.getElementsByClassName('overlay-logo')[1];
// update position of square 1 and square 2 when scroll event fires.
window.addEventListener('scroll', function() {
var scrollTop = window.pageYOffset || window.scrollTop;
var scrollPercent = scrollTop / scrollArea || 0;
square1.style.bottom = -100 * (1 - scrollPercent * 1.5) + 'vh';
// square2.style.top = 800 - scrollPercent*window.innerHeight*0.6 + 'px';
});
// Global variable to control the scrolling behavior
const step = 30; // For each 30px, change an image
function trackScrollPosition() {
const y = window.scrollY;
const label = Math.min(Math.floor(y / 30) + 1, 20);
const imageToUse = fruitImages[label];
// Change the background image
$('.image-container').css('background-image', `url('${imageToUse}')`);
}
$(document).ready(() => {
$(window).scroll(() => {
trackScrollPosition();
})
})
.overlay-container {
position: relative;
max-width: 100%;
}
.overlay-background-image {
position: absolute;
z-index: 5;
left: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<div class="overlay-container">
<div class="overlay-background-image">
<img style="height: 100vh;" src="https://cdn.shopify.com/s/files/1/0608/2225/7886/files/01_-_Landing_Page.png?v=1636020266" />
</div>
</div>
Edit:
I misread the question.
Original answer:
This will automatically scroll the image offscreen once the page is loaded. (Not what the question wanted)
I'd recommend using css rather than JavaScript for this.
body {
margin: 0px;
}
.overlay-background-image {
animation-fill-mode: forwards;
animation-name: shop_reveal;
animation-duration: 3s;
position: absolute;
width: 100vw;
background-size: calc(100vh * 1440/767);
height: 100vh;
background-image: url('https://cdn.shopify.com/s/files/1/0608/2225/7886/files/01_-_Landing_Page.png?v=1636020266');
}
#keyframes shop_reveal {
from {
bottom: 0px
}
to {
bottom: 100vh
}
}
<div class="overlay-container">
<div class="overlay-background-image">
</div>
</div>
Edited answer:
This will scroll the image along with the scrollbar.
<div class="overlay-container">
<div class="overlay-background-image">
</div>
</div>```
<!-- end snippet -->
pagebox is the content that will be revealed when the user scrolls the page.
<!-- language: lang-css -->
```#pagebox {
position: absolute;
}```
<!-- end snippet -->
Give pagebox absolute positioning so that it's position can be set in JavaScript and it doesn't push the image.
<!-- language: lang-javascript -->
```var container = document.getElementById('overlay-container');
var windowHeight = window.innerHeight;
var windowWidth = window.innerWidth;
var scrollArea = 1000 - windowHeight;
var square1 = document.getElementsByClassName('overlay-background-image')[0];
// var square2 = document.getElementsByClassName('overlay-logo')[1];
var p = document.getElementById("pagebox");
// update position of square 1 and square 2 when scroll event fires.
window.addEventListener('scroll', function() {
var scrollTop = window.pageYOffset || window.scrollTop;
var scrollPercent = scrollTop / scrollArea || 0;
square1.style.bottom = p.style.marginTop = -100 * (1 - scrollPercent * 1.5) + 'vh';
// square2.style.top = 800 - scrollPercent*window.innerHeight*0.6 + 'px';
});```
<!-- end snippet -->
As the page is scrolled. The image overlay is moved up by this code. However the normal functioning of the scrolling is still in effect so the rest of the page moves up with it. In order to counteract this. The position of the content underneath the image is moved down by the amount the page is scrolled.
(simply using position:sticky would prevent the content underneath the page from exceeding the height of the window so can't be used)
I've changed the cursor to a small circle and it works ok on the front page, where the height of body is 100vh. On the portfolio page, where there are more photos etc. the small circle comes until 100vh and then stops there. What would make it stop there? Any idea? When I start scrolling, it goes up and away from the actual cursor.
Thanks a lot in advance. The code is below.
.cursor__point {
position: absolute;
transform: translate(-50%,-60%);
z-index: 3;
pointer-events: none;
z-index: 1000;
}
window.addEventListener("mousemove", (event) => {
cursor.style.top = event.pageY + "px";
cursor.style.left = event.pageX + "px";
});
I am building this site as a fun little side project but I am stuck. My sticky nav bar jumps once the user scrolls far enough down. I have read other threads and can't quite connect the dots.
I have been thinking it must be a padding issue, however, my JS isn't all that great so there is potential for problems there as well.
Here is my Javascript:
var header = document.getElementById("header");
var navbar = document.getElementById("navbar");
var navbarHeight = navbar.offsetHeight;
var headerHeight = header.offsetHeight;
header.style.height = screen.height - navbarHeight;
function initJake() {
if (window.pageYOffset > headerHeight) {
navbar.style.position = "fixed";
navbar.style.top = "0";
} else {
navbar.style.position = "relative";
}
}
window.onscroll = function() {
initJake()
};
Here is my jsFiddle (the links are cut off since this is the full-screen HTML setup): https://jsfiddle.net/jihlenfeldt/435ugdyf/2/
I am hoping to find a way in which the transition from absolute to fixed is smooth and doesn't end up covering a bunch of lines of text.
Thank you to anyone willing to offer a bit of advice, this little issue has become quite a headache.
Is this what you mean?:
var header = document.getElementById("header");
var navbar = document.getElementById("navbar");
var content = document.querySelector('#navbar + .content');
var navbarHeight = navbar.offsetHeight;
var headerHeight = header.offsetHeight;
header.style.height = screen.height-navbarHeight;
function initJake(){
if(window.pageYOffset > headerHeight){
navbar.style.position = "fixed";
navbar.style.top = "0";
content.style.padding = '60px 0 0 0';
}
else{
navbar.style.position = "relative";
content.style.padding = '0 0 0 0';
}
}
function hamburgerMenu() {
var x = document.getElementById("submenu");
if (x.style.display == "none") {
x.style.display = "block";
} else {
x.style.display = "none";
}
}
window.onscroll = function() {initJake()};
The issue here is that your navbar gets position "fixed" and its height is not considered by the DOM anymore since it'll be positioned "on top" of everything. Best way to fix this is to give the element after it (the content in this case) a padding-top of the same height that navbar has. (Unlike me, use a variable that gets the height of the navbar since its height can vary, not a fixed number like I did (the 60px))
Well here's your mistake.
if (window.pageYOffset > headerHeight) {
navbar.style.position = "fixed";
navbar.style.top = "0";
} else {
navbar.style.position = "relative"; // here
}
Your navbar has position absolute and when window.pageYOffset > headerHeight is false, you are making it relative
#navbar {
position: absolute;
bottom: 0;
width: 100%;
background-color: #111;
z-index: 3;
overflow: hidden;
height: 20%;
padding-bottom: 3%;
display: flex;
flex-direction: column;
transition-property: width;
}
That's why the bump. Also, the navbar is fixed now, so It doesn't disturbs other elements. That's why the this div is covered by the navbar (or is going upwards)
<div class="content">
<h1>text here</h1>
<p>text here text here text here text here text here text here text here text here text here text here text here text here </p>
</div>
Possible fix is we stick to one position. Let's make it relative. Then we add margin top to the content div when the position is fixed. Which makes it some distance from above. So javascript becomes becomes
var content = document.getElementsByClassName("content")[0];
if (window.pageYOffset > headerHeight) {
navbar.style.position = "fixed";
navbar.style.top = "0";
content.style.marginTop = " 115px";
} else {
navbar.style.position = "relative";
content.style.marginTop = "0px";
}
And stick to relative in css
#navbar {
position: relative;
...
}
So your fiddle becomes something like this
Why do you guys use always JS to interact with the appearance of a HTML object.
Use JS to check if the header is outside of the viewport and if yes, set a class on the body. Via CSS you can modify the sticky header.
Something like this:
$(window).scroll(function(){
if($(this).scrollTop() > $('#header').outerHeight()){
$('body').addClass('scrolled');
} else {
$('body').removeClass('scrolled');
}
});
And via CSS
#header { position:relative; }
body.scrolled #header { position:fixed; top:0; left:0; width:100%; }
body.scrolled { padding-top:<Enter here Height of Header to prevent jumping> }
I have created a magnifier in pure js. What I discovered in needing to translate the mouse position of a div relative to its parents is that in calculating the top for the overlaying magnifier div, the offsetTop works differently than the offsetLeft. After adjusting for what should be the top, I need to subtract the whole container div's offsetHeight.
The line in the code in question is this:
magnifier.style.top = yPosition - container.offsetHeight + "px";
Why do I need to subtract container.offsetHeight?
I know I've read something regarding this, but can't find it.
Disclaimers This code is working. I am asking so I (and those following) can understand how the box model works.
I know there are jQuery alternatives that are more cross browser reliable. I like to code it myself so that I can learn how it all works. If you see something which is not compatible for a modern browser, feel free to comment.
Lastly, For anyone using this, I removed code from this example to adjust for transforms. For example, if the wrapper has a transform: translate(-50%, 0); to center the wrapper horizontally, you will need to add the resulting amount of the translation (which translates to the wrapper's left position) back into the calculation.
I have created a jsfiddle here. I left more comments in the Fiddle as to methodology if anyone is interested.
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="../css/ms.js"></script>
<style type="text/css">
/********************/
body {
background-color: #FFF;
margin-left: 30px;
margin-top: 10px;
}
.wrapper {
position: absolute;
left: 100px;
}
#container {
width: 527px;
height: 450px;
border: 5px black solid;
overflow: hidden;
background-color: #F2F2F2;
cursor: pointer;
}
#image {
width: 527px;
height: 450px;
}
#magnifier {
width: 250px;
height: 250px;
overflow:hidden;
position:relative;
z-index: 1000;
border: solid 1px;
}
#magnifier img {
position: absolute;
}
</style>
</head>
<body>
<div class="wrapper" id="wrapper">
<div id="container">
<img id="image" src="../docs/grade-2/jpg/g2-bb-saints-francis.jpg">
<div id="magnifier" class="magnifier">
<img id="imagecopy">
</div>
<br>
</div>
<input type="button" value="Zoom" onClick="initmagnifier('magnifier', 'image', 'imagecopy');"><br>
</div>
<script>
function initmagnifier(magnifier, image, imagecopy){
var magnifier = document.getElementById("magnifier");
var container = document.getElementById("container");
var wrapper = document.getElementById("wrapper");
var img = document.getElementById(image);
var imgcopy = document.getElementById(imagecopy);
var zoom = 2;
container.addEventListener("mousemove",
function(e){
movemagnifier(e, img, imgcopy, magnifier, container, wrapper, zoom)
}, false);
var src = img.src;
imgcopy.src = src;
var src2 = imgcopy.src;
imgcopy.height = img.height * zoom;
imgcopy.width = img.width * zoom ;
}
function movemagnifier(e, img, imgcopy, magnifier, container, wrapper, zoom) {
// to get the left & top of the magnifier
// position needs to be adjusted for WRAPPER & CONTAINER top and left
// gets the top and left of the container
var containerPosition = getPosition(e.currentTarget);
// adjust out the CONTAINER's top / left
// Then takes 1/2 the hight of the MAGNIFIER and subtracts it from the MOUSE position to center MAGNIFIER around the MOUSE cursor
var xPosition = e.clientX - containerPosition.x - (magnifier.clientWidth / 2);
var yPosition = e.clientY - containerPosition.y - (magnifier.clientHeight / 2);
magnifier.style.left = xPosition + "px";
magnifier.style.top = yPosition - container.offsetHeight + "px";
// Adjust for zoom
// adjust the MAGNIFIER's top/left at an equal pace to the zoom amount
var yTravel = (e.clientY - containerPosition.y ) * (zoom - 1);
var yimgPosition = -(yPosition - container.clientTop + yTravel);
imgcopy.style.top = yimgPosition + "px";
var xTravel = (e.clientX - containerPosition.x) * (zoom - 1); // * 1.5
var ximgPosition = -(xPosition + xTravel);
imgcopy.style.left = ximgPosition + "px";
console.log('****');
console.log(e.clientY); // MOUSE POSTION
console.log(containerPosition.y);
console.log(wrapper.offsetTop);
console.log(wrapper.clientHeight);
console.log(container.offsetTop);
console.log(container.clientHeight);
console.log(yPosition);
console.log(container.offsetHeight);
console.log(magnifier.style.top);
}
function getPosition(element) {
var xPosition = 0;
var yPosition = 0;
// element is the CONTAINER
// This calculates the postion of the element (CONTAINER) TOP & LEFT relative to ALL parents
while (element) {
// if transform: translate in place for x and y,
// add it back as it skews the offsetLeft offsetTop values by the translate amount
xPosition += ((element.offsetLeft) - element.scrollLeft);
yPosition += ((element.offsetTop) - element.scrollTop);
element = element.offsetParent;
}
return { x: xPosition, y: yPosition };
}
</script>
</body>
</html>
It took me longer than I care to admit, but I have found the reason. In your fiddle you position the #magnifier-element relative, which means you have to move it from its 'natural' position, which is below the image inside the container.
So with every move you have to compensate for this, by pulling the #magnifier to the top/left position of the container, the left position already matches, but the 'natural' top position of the #magnifier is the full height of the container, as you calculate from the top/left position of the #container, you need to subtract the #container height.
A simple fix is to add position: relative to the #container and change position: relative on the #magnifier to position: absolute.
This will give you the expected coordinate system for the #magnifier as top: 0; left: 0 for the absolute positioned element is the top left corner of the its relative parent (the first positioned parent element, in this case #container).
a working example without the need to to subtract container.offsetHeight.
While I'm at it, you may want to look into the Element.getBoundingClientRect function, as you can get all information you need to determine the position in a single call.
I have a Javascript function which is used to shake the screen for about a second.
function shakeScreen() {
var degrees = 0;
var goal = 0;
var goals = [5,-5,4,-4,3,-4,2,-2,1,-1,0];
function frame() {
if(goals[goal] < 0) {
degrees -= 1;
} else {
degrees += 1;
}
get('body','tag');
current[0].style.transform = 'rotate(' + degrees + 'deg)';
if(degrees === goals[goal]) {
goal += 1;
if(goal === goals.length) {
clearInterval(intervalId);
}
}
}
var intervalId = setInterval(frame,16);
}
Inside my HTML body, my first element has a fixed position. This element is a pop-up that displays messagers to users, and it has a fixed position so it appears in the same position on the screen if the end user has scrolled down or up the page. Here is a snippet of the HTML:
<body>
<div id='fade' onclick="fade('out')"><div id='alert'></div></div>
<!-- more unrelated content -->
Here is the CSS for the specified element above:
#fade {
z-index: 2750;
position: fixed; /*important*/
display: none;
width: 100%;
height: 100%;
margin: 0;
padding: 0;
background-color: rgba(0, 0, 0, 0);
text-align: center;
}
#fade:hover {
cursor: pointer;
}
When the Javascript function shakeScreen() is executed, the fade element gets misaligned and moves to the top of the body rather than remaining in the center of the end user's screen. Here is the JSFiddle: https://jsfiddle.net/turkey3/ug9zx1d2/3/ Scroll down halfway and you'll see a button. Click that button to shake the screen. You'll notice a split second where the fade element starts appearing at the center of the screen, but then it moves to the top after it starts shaking. Also, to see how I want it to be, comment out the shakeScreen function that's inside the setup function and then run the code.
Edit: The fade element is simply a dark background. The alert element is a white box with the message that shows to the user.
Solution
I found out the best method was, rather than rotating the body element, was to wrap all the other code insider a div and shake the division rather than the entire body. After that, the alert message properly showed in the center of the screen. Here is the fixed code: https://jsfiddle.net/turkey3/ug9zx1d2/4/
Here is the HTML wrapped in the div:
<body>
<div id='fade' onclick="fade('out')"><div id='alert'></div></div>
<div id='shake'>
<!-- more unrelated content -->
</div>
And updated JS:
function shakeScreen() {
var degrees = 0;
var goal = 0;
var goals = [5,-5,4,-4,3,-4,2,-2,1,-1,0];
function frame() {
if(goals[goal] < 0) {
degrees -= 1;
} else {
degrees += 1;
}
get('shake','id');
current.style.transform = 'rotate(' + degrees + 'deg)';
if(degrees === goals[goal]) {
goal += 1;
if(goal === goals.length) {
clearInterval(intervalId);
}
}
}
var intervalId = setInterval(frame,16);
}