Make a div bigger and wider while scrolling - javascript

How do I enlarge a div while scrolling from a size of 20% width and height in the center to 100% width and height?
I'm currently trying at my first website and I'm almost there. All that is missing is animations and improvements in CSS. One of my ideas is that you have a div with a background inside and while scrolling the picture gets bigger up to the whole viewpoint. I would be very grateful if someone could help me.

You can use transform scale to do it.
CSS part will set the element to take 100% of width and height (i use viewport units), and set it position to fixed (so you will see what happen when you scroll).
Since we gonna change it's scale while scroll, set it initial scale to be 20% of it's original size.
JS part will listen to scroll event and scale the div that it won't be less then 20% but also won't be larger then 100%.
Play with the numbers on the condition to get what you need:
const demoDiv = document.querySelector("#demo");
window.addEventListener('scroll', function() {
if (pageYOffset*0.0001 > 1 || pageYOffset*0.0001 < 0.2) { return; }
else { demo.setAttribute('style', 'transform: scale('+pageYOffset*0.0001+');'); }
});
body {height: 40000px; margin: 0; padding: 0;}
p {position: fixed; top: 0; left: 0; font-size: 40px;}
#demo {
text-align: center;
font-size: 10vw;
position: fixed; top: 0; left: 0;
width: 100vw;
height: 100vh;
background-color: black;
color: white;
transform: scale(0.2); /* since you ask for 20% */
}
<p style="">Scroll to see it grow.</p>
<div id="demo">My minumum width and height are 20% and i will stop grow when i get to 100%</div>

Firstly, Congratulations on your first website. Good luck on your coding journey.
You can do it by using CSS & JavaScript. There is many way, but I'm writing one here. I hope it will be some good.
Let us call the div with an CSS ID animatedDiv.
<div id="animatedDiv"></div>
Now, lets style it with CSS
#animatedDiv
{
margin-top: 200px;
background: #dc143c;
min-height: 350px;
min-width: 20%;
position: absolute;
}
Here, I gave the div a background color, Absolute type of position, and margin-top of 200px. You can change it according to your needs. I used min-height and min-width property because these value will not be any fixed value, they will change on scroll.
Now, lets write some JavaScript
var aDiv = document.getElementById("animatedDiv");
function changeWidth()
{
var scrollVal = window.pageYOffset;
var scrollSlow = (scrollVal / 4);
//Changing CSS Width
aDiv.style.width = Math.min(Math.max(scrollSlow, 20), 100) + "%";
}
window.addEventListener('scroll', function()
{
requestAnimationFrame(changeWidth);
}, false);
Here, on a user define function, I catch the div with it's ID and assign into aDiv variable. Then I catch the page offset on Y axis (How much pixel the page was scrolled) and store it into a variable scrollVal, Next I divide the value by four (you can use 5, 10 20). It will slow the changing effect.
I've use Math methods (min and max) to assign a value between 20 to 100%.
To make the function work on scroll, window.addEventListener is used, and the window.requestAnimationFrame() method will tell the browser that we wish to perform it as an animation.
I hope it will be some help to you. I don't know did I explain well the process to you or not. English is not my mother language, so please don't mind if I made any grammatically mistake.
Wish you all the best.

Related

Css - how to change element size if it reached to certain spot on screen?

I've dynamically created some divs with random color who are scattered over the page randomly. I want to use css to give them a condition that says that if the div is located above let's say 600px on the screen - his size will change. I know the "if" statement for css is #media but I didn't figure how to use it right in this situation. Can you help me?
Example of a div (they all have the same class - "frog")
<div id="frog" class="fas fa-ad" style="width: 66px; height: 66px;
background-color: rgb(87, 58, 55); position: absolute; left: 312px; top:
93px; display: block;"></div>
You can't do that with CSS only. The only way you can have dynamic styling based on what happens in the windows in CSS is to use media queries. However, the docs precise that you can only detect window-level data, like the device width, or whether the page is displayed on a screen or on a printed paper, etc.
You'll have to change your style with JS. This is often a bad way to have dynamic styling, because the only way to do so is to 'probe' the DOM (using for example setInterval). Luckily your case is an exception - since you update your divs position with JS, you can check directly after that the position of your divs, and update your styles accordingly!
Example using the very useful getBoundingClientRect:
// select the frog element
let frog = document.getElementById('frog');
let count = 0;
setInterval(() => {
// update the frog position
frog.style.top = `${count}px`;
count = (count+2)%200;
// check if the frog is after 100px from the top of the window
if (frog.getBoundingClientRect().top>100) {
frog.className = 'over-100';
} else {
frog.className = '';
}
}, 1000/30);
#frog {
position: fixed;
top: 0;
left: 0;
width: 50px;
height: 50px;
background-color: green;
}
#frog.over-100 {
background-color: olive;
}
<div id="frog"></div>

Alternative to absolute positioning that updates parents height

I am working on a library that draws brackets.
I am calculating the coordinates of each element (matches and lines) using javascript. Each element has position: absolute; and uses left and top to set their x and y coordinates.
Because I am using position: absolute; it is necessary to set the parent to position: relative; so that the children are positioned relative to their parent.
This was working perfectly until I noticed that the parents height was not updating from its children, because position: absolute; elements are taken out of the flow of the document.
I need the parent to have height so that I can place other elements underneath, and give the parent styles such as background-color...
Is there an alternative to absolute positioning that uses x and y coordinates but also keeps them in the flow of the document to allow the parents width and height to adjust automatically?
Or, if that is not possible, is there away using vanilla javascript (no jQuery or other libraries) to find out the width and height of the contents of the parent div. If this is possible I can just set the parent's width and height styles through javascript.
What I've tried so far
I tried to set the children to position: relative; instead of position: absolute; which I believe would work if you only have one child. However, with more than one child, the children are not relative to the parent but are now relative to the previous child which messes things up.
Even though the parent has no height there is still a vertical scrollbar on the page. Using javascript, I tried to get the scrollHeight and height of elements such as document, document.body and window. This did not work because either the result was undefined or the result was incorrect.
Right now my temporary solution is to set body height to 2500px which should be the highest it will ever need to be. The problem with this is that there will always be a scrollbar, most of the time scrolling to nothing.
Code
<div class="BrackChart_wrapper">
<div class="BrackChart_match"> ... </div>
<div class="BrackChart_line"></div>
etc.
</div>
.BrackChart_wrapper {
position: relative;
top: 0px;
left: 0px;
}
.BrackChart_match, .BrackChart_line {
position: absolute;
}
Thank you for the help, much appreciated!
JSFiddle: https://jsfiddle.net/jmjcocq8/1/
Solution: https://jsfiddle.net/jmjcocq8/2/
I'm fairly sure there's no alternative that both lets you position the children absolutely (relative to their parent) and keeps them in the flow such that they contribute to the size of the parent.
But since you're calculating the positions of the elements yourself, and you know how tall they are, you can set the height of the parent based on the lowest child's y plus height.
You haven't shown your code, but for instance:
var forEach = Array.prototype.forEach;
function positionChildren(parent) {
var left = 0;
var top = 0;
forEach.call(parent.children, function(child, index) {
child.style.left = left + "px";
child.style.top = top + "px";
left += 20;
top += 10;
});
var height = top - 10 + 1 + parent.lastElementChild.clientHeight;
console.log("height = " + height);
parent.style.height = height + "px";
}
positionChildren(document.getElementById("parent"));
#parent {
border: 1px solid black;
background-color: #ddd;
position: relative;
}
.child {
position: absolute;
border: 1px solid blue;
padding: 0;
margin: 0;
}
<div id="parent">
<div class="child">Child1</div>
<div class="child">Child2</div>
<div class="child">Child3</div>
</div>

Append divs from bottom with scroll - Chat application example

I'm looking to append divs from the bottom. At a certain point, the vertical scroll should kick in so you can view divs that were appended earlier on. I'm trying to replicate a typical chat application and how messages come from the bottom. Here's the codepen...
http://codepen.io/jareko999/pen/yaQmgk
Before I put the code, I'll explain a couple of workarounds I've tried thus far. The pen currently has the container absolutely positioned with a bottom of 0. The problem, which is a pain, is that once the height goes beyond the height of the viewport, it won't scroll. This is the problem with the absolute positioning workaround.
Another workaround I've tried is doing a height of 100vh and display of flex with justify-content flex-end so the columns start at the bottom. The problem with this is that the scroll will always start from the top. I believe the solution is a scroll function that I've created to scroll to the bottom every time a new div is added. Would this be the best method? The key here is that I want to be able to scroll up to the older divs but have the newer divs start from the bottom. Think of a typical chat application like slack or messages or similar.
HTML
<button onclick="myFunction()">Hey here's a box</button>
<div id="container">
</div>
CSS
body {
margin: 0;
width: 100%;
}
button {
position: fixed;
z-index: 10;
}
#container {
position: absolute;
bottom: 0;
width: 100%;
}
#box {
width: 100%;
background: tomato;
opacity: 0;
height: 100px;
transition: .2s;
}
#box:last-child {
opacity: 1;
height: 0;
animation: .2s height linear forwards;
}
#keyframes height {
to {
height: 100px;
}
}
#box:nth-last-child(2) {
opacity: .8;
}
#box:nth-last-child(3) {
opacity: .6;
}
#box:nth-last-child(4) {
opacity: .4;
}
#box:nth-last-child(5) {
opacity: .2;
}
JS
function myFunction() {
var box = document.createElement("div");
box.setAttribute("id", "box");
var container = document.getElementById('container');
container.appendChild(box);
// window.scrollTo(0, document.body.scrollHeight || document.documentElement.scrollHeight);
}
Is there a better solution than the function I've created to scroll to the bottom? Much appreciated.
Ok, so after messing around with some JS, I figured it out. I love when that happens...
Here's the codepen...
http://codepen.io/jareko999/pen/yaQmgk
I created a setInterval function for scrolling to the bottom.
var myVar = setInterval(function(){
window.scrollTo(0, document.body.scrollHeight || document.documentElement.scrollHeight);
}, .1);
However, since this interval runs every .1 seconds, I need to kill it in order to scroll around the divs above (like old chat messages), but I want the animation (of the new div coming in) to finish. So, I created a setTimeout function to kill the setInterval function at 200 ms.
setTimeout(function(){
clearInterval(myVar);
}, 200);

Simple ternary operation is not working

I am attempting to make a div change position on click and then revert to it's original position when clicked again. I cannot for the life of me figure out what the problem is.
$("#bottom").click(function() {
var $about = $('#bottom'),
top = $about.css('top') === '50%' ? '90%' : '50%';
$about.stop().animate({top: top}, 500);
});
my css is:
#bottom {
top: 90%;
left: 0; right: 0;
height: 100%;
}
When I click #bottom, the div positions itself at 50%, but when I hit it again, nothing happens.
.css('top') doesn't give you the literal CSS top declaration; it gives you the calculated pixel amount of the top. If your container for #bottom is 100px tall, then $('#bottom').css('top') will give you 90px, not 90%.
Here's a fiddle with a solution for you.

Position fixed but still scrollable?

Would it be possible to have a DIV position: fixed, but if the content of that DIV extend beyond the viewing area of the screen then you could still scroll with the window? I've put everything I have thus far in this...
FIDDLE
This code sits inside a media query that gets triggered when the screen hits a max width and/or a max height, but I don't think that code is relevant to my question. This is the bit of code that I believe I need to modify to work correctly:
.expand {
display: block !important;
position: fixed;
-webkit-backface-visibility: hidden;
top: 50px;
left: 0;
background: rgba(31, 73, 125, 0.8);
width: 100%;
z-index: 999;
}
The reason I want this fixed is so the little hamburger menu stays statically in the upper left hand corner of the screen at all times, as at times the site I'm building could be rather lengthy, so I would like viewers to have a little more ease of access.
Thank you!
Yes, you just need to give the div a fixed height and the overflow: auto setting
(Demo)
.expand {
bottom: 0;
overflow: auto;
}
If you don't want to give it a minimum height, a simple (but not supported by old browsers) option would be to use css calc() like so
.expand {
max-height: calc(100% - 50px); // 100% viewport height minus the height of the nav.
}
I would suggest setting a fallback height before in case the browser does not support calc
JavaScript
To achieve what you really want you need javascript. Here it is.
Check to see if the menu is open, if not...
Define a check to see if the contents are larger than the viewport, if so then set bottom: 0px; and overflow: auto and remove scrolling from the body.
If so...
Remove all styles from the menu and the body that were added when opening the menu.
(Demo)
(function($) {
var menu = $('.responsive-menu'), open;
$('.menu-btn').click(function () {
if(!open) {
if(menu.height() > $(window).height()) {
open = true;
menu.css({'bottom': '0px', 'overflow': 'auto'});
document.body.style.overflow = 'hidden';
}
} else {
open = false;
menu.css({'bottom': '', 'overflow': ''});
document.body.style.overflow = '';
}
menu.toggleClass('expand');
});
})(jQuery);

Categories

Resources