I am building a template where there are large navigation buttons at the very top that, when clicked, make a corresponding page (an absolutely positioned DIV) slide out from underneath the button and fill the whole page via CSS transitions.
I have a series of commands in a window resize function that keep everything in place/the right size if the window changes size. It is all working fine, except for a small issue where when the page is "out", if the browser window gets resized vertically, the CSS height transition triggers as opposed to the DIV snapping to the new height instantly (the DIV is 100% width and a dynamically calculated height the makes it fill the screen below the navigation buttons exactly). My solution to that was to add a line of code that would change the transition property to not include height BEFORE updating the height, then change it back immediately after. It seems to do nothing at all though. My code:
window.addEventListener('resize', function(event){
bottomLoc = findBottom.getBoundingClientRect();
if (pageOut1 == false) {
pageLoc1 = pageButton1.getBoundingClientRect(); //redefine location variable
document.getElementById("page1").style.top = pageLoc1.top + 70 + "px"; //update closed page position
document.getElementById("page1").style.left = pageLoc1.left + "px"; //update closed page position
} else if (pageOut1 == true) {
document.getElementById("page1").style.transition = "width 0.5s, left 0.5s"; //turn off height transition
document.getElementById("page1").style.height = bottomLoc.bottom - 70 + "px"; //update height
document.getElementById("page1").style.transition = "height 0.5s, width 0.5s, left 0.5s"; //turn height transition back on
}
});
The part that doesn't seem to be working is in the "else if" statement. Even though I take out the "height 0.5s" before the height update happens, it still does the transition. This is not exactly a huge, website breaking problem, but it does cause a scroll bar to randomly appear and disappear when resized smaller, which looks bad.
Hopefully someone can help me understand why this is not working, as this would help with a lot of other templates I have that require dynamic repositioning of absolutely positioned elements. Thanks!
Related
I have explored few approaches to this, but none really seems to work exactly like I would like:
I would like that when scrolling down, navbar is moving up at the speed the user is scrolling down, like that is static at that point.
When it disappears, I would like that the bottom of it is still visible, because this is where I have a progress bar (but maybe progress bar should detach at that point and be on top of the viewport).
When you scroll up, I would like that navbar appears again, again at the speed of scrolling, like it is static, until you see the whole navbar, when it should stick to the top of the viewport.
Here is an example of behavior I would like, but not performance/experience (because behavior is implemented using scroll event, it is not smooth).
I have also attempted to use CSS transform, which would on scroll down add a class to hide the navbar, and scroll up remove the class, animating the navbar hiding/showing, but the issue with that is that animation speed is disconnected with scrolling speed.
I tried CSS sticky position as well, but it looks like I need the opposite of what it provides.
Is there some other way to make this work well?
I've looked at your problem and I think i found a simple approach.
with this simple function you can get the amount of pixels user has scrolled.
window.onscroll = function (e) {
console.log(window.scrollY); // Value of scroll Y in px
};
after user scrolls the desired amount of pixels, make the progress bar fixed top ( or position:fixed;top:0)
Checking the link you provided, it seems to work as expected (you want it to be linked to the scroll event since you want it to move as "static"). If, though, it staggers on some system due to inconsistent scroll events, you could try adding a transition property with a small enough duration. Keep in mind the this should only be enabled while the position property remains the same, otherwise when changing from "absolute" to "fixed" it would mess things up, since the coordinate origin changes.
So you can add another variable let changedPosition = false; and whenever you change the position property you can do
if (position !== "absolute") {
changedPosition = true;
} else {
changedPosition = false;
}
position = "absolute";
or
if (position !== "fixed") {
changedPosition = true;
} else {
changedPosition = false;
}
position = "fixed";
and when you apply the style do
navbar.style = `position: ${position}; top: ${navbarTop}px; transitiona: ${
changedPosition ? "none" : "100ms linear"
}`;
like https://codepen.io/gpetrioli/pen/XWVKxNG?editors=0010
You should play around a bit with the transition properties you provide, i just put some sample values there.
I'm creating an Chrome Extension, which should add sidebar to all webpages.
This sidebar shouldn't overlap webpage content, it should be placed next to the existing content, essentially shrinking width of body of webpage to initial width - sidebar width.
This is the code I came up with, but I have a problem with some pages like stackoverflow for instance, see how top bar doesn't shrink like the rest of the page does (screenshots attached below the code)
// create sidebar
const sidebar = document.createElement("iframe");
sidebar.src = chrome.extension.getURL("iframe/iframe.html");
sidebar.id = "extensionSidebar";
sidebar.frameBorder = "0";
sidebar.style.height = "100%";
sidebar.style.width = "100px";
sidebar.style.position = "fixed";
sidebar.style.top = "0";
sidebar.style.right = "0";
sidebar.style.zIndex = "2147483646";
// append sidebar to body
document.documentElement.appendChild(sidebar);
// shrink body
document.body.style.width = window.innerWidth - 100 + "px";
Screenshots:
https://prnt.sc/o215x5
https://prnt.sc/o21637
The top bar doesn't shrink as you would like it to do because it is fixed, it will always take 100% of the viewport width. Its CSS properties on your example with stackoverflow are :
...
position: fixed;
top: 0;
left: 0;
width: 100%; /*though it's not "really" 100vw*/
...
Even by changing the html element in CSS, in order to change its maximum size to 80% of the viewport width for instance, the navbar would still take all the viewport's width.
To understand it you can try the following fiddle, it might speak for istelf : https://jsfiddle.net/bcg2vkjm/4/
On it you can "un-comment" the body element inside the CSS and see the result, it might give you some help ! Though it only applies a scale of 1 (so it should not change...), for some reason it makes the fixed element adapt to the body size, which is what you want, you just might have to play along with the translateX and/or scale in the CSS, but it might be a risky solution because it changes quite a lot the way everything is displayed, not only the fixed element, as you can see.
In your javascript you can try the following :
document.querySelector('body').style.transform = "scaleX(something)";
for instance !
I am trying to build an animated sidebar that slides in and out when you click the button. This was quite easy to achieve however I ran in to a problem when making the sidebar 'more' responsive. Basically, I wanted the sidebar to be 200px wide when the width is less than 500 and 300px wide otherwise. This was done in a media query. The problem I've run into is that when you resize the window the sidebar goes out of position if you have already run the function before resizing.
This problem can occur for example if a user rotates their mobile screen whilst using the sidebar and so I feel it's best to try and fix it.
Here is the jQuery:
function sidebar(){
var menuWidth = $('#menu').width();
if($('#menu-link').hasClass('hidden')){
$('#menu-link').removeClass('hidden');
$('.push').animate({right: "-=" + menuWidth});
}else{
$('#menu-link').addClass('hidden');
$('.push').animate({right: "+=" + menuWidth});
}
};
$('body').on('click', '#menu-link', sidebar);
The sidebar changes to 200px <500 and is otherwise 300px. What is the best way to code this or is it better to keep it simple by just always making the sidebar 200px even though it's not as aesthetically pleasing at larger resolutions.
Here is a link to a JSFiddle of my code
https://jsfiddle.net/fqcydqu7/
Edit: Sorry, to explain the actual problem clearly - Before you resize, this code runs fine and is perfect. However, if you run this code (ie. open and close the sidebar) and then resize the window so the media query is active you will see that the sidebar is out of position by 100px. The opposite will happen if you reverse the order.
Okay guys I came up with a solution for my problem.
Basically, I remove the media query from CSS and set the div to always be 300px.
The jquery uses a variable that is updated whenever the window is resized to judge how much to slide the menu. (200px or 300px).
here is the code:
// variable is set to 0 by default
var menuWidth = 0;
//call to function that will set this variable
setWidth();
function setWidth(){
if(windowSize <= 800){ //if its less than 800px wide, set the variable to 200px (the menu is still 300px)
menuWidth = "200px";
}else{
menuWidth = "300px"; //otherwise set the variable to 300px
}
}
$(window).resize(function(){ //when a user resizes the window, run the setWidth function to readjust the variable
setWidth(); //this re-runs setWidth
//the following closes the menu if it's already open to avoid glitches
if($('#menu-link').hasClass('hidden')){
$('#menu-link').removeClass('hidden');
$('.push').animate({right: "-=" + menuWidth});
}
});
//nav slide
function sidebar(){
if($('#menu-link').hasClass('showing')){ //checks to see if the nav is showing or not
$('#menu-link').removeClass('showing'); //remove the showing tag
$('.push').animate({right: "-=" + menuWidth}); //closes the nav
}else{ //if the nav doesnt have showing tag it must be hidden
$('#menu-link').addClass('showing'); //add the showing tag
$('.push').animate({right: "+=" + menuWidth}); //open the nav
}
};
With this code, the menu will only slide out by 200px when the window is less than 800px wide and 300px if it's wider. The div will always be in the correct position even if the user rotates the mobile or changes the window width.
I can't find a solution to this, there was a question over here, but the answers are not very usable (at least for me).
I have a JavaScript modal pop-up that disables everything on the background by placing transparent div over the page. It also disables the scrolling by setting the overflow to hidden, and must do so, because the page is scrollable with the mouse wheel otherwise and distracts the user.
The problem is, when hiding and showing the scrollbar the page resizes and the effect is ugly. Also, my page is designed in such a way that if I stop it from resizing that would be ugly either.
What I want is to disable the scrollbar, but keep it visible (the page content is longer than the screen fits). Is this somehow possible in CSS?
Instead of changing the css, which will remove the scrollbar, and as you said change the layout of the page, try calling a jquery function instead.
// call your pop up and inside that function add below
$('body').on('scroll mousewheel touchmove', function(e) {
e.preventDefault();
e.stopPropagation();
return false;
});
then when you close the modal, call the same function but replace on with off
Since scrollbars are not all 17px wide, I solved this with JavaScript. That is, I calculated the exact width of the scrollbar and added an equal amount of margin to the right of the body element. This also works when the scrollbar isn't present due to a high resolution or a lack of content.
function toggleMenu() {
// get width before hiding scrollbar
let oldWidth = document.documentElement.clientWidth;
// toggle CSS class that sets overflow to hidden
document.body.classList.toggle('MenuOpen');
// get new width after hiding scrollbar
let newWidth = document.documentElement.clientWidth;
// set margin-right value equal to width of the scrollbar
let scrollbarWidth = Math.max(0, newWidth - oldWidth);
document.body.style.marginRight = `${scrollbarWidth}px`;
}
...and my CSS looks like:
html {
background-color: #e6e6e6; /* color of fake scrollbar */
}
body.MenuOpen {
overflow: hidden;
}
Once you start showing your popup, give the body a class (like popupOpen). This should be an easy workaround.
.popupOpen {
overflow: hidden;
margin-right: 17px //size of the scrollbar in each browser
}
When you close your popup, simply remove the class from the body.
I have a website that uses a parallax background, the background is 1200px long.
The issue is:
I have a page with indefinite height, the page get expanded dynamically to its content. So if a user press read more it expands without refresh, which ruin the parallax effect because the background reaches its end before the page finish.
The background is complex design image, it cannot be repeated and adding background-color to cover up the white space cant be done, but I wish I can keep the cool parallax effect!
My question:
Is it possible to make the parallax stop when it reaches a specific y-position, and freezes the background when scrolling beyond the specific y position? But also to be able to trigger on the parallax effect when scrolling back to the specific y-position and above?
If we assume background is moving at 0.1 speed, then the max height will be 1200/0.1 = 12000px.
If page reaches y-position = 12000px -> stop parallax effect and freeze image as is -> and if page return back to 1199px start parallax again
How to do this in Javascript? If possible in CSS would be great too.
Edit:
here is what I did before posting on Stackoverflow:
I used Stellar.js for the parallax effect, simply i added the following javascript:
$(window).stellar({responsive:false});
and added the following code to the tag (which hold the background-image):
<body data-stellar-background-ratio="0.1">
I also tried another approach, by using a custom JavaScript I found in the web:
$( window ).scroll( function(){
var ypos = $( window ).scrollTop(); //pixels the site is scrolled down
var visible = $( window ).height(); //visible pixels
const img_height = 1261; //image height
var max_scroll = img_height - visible; //number of pixels of the image not visible at bottom
//change position of background-image as long as there is something not visible at the bottom
if ( max_scroll > ypos) {
$('body').css('background-position', "center -" + ypos + "px");
} else {
$('body').css('background-position', "center -" + max_scroll + "px");
}
});
in this case, it do scroll until the end of the background, But I can't figure out how to slow down the scroll speed of the background.