I've seen a lot of question related to modifying an element opacity when user scrolls but haven't found one that helps me the way I need. I have tried several formulas and haven't been able to achieve the effect I want.
I have a header with a BG image, and inside it a div that I use as an overlay, and I want it to get darker and darker smoothly (opacity increase) while the user scrolls down.
EDIT:
The desired effect is:
Opacity is by default set to 0.2 in CSS. When user starts scrolling down it will start increasing from 0.2 to 1. When user scrolls up again it will decrease from 1 (or whatever value it was) to 0.2.
Fiddle: https://jsfiddle.net/z7q2qtc6/
<div class='nice-header'>
<div class='header-overlay'></div>
</div>
CSS
.nice-header {
position: relative;
height: 300px;
background: center center;
background-size: cover;
background-image: url(http://www.boeing.com/resources/boeingdotcom/commercial/787/assets/images/marquee-787.jpg);
}
.header-overlay {
position: absolute;
top: 0; left: 0;
width: 100%; height: 100%;
background: rgb(0,0,0);
opacity: 0.2;
}
JS
$(window).scroll(function() {
$('.header-overlay').css({
opacity: function() {
var opacity = 0;
//TODO:
//Set opacity to a higer value whilst user scrolls
return opacity;
}
});
});
You can retrieve the current scrolling position by using the .scrollTop() method.
To calculate the opacity, subtract the scrollTop value from the height of the element and then divide that by the element's height.
Example Here
$(window).scroll(function() {
var scrollTop = $(this).scrollTop();
$('.header-overlay').css({
opacity: function() {
var elementHeight = $(this).height();
return 1 - (elementHeight - scrollTop) / elementHeight;
}
});
});
If you want to account for the element's initial opacity of 0.2:
Updated Example
$('.header-overlay').css({
opacity: function() {
var elementHeight = $(this).height(),
opacity = ((1 - (elementHeight - scrollTop) / elementHeight) * 0.8) + 0.2;
return opacity;
}
});
For anyone trying to do this but in the reverse (the elements fades out as you scroll)
opacity = ((elementHeight - scrollTop) / elementHeight);
$(window).scroll(function() {
var scrollTop = $(this).scrollTop();
$('.header-overlay').css({
opacity: function() {
var elementHeight = $(this).height(),
opacity = ((elementHeight - scrollTop) / elementHeight);
return opacity;
}
});
});
.nice-header {
position: relative;
height: 300px;
background: center center;
background-size: cover;
background-image: url(http://www.boeing.com/resources/boeingdotcom/commercial/787/assets/images/marquee-787.jpg);
}
.header-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgb(0, 0, 0);
opacity: 1;
}
.dummy {
height: 900px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class='nice-header'>
<div class='header-overlay'>
</div>
</div>
<div class='dummy'>
</div>
Use rbga instead of rbg and change the alpha value as the user scrolls. I'm obviously not 100% sure what effect you are going for but in most cases using rgba is a better approach than using rgb and opacity.
What are differences between RGB vs RGBA other than 'opacity'
Here is the link to another post that explains this in further detail.
Pretty new to programming. Manage to do it without JQuery
window.addEventListener(`scroll`, function (e) {
const heroOpas = this.scrollY / 1000;
if (heroOpas === 0) {
sectionHero.style.opacity = 1;
}
if (heroOpas > 0) {
sectionHero.style.opacity = `${1 - heroOpas}`;
}
});
Related
I have a problem with a script that until recently worked, but now seems not to want to work.
I want to reduce the opacity of the green spheres when scrolling down, it seems to be working until recently, but now I can't figure out what the problem is.
The website is this: https://attiliosantomo.com/PROVA/
The script is this:
$(document).ready(function() {
$(window).scroll(function(event) {
let scroll = $(this).scrollTop();
let opacity = 1 - (scroll / 1300);
if (opacity > 0.2) {
$('.bg-bubble').css('opacity', opacity);
}
});
});
</script>
Thank you so much for you help
The issue is that it's not the window that is scrolling. It's the .main-desktop element that is being scrolled. Targeting the scroll event of the .main-desktop as per below should solve the issue.
$(document).ready(function() {
// \/ Changed \/ selector from window to '.main-desktop'
$('.main-desktop').scroll(function(event) {
let scroll = $(this).scrollTop();
let opacity = 1 - (scroll / 1300);
if (opacity > 0.2) {
$('.bg-bubble').css('opacity', opacity);
}
});
});
html,
body {
height: 100%;
margin: 0;
}
.main-desktop {
overflow: scroll;
height: 100%;
}
.inner {
height: 3000px;
}
.bg-bubble {
height: 100px;
width: 100px;
background-color: blue;
position: absolute;
top: 0;
left: 0;
border-radius: 50%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="bg-bubble"></div>
<div class="main-desktop">
<div class="inner"></div>
</div>
I'm trying to change the size (or scale) of a div while scrolling.
This div has a .8 scale attached to it css. I'd like to reach a scale of 1 progressively while scrolling.
IntersectionObserver seems to be a good choice to work with instead of scroll event but i don't know if i can change the state of an element using it.
You can change the scale of a div using.
document.getElementById("scaledDiv").style.transform = "scale(1)";
The scroll event should do what you want it to do. You can continue to add more if statements and check how many pixels they are scrolling to change it gradually to 1 or even back to 0.8 when they scroll back up. The 50 below represents 50 pixels from the top of the page.
window.onscroll = function() {
if (document.body.scrollTop > 50 || document.documentElement.scrollTop > 50) {
// They are scrolling past a certain position
document.getElementById("scaledDiv").style.transform = "scale(1)";
} else {
// They are scrolling back
}
};
I hope this will help you:
const container = document.querySelector('.container');
const containerHeight = container.scrollHeight;
const iWillExpand = document.querySelector('.iWillExpand');
container.onscroll = function(e) {
iWillExpand.style.transform = `scale(${0.8 + 0.2 * container.scrollTop / (containerHeight - 300)})`;
};
.container {
height: 300px;
width: 100%;
overflow-y: scroll;
}
.scrollMe {
height: 1500px;
width: 100%;
}
.iWillExpand {
position: fixed;
width: 200px;
height: 200px;
top: 10px;
left: 10px;
background-color: aqua;
transform: scale(0.8);
}
<div class='container'>
<div class='scrollMe' />
<div class='iWillExpand' />
</div>
Looking to make a specific animation for a div element. I want it to go down (smoothly) and when it reaches the bottom of the screen to come back up (smoothly).
The code I have is as follows:
The Javascript part at the If statement is where I am having difficulties. I want the box to come down and come back up smoothly.
HTML:
<div class="verticalDiv" id="verticalDiv" onclick="verticalMove()"></div>
CSS:
.verticalDiv {
position: absolute;
top: 0px;
right: 500px;
width: 100px;
height: 100px;
margin: 100px auto;
background: red;
}
JS:
myVar1 = setInterval(verticalMove, 50);
v = 0;
function verticalMove() {
redBox = document.getElementById('verticalDiv')
redBox.style.top = v + "px";
if (v >= 0) {
v++;}
if (v === 200) {
v--;
}
console.log(v);
}
I think, best way is to use css animation. You don't have to care about animation logic. Just use keyframes.
Here is example:
HTML
<div id="verticalDiv" class="verticalDiv"></div>
CSS
.verticalDiv {
height: 20px;
width: 20px;
background: red;
}
#keyframes move {
0% { transform: translateY(0); }
50% { transform: translateY(200px); }
100% { transform: translateY(0); }
}
.verticalDiv.move {
animation: move 3s ease-in-out;
}
JS
const verticalDiv = document.getElementById('verticalDiv');
verticalDiv.addEventListener('click', () => {
verticalDiv.classList.toggle('move');
});
WORKING DEMO click on red div to start animation.
BTW If you want animate something. It is always better to animate properties that doesn't force layout updates: transform and opacity.
Other properties, like top, bottom, margin are expensive for browser to animate. You should avoid them if possible.
Read more
You need to differentiate between the two phases, moving down and moving up. It can be a simple true/false boolean, but storing a "speed" or "delta" value (like +/-1) is also a very typical approach.
var v = 0;
var delta=1;
function verticalMove() {
redBox = document.getElementById('verticalDiv')
v += delta;
redBox.style.top = v + "px";
if (v <= 0) delta = 1;
if (v >= 50) delta = -1;
}
function startMove(event) {
setInterval(verticalMove,30);
event.target.onclick="";
}
.verticalDiv {
position: absolute;
top: 0px;
right: 500px;
width: 100px;
height: 100px;
background: red;
}
<div class="verticalDiv" id="verticalDiv" onclick="startMove(event)"></div>
I'm trying to recreate an effect like this: https://www.brontidebg.com/product
The main image at the top of the screen (to the left) has a really smooth animation out into the screen (same with the image at the bottom). When you scroll to either image, they animate out in the same manner.
Here is what I've come up with:
HTML
<div class="top">
<h1>scroll down<h1>
</div>
<div class="container">
<div class="block image-block slideright">
<figure>
<img src="https://i.guim.co.uk/img/media/11d4c182d094199e26ddb36febe67123a9bbc93a/34_246_2966_4275/master/2966.jpg?w=700&q=55&auto=format&usm=12&fit=max&s=4a5b5fe1d34627003607df532913292d">
</figure>
</div>
<div class="block text-block">
<h2> Some text </h2>
</div>
</div>
CSS
.top{
height:100vh;
}
h1{
text-align: center;
}
.block{
display: inline-block;
height: 100vh;
}
.image-block{
}
figure{
position: relative;
overflow: hidden;
height: 100vh;
width: 34vw;
text-align: center;
margin: 0;
}
image{
height: 100vh;
width: 34vw;
position: relative;
object-fit: cover;
}
.slideright{
transform: translateX(-34vw);
transition: all .8s ease-out;
}
.slideright.slideinright{
transform: translateX(0);
}
JS
$(window).scroll(function() {
var winTop = $(window).scrollTop();
$(".slideright").each(function(){
var pos = $(this).offset().top;
if (pos < winTop + 600) {
$(this).addClass("slideinright");
}
});
$(".slideleft").each(function(){
var pos = $(this).offset().top;
if (pos < winTop + 600) {
$(this).addClass("slideinleft");
}
});
});
Codepen (view in fullscreen since I'm using vh): https://codepen.io/Caj/pen/GdZwYP
As you can see, the image slides out as you scroll towards it, but it's not a smooth, professional looking animation like the example link. I'm also hoping to have the image slide out if you were to scroll up to the top and then back down (have the function run repeatedly, not just the first time you scroll to within view). Thanks in advance!
Try this:
https://codepen.io/anon/pen/ZoWVxr
$(".slideright").each(function(){
var pos = $(this).offset().top;
if (winTop + 600 > pos) {
$(this).addClass("slideinright");
}
if(winTop === 0) {
$(this).removeClass('slideinright')
}
});
Added opacity, changed the speed and added the reset when the scroll is at the top. I changed your logic a bit so that it doesn't start the animation immediately, it only starts right when the image is in view. You can change the winTop + 600 to control when it starts. Add more to make it start earlier, less to make it start later. winTop + 200 would start the animation further down the scroll.
You are almost there, but what gives that subtle touch of professionality to the animation is the choice of the ease function. I would try with a softer transition like this one:
transition: all 2s cubic-bezier(0.23, 1, 0.32, 1) 400ms;
I have some sections and want to set the height of a separate div (fixed) depending to the scrolling (for a parallax effect). Every scroll action $(window).scroll(function() {...}); the following code is fired. That works fine, but very laggy, because of the CPU usage, I think.
You know how to get the whole thing into the GPU usage with translate or something else.
var windowHeight = $(window).height();
var sectionNumber = 0;
$("main section").each(function() {
sectionNumber++;
var secPosition = $(this).position();
if( ( $(window).scrollTop() + windowHeight ) > secPosition.top ) {
var secScrollValue = ($(window).scrollTop() + windowHeight) - secPosition.top;
$(".parallaxBg" + sectionNumber).css("height", (windowHeight - secScrollValue) + "px");
} else {
$(".parallaxBg" + sectionNumber).css("height", "100%");
}
});
the parallax divs (without the section-numbers):
.parallaxBg {
position: fixed;
height: 100%;
width: 100%;
top: 0px;
left: 0px;
background-position: 0px 0px;
background-size: 100%;
background-repeat: repeat-x;
background-attachment: fixed;
background-image: ...;
}
Here is a sample: http://jsfiddle.net/c5axqoo1/
On retina and with more content its a way more laggy!
Why I used height? Because I want the background-position fixed.
Pre-Thanks :)
You could animate translateY so it uses GPU
Here's a plugin that can might help you:
http://ricostacruz.com/jquery.transit/