Resizing rectangle transition on scroll gets cut off - javascript

I'm trying to resize a rectangle on scroll, when the user scrolls down, the rectangle shrinks and when they scroll up the rectangle goes back to its original size. However, I've encountered a problem where if the user scrolls too fast, the rectangle doesn't have enough time to adjust its height before the user reaches the top/bottom of the page (thus not allowing the onScroll function to change the rectangle's height). No transition time is added for the resizing of the rectangle.
I'm assuming this is because the height of the rectangle is taken from the height of the div containing some text. The text also resizes on the scroll and there's a transition time of 0.4 seconds, which may be delaying the rectangle.
Is there a way to continue to allow the rectangle to resize itself, even after the user stops scrolling? Help would be greatly appreciated!
Here's the skeleton of my code:
window.onscroll = function() {scrollFunction()};
var width = window.innerWidth;
// shrink and grow are functions that change the font size of text
function scrollFunction() {
document.getElementById("rect").style.height = document.getElementById("menu").offsetHeight + (width / 100) + "px";
if (document.body.scrollTop > 80 || document.documentElement.scrollTop > 80) {
document.getElementById("title").style.fontSize = shrink("title");
document.getElementById("here").style.fontSize = shrink("here");
} else {
document.getElementById("title").style.fontSize = grow("title");
document.getElementById("here").style.fontSize = grow("here");
}
}
#rect {
width: 100%;
position: relative;
height: clamp(40px, 10vw, 130px);
background: white;
}
#background {
height: 200vh;
}
#title {
transition: 0.4s;
}
<div id="background">
<div id="rect" style="border: 2px solid green">
<div id="menu">
<div id="title">title</div>
<div id="here">here</div>
</div>
</div>
</div>

use transform: scale(/* Your shrink size goes here, say 0.3 */) for your rectangle.

Related

How to have an element change its color during a scroll event and then revert back to its original color?

I am trying to make the footer of a website im creating change color DURING scrolling and revert back to its original color after the scroll is done.
Is there any way to detect when a scroll event ends?
I am looking for answers in vanilla js. Or if there are any specific recoomendation available in for example jQuery im more than willing to look into it per your kind suggestion.
So you're probably looking for scroll event handeler here
And to check if you're done scrolling to the bottom, you need to check if the scroll height is left or not? This might help with that!
Using code I got from detecting when a visitor has stopped scrolling I derived this:
// Setup isScrolling variable
var isScrolling;
// Listen for scroll events
window.addEventListener('scroll', function ( event ) {
// Clear our timeout throughout the scroll
window.clearTimeout( isScrolling );
// Set a timeout to run after scrolling ends
isScrolling = setTimeout(function() {
// Run the callback
if(document.querySelector('#mydiv').style.background=='red')
document.querySelector('#mydiv').style.background='blue';
else if(document.querySelector('#mydiv').style.background=='blue')
document.querySelector('#mydiv').style.background='yellow'
else
document.querySelector('#mydiv').style.background='red'
}, 66);
}, false);
div{
width:100%;
height:400vh;
}
<body>
<h1>scroll down this(document should change colour when you stop:</h1>
<div id="mydiv"></div>
</body>
You just set a timeout to wait until the user is done scrolling. If the user continues to scroll the timeout is cleared and reset before it activates(meaning the code won't run until he stops).
You can get the window height and the height of your footer element and check the scroll pageYOffset in relation to the window height => window.innerHeight and the footers top position in relation to the viewport => footer.getBoundingClientRect().top.
Use a set of conditionals to check the scroll position. Set it anywhere you'd like for the initial color change, I used the initial window.innerHeight to start the BG color change.
For the bg-color change, I use a class and add it to the body with classList.add('bgColor'). Then we further check if the pageYOffset is greater than the window.innerHeight - footer.getBoundingClientRect().top, meaning the footer will just be breaking the bottom fold of the page and coming into view, if this happens we remove the class that adds the bg-color and return the document to its initial bg-color.
const height = 3000;
document.documentElement.style.setProperty("--height", `${height}px`)
const display = document.getElementById('display')
const footer = document.querySelector('.footer')
const rect = footer.getBoundingClientRect()
const screenHeight = window.innerHeight
function setBgOnScroll(e) {
let offset = window.pageYOffset
display.textContent = `scroll offset: ${offset} footer top position: ${rect.top - screenHeight}`
offset > screenHeight ?
document.body.classList.add('bgColor') : document.body.classList.remove('bgColor')
offset > rect.top - screenHeight ?
document.body.classList.remove('bgColor') : null
}
window.addEventListener('scroll',setBgOnScroll)
:root {
--body-bg-color: white;
}
body {
background-color: var(--body-bg-color);
transition: background-color ease-in-out 500ms;
}
.cont {
height: var(--height);
}
#display {
position: fixed;
top: 20px;
right: 220px;
}
.footer {
position: absolute;
top: calc(3000px - 100px);
left: 0;
width: 100%;
background-color: green;
height: 100px;
display: flex;
justify-content: center;
align-items: center;
}
.bgColor {
background-color: lightblue;
transition: background-color ease-in-out 500ms;
}
<div class="cont">
<div id="display"></div>
Page content, scroll down...
<div class="footer">Footer</div>
</div>
While you can react to the scroll event with Javascript you'll need to define some timings to decide when the user has stopped scrolling.
As you can't sense a 'not-scrolling' event this will have to be with something like a setTimeout.
<style>
div {
height: 300vh;
}
footer {
position: fixed;
bottom: 0;
width: 100vw;
height: 20vh;
background-color: magenta;
}
</style>
<body>
<div>scroll down</div>
<footer>Footer</footer>
<script>
let timeout = false;
const footer = document.querySelector('footer');
document.addEventListener('scroll', function () {
if (timeout) {clearTimeout(timeout); timeout = false;}
footer.style.backgroundColor = 'blue';
timeout = setTimeout( function () {
footer.style.backgroundColor = 'red';
}, 1000);
});
</script>
</body>

How to control when a jQuery slideToggle(); which is position:absolute; is higher than viewport?

I have a slideToggle(); menu which is positioned absolutely on the bottom of the page. The slideToggle(); is going to show big content and sometimes this ends up being taller than the viewport.
My question is, how do I prevent the menu to:
1 - Not going on the top of the logo as they are both on the sidebar of my website
2 - When it reaches a height taller than the viewport, this will be scrollable
To explain myself better, I'd like the content of my menu, once is shown by slideToggle(); and whenever is taller than the viewport's height minus logo's height, to stop right below my logo and to continue expanding downwards if that's the case, and that I am able to scroll it down despite its position:absolute.
Does anyone have an idea on how I can achieve that? Please have a look at the snippet.
$( "#click" ).click(function() {
$( ".content" ).slideToggle();
});
.logo {
background: #11a1d6;
margin: 10px;
height: 100px;
width: 300px;
}
.list {
width: 200px;
position: absolute;
bottom: 20px;
}
.content {
background: #082965;
height: 10000px;
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="logo"></div>
<ul class="list">
<li id="click">
Click me
<div class="content"></div>
</li>
</ul>
You would need an additional wrapper for your .content that has overflow-y: hidden and height set to the max height available. To determine this height you need a function that runs after your DOM is loaded and adds this to your .content-wrapper:
function setContentMaxHeight() {
let containerHeight = $('.container').height()
let logoMargin = $('.logo').offset().top;
let logoHeight = $('.logo').height();
let listHeight = $('.list').height();
let listMargin = 20;
let maxHeight = containerHeight - ( 2 * logoMargin ) - logoHeight - ( 2 * listMargin) - listHeight;
$('.content-wrapper').css({
'height': maxHeight + 'px'
});
}
$(document).ready(function(){
setContentMaxHeight();
window.onresize = setContentMaxHeight; // detect the window resize and rerun the function
});
working fiddle

Check Whether a DIV Reaches it End on Window Scroll in Javascript

I have a div of dynamic content so it height depends on dynamic data. when i scroll the browser window to bottom, if the that div reaches its end (bottom) on the view, i want to trigger a function (for now just console it ('reached bottom of div')). Also if browser reached the end of the page, the same function wants to trigger. how to achieve this im new to JS and innerHeight, clientHeight so on.. are confusing.
body {
min-height: 500px;
background-color: yellow;
}
.dynamicDiv {
min-height: 200px;
background-color: red;
color: #fff;
}
<div class="dynamicDiv">
some Dynamic data
</div>
window.innerHeight property returns the height of a window's content area.
window.scrollY returns the number of pixels that the document is currently scrolled vertically.
document.body.offsetHeight returns body's height including padding and border
https://jsfiddle.net/smilingpigs/n1vcx3po/4/
window.onscroll = function(ev) {
if ((window.innerHeight + window.scrollY) >= document.body.offsetHeight) {
alert("you are at the bottom of the page");
}
};

How to maintain a dynamic scroll in bottom only if the user moves it to bottom?

I have a scrollview which has content that is being refreshed (increasing it's size) by a ajax query.
I want that (like commonly in all the ides) when the user has the scroll on the bottom, the scroll must be mantained in the bottom even when adding more text.
I tryed to find when the scroll is in the bottom with this code:
var scrollDiv = $('#modalText');
var height = scrollDiv[0].scrollHeight;
if (scrollDiv[0].scrollTop==height){
//scroll is in the bottom, must force the scroll to bottom
}else{
//scroll is not in the bottom, must maintain the scroll point
}
The problem is that scrollDiv[0].scrollTop is not equal to scrollDiv[0].scrollHeight when the user has the scroll in the bottom I can't understand why, but it's about 900 pixels less!
Does anyone has any solution for this?
you need to add the height to scrollTop to get scrollBottom
var scrollDiv = $('#modalText');
function add() {
var height = scrollDiv[0].scrollHeight;
var scroll = scrollDiv[0].scrollTop + scrollDiv[0].offsetHeight;
scrollDiv.append('<p>' + Number(new Date()) + '</p>');
if (scroll == height) {
//scroll is in the bottom, must force the scroll to bottom
scrollDiv.scrollTop(height);
} else {
//scroll is not in the bottom, must maintain the scroll point
}
};
#modalText {
max-height: 180px;
overflow: auto;
width: 200px;
background-color: #f5f5f5;
padding: 10px;
box-sizing: border-box;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button onclick="add()">Add</button>
<div id="modalText"></div>
The difference of 900 you are facing is because because of the viewport/client height. If you add that to the calculations you'll see that find that scrollHeight == scrollTop + clientHeight. You may review this at Mozilla Foundation's documentation of scrollHeight.

Shrink a fixed Div after user has scrolled 175px with animation

I have a div that is fixed at the top of the page, which holds the navigation to the website. It has a height of 175px. This DIV will remain on show as you scroll down the page.
I would like this div to shrink to a height of 90px when the user has scrolled down the page 175px and remain at 90px as they scroll down the page. When they scroll back up to the top, I'd like the DIV to grow back to its original 175px height.
I'd like this to animate when doing so (preferably slide up and slide down) and would prefer to use CSS3 to do so...
Here is a fiddle of what I have so far but because I'm a query noob, not sure how to go about thingsā€¦ http://jsfiddle.net/bnsUB/
EDIT:
I forgot to mention that I also have content within this DIV that will need its paddings etc. adjusted whilst the container slides up/down. So if those padding values could shrink/grow as well then that would be an added bonus
You need to trigger an action based on the current $.scrollTop() value of the window.
Something like:
$(document).scroll(function(){
if ($(this).scrollTop()>175){
// animate fixed div to small size:
$('.wrapper').stop().animate({ height: 90 },100);
} else {
// animate fixed div to original size
$('.wrapper').stop().animate({ height: 175 },100);
}
});
Here goes:
http://jsfiddle.net/bnsUB/4/
If you want to animate any other thing (such as paddings and margins), just add them as values to the object you pass to the .animate() function. ( for example - { height: 175, 'padding-top': 20, 'margin-top': 10 } etc. )
$(window).scroll(function()
{
if ($(window).scrollTop() == $(document).height() - $(window).height())
{
$('#tt').animate({height:'90px'}, 500);
}
});
Here is a solution in vanilla JS and CSS animation:
JS:
window.onscroll = function () {
scrollFunction()
};
function scrollFunction() {
if (document.body.scrollTop > 175 || document.documentElement.scrollTop > 175) {
document.getElementById("header").classList.add("narrow");
} else {
document.getElementById("header").classList.remove("narrow");
}
}
CSS:
#header{
transition: 0.2s;
height: 175px;
}
#header.narrow{
height: 90px !important;
}
#header .anyelementclass{
transition: 0.2s;
}
#header.narrow .anyelementclass{
/* any style here */
}

Categories

Resources