How to Create a Simple Fade Effect on Scroll - javascript

Hope you all doing well.
I'm looking for some help on a way to make some adjustment on a JS code. I found this tutorial on how to create a fade effect on scroll, link here.
This works pretty well ! Take a look here.
The JS code is written on a way to only work with 2 slides and I want to add more background-images but I don't know how to do that. Can you help me, please ?
Thank you
HTML
<section>
<div class="img-wrapper">
<div style="background-image: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/162656/cinque-terre-back.jpg);"></div>
<div class="front" style="background-image: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/162656/cinque-terre-front.jpg);"></div>
</div>
</section>
CSS
.img-wrapper {
display: grid;
height: 100vh;
}
.img-wrapper div {
grid-column: 1;
grid-row: 1;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
background-color: var(--gray);
transition: opacity 0.1s;
}
JS
const checkpoint = 300;
window.addEventListener("scroll", () => {
const currentScroll = window.pageYOffset;
if (currentScroll <= checkpoint) {
opacity = 1 - currentScroll / checkpoint;
} else {
opacity = 0;
}
document.querySelector(".front").style.opacity = opacity;
});
I have implemented the code and it works. But I'm not good at JS so I don't know how to edit the JS code so I can display more than 2 background-images.

Related

Translating div to behave like odometer

I've been trying to create an odometer like animation using React, and vanilla css. So far it's working where when number is incremented, a translationY upwards occurs like an actual odometer. My current problem is that when it goes from 9 to 0, the translationY occurs in the opposite direction (downwards instead of upwards). I would like for it to still go in the same direction (up) but super stuck on how to do this. Any help would be greatly appreciated...
Code is here: https://codesandbox.io/s/inspiring-ellis-jpzx2
I spent way too much time looking at solutions for this. First off, there are a ton of libraries that would make something like this trivial, however I enjoyed the learning process of finding a solution.
I did not create a react specific solution, but my vanilla javascript demo should be more than enough to easily port it into a react solution.
To accomplish this task I first tried to create an element each time there was a change, with the bottom number being the starting number, and the top number being the landing number, and slide it down until the desired number was hit, and make the old element disappear. However this ended up looking choppy and had some unintended effects when the element was changed rapidly.
After stumbling across a few demos, I realized that 3d css might be the perfect solution. Instead of having a 2d element we transition up and down, we could create a 3d element that was spinning on a wheel. Js could calculate the degree needed for rotating the element to always be spinning forward.
Please enjoy my small demo, and if you have any questions please ask.
const $ = (str, dom = document) => [...dom.querySelectorAll(str)];
const panels = $(".panel");
panels.forEach((panel, i) => {
panel.style.setProperty("--angle", `${360 / panels.length * i}deg`)
});
const ring = $(".ring")[0];
const nums = $(".num");
nums.forEach((num, i) => {
num.addEventListener("click", () => {
const numAngle = 36 * i;
const currentAngle =
ring.style.getPropertyValue("--deg")
.replace(/\D/g, "");
let nextAngle = numAngle;
while (nextAngle < currentAngle) {
nextAngle += 360;
}
ring.style.setProperty("--deg", `-${nextAngle}deg`)
});
});
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: monospace;
}
body {
display: grid;
place-items: center;
min-height: 100vh;
perspective: 500px;
perspective-origin: 50% 50%;
}
.ring {
transform-style: preserve-3d;
transition: transform 1s;
transform: rotateX(var(--deg));
}
.panel {
position: absolute;
transform:
translate(-50%, -50%)
rotateX(var(--angle))
translateZ(22.5px);
border-bottom: 1px solid black;
background-color: white;
}
.numPanel {
position: absolute;
top: 0;
left: 0;
width: 100%;
display: flex;
justify-content: center;
gap: 1rem;
user-select: none;
}
.num {
font-size: 2rem;
padding: 0.5rem;
cursor: pointer;
}
.num:hover {
background-color: lightblue;
}
<div class="numPanel">
<div class="num">0</div>
<div class="num">1</div>
<div class="num">2</div>
<div class="num">3</div>
<div class="num">4</div>
<div class="num">5</div>
<div class="num">6</div>
<div class="num">7</div>
<div class="num">8</div>
<div class="num">9</div>
</div>
<div class="ring">
<div class="panel">0</div>
<div class="panel">1</div>
<div class="panel">2</div>
<div class="panel">3</div>
<div class="panel">4</div>
<div class="panel">5</div>
<div class="panel">6</div>
<div class="panel">7</div>
<div class="panel">8</div>
<div class="panel">9</div>
</div>

How do I prevent scroll back up with JavaScript or jQuery?

I have a webpage where there is a full height intro image. Underneath this image is the main body of the site with a regular site header at the top, I'm trying to create an effect where once the user scrolls down to the site header, they cannot scroll back up to view the intro image.
CSS Classes:
Main Intro Image: .cq-fullscreen-intro
Site Header: .nav-down
I had a poke around on StackOverflow but I can't find anything that addresses this circumstance, can anyone point me in the right direction to achieve this using jQuery?
you can use JQuery scrollTop function like this
$(function() {
$(window).scroll(function() {
var scroll = $(window).scrollTop();
// set the height in pixels
if (scroll >= 200) {
// after the scroll is greater than height then you can remove it or hide it
$(".intro-image").hide();
}
});
});
So instead of scrolling, I personally think it would be better to have it be actionable. Forcing the user to manually do the transition (and all in between states) is a bad idea. If the user scrolls half way, and see's something actionable (menu, button, input field) is it usable? If it is, what happens if they submit... very awkward. If it isn't usable, how do they know when it is? How do they know it's because they haven't scrolled all the way. It's very poor user experience.
In the following example, I've created a pseudo-screenport for you to see what's actually going on. The .body container in your real site would be the body element.
Code Pen Example
$(document).ready(function(){
$('.splash-screen').on('click', function(){
$('.splash-screen').addClass("is-hidden");
});
})
html, body{
background: #eee;
margin: 0;
padding: 0;
}
.flex-root {
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
width: 100vw;
}
.web-container {
width: 640px;
height: 480px;
background: #fff;
}
.body {
font-size: 0; // this is only to prevent spacing between img placholders
position: relative;
}
.splash-screen{
position: absolute;
transition: transform 1s ease-in-out;
}
.splash-screen .fa {
position: absolute;
z-index: 1;
font-size: 24px;
color: #fff;
left: 50%;
bottom: 15px;
}
.splash-screen.is-hidden {
transform: translateY(-110%);
transition: transform 1s ease-in-out;
}
<link href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="flex-root">
<div class="web-container">
<div class="body">
<div class="splash-screen">
<img src="https://via.placeholder.com/640x480?text=Splash+Screen"/>
<i class="fa fa-chevron-circle-up"></i>
</div>
<img src="https://via.placeholder.com/640x60/cbcbcb?text=Menu"/>
<img src="https://via.placeholder.com/640x420/dddddd?text=Site Body"/>
<div>
</div>
</div>
While its not direclty preventing you from scrolling up and its not jQuery, I would suggest to remove/hide the element once its out of view.
You could get the current scroll position, relative to the top of the page, and check if its greater than the elements height:
const target = document.getElementById('my-target')
const targetHeight = target.getBoundingClientRect().height
const scrollEventListener = () => {
if (
document.body.scrollTop > targetHeight ||
document.documentElement.scrollTop > targetHeight
) {
target.remove()
window.removeEventListener('scroll', scrollEventListener)
document.documentElement.scrollTop = 0
}
}
window.addEventListener('scroll', scrollEventListener)
Here is a codepen https://codepen.io/bluebrown/full/aboagov

CSS/JS image slide out animation

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;

Parallax effect within bootstrap grid

Hello guys I'm trying to make simple parallax effect within bootstrap grid system and I've run into a problem. I made two divs side by side and I want one div to hold static image while other should have parallax effect.
I have a problem with parallax div background-size property no matter what I try I can't make it to cover my parallax div the way I want it, background image always end up being larger then it should be or not aligned correctly.
This is my code:
HTML:
<section id="twoImages" class="container-fluid">
<div class="row">
<div class="col-md-6">
<div class="parallax"></div>
</div>
<div class="col-md-6">
<img class="d-block img-fluid" src="https://placebear.com/715/470" alt="shoe newspaper">
</div>
</div>
</section>
CSS:
body {
margin-bottom: 50em;
}
#twoImages {
padding: 0;
margin: 0;
}
#twoImages .col-md-6 {
padding: 0;
margin: 0;
}
#twoImages .parallax {
/* The image used */
background-image: url("https://placebear.com/715/470");
/* Full height */
height: 100%;
/* Create the parallax scrolling effect */
background-attachment: fixed;
background-position: center;
background-repeat: no-repeat;
background-size: cover;
}
Here is the codepen so you can better understand my problem https://codepen.io/Karadjordje/pen/VpeBzp
Here is your answer
you need to use jquery
check this https://codepen.io/parthjasani/pen/YZwJMq
remove
background-attachment: fixed;
from css
and add this jquery code
var $ = jQuery.noConflict()
$(window).scroll(function(){
var scroll = $(this).scrollTop()
$(".parallax").css({"background-position":"0px "+scroll/2+"px"})
})

Custom scroll UX

I'm currently working on a project where the desired user experience involves a very customized interaction with scroll events.
Problem to solve:
The page has X sections, each of them with a height equal to the viewport hight height: 100vh;. When a user scrolls down on the viewport, the current visible section stays where it is and a scroll indicator animates based on a threshold of distance scrolled (30px, for example). Once the user has scrolled the threshold, the next section comes up from the bottom of the screen and covers up the current section (which still doesn't move).
Initial Approach:
Set each section to an absolute position and adjust them with by changing CSS classes based on the scrollwheel event. Body overflow:hidden and transform property to manipulate the sections. I am running in to issues, though.
The scrollwheel event seems to be documented as very unstable solution to implement.
The .wheelDelta aspect of the event fires asynchronously and is difficult to capture a gesture with. (On chrome, it just spits out a multiple of 3 a bunch of times rather than a distance of the gesture in px). This makes it difficult to set a threshold and animate the elements that are responsive to that threshold.
I basically want to be able to track the number of pixels a scrollwheel-like event is covering and apply that number to the position of a certain scroll-hint element until the scroll threshold is met. Once it is met, a function fires to change the classes and update some information on the page. If the threshold is not met, the scroll hint element goes back to it's default position.
My attached approach doesn't feel very conducive to accomplishing this, so I'm looking for either 1) a different and more stable approach or 2) revisions / criticisms on what I'm doing wrong with this approach to make it stable.
(function scrollerTest($){
$('body').on ('mousewheel', function (e) {
var delta = e.originalEvent.wheelDelta,
currentScreenID = $('section.active').data('self').section_id,
currentScreen = $('section.part-' + currentScreenID),
nextScreenID = currentScreenID + 1,
nextScreen = $('section.part-' + nextScreenID);;
if (delta < 0) { // User is Scrolling Down
currentScreen.removeClass('active').addClass('top');
nextScreen.removeClass('bottom').addClass('active')
} else if (delta > 0) { // User is Scrolling Up
}
});
}(jQuery));
body {
overflow: hidden;
padding: 0;
margin: 0;
}
section {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100vh;
z-index: 999;
background-color: #CA5D44;
transition: 0.8s all ease-in-out;
}
section.part-1 {
position: relative;
z-index: 9;
}
section.part-2 {
background-color: #222629;
}
section.active {
transform: translateY(0);
}
section.top {
transform: translateY(-10%);
}
section.bottom {
transform: translateY(100%);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<body>
<section class="part-1 home active" data-self='{ "section_id" : 1, "section_title" : "Home", "menu_main_clr" : "#fff" , "menu_second_clr" : "#CA5D44", "logo_clr" : "white" }'>
</section>
<section class="part-2 about bottom" data-self='{ "section_id" : 1, "section_title" : "About", "menu_main_clr" : "#CA5D44" , "menu_second_clr" : "#fff", "logo_clr" : "white" }'>
</section>
<section class="part-3 contact bottom" data-self='{ "section_id" : 1, "section_title" : "Contact", "menu_main_clr" : "#fff" , "menu_second_clr" : "#CA5D44", "logo_clr" : "white" }'>
</section>
</body>
Edit Note:
The snippet seems to have some issue with firing the event and changing classes after the first instance - not sure why. On my local example it fires them all at once..
**Edite Note 2: **
Listed code is just a copy of the closest behaviour I could achieve. The whole threshold functionality seems pretty unattainable with this method, unfortunately, as the wheel event doesn't behave like a scroll event.
the whole scroll topic is rather complex especially when you think about touch scroll events, too.
There are some libraries out there - see this list for example: http://ninodezign.com/30-jquery-plugins-for-scrolling-effects-with-css-animation/
I used https://projects.lukehaas.me/scrollify/ before and it might allow you to do what you intend (using the before callback eventually) but I can't tell without trying myself. Also regard that scrollify is relatively big (8kb minified) in comparison to other libraries.
You can approach this using by ensuring each content-filled section is followed by a blank transparent gap (in the example below, also 100vh in height) and then using javascript to apply position:fixed to each content-filled section when it hits the top of the viewport.
Example:
var screens = document.getElementsByClassName('screen');
function checkPosition() {
for (var i = 0; i < (screens.length - 1); i++) {
var topPosition = screens[i].getBoundingClientRect().top;
if (topPosition < 1) {
screens[i].style.top = '0';
screens[i].style.position = 'fixed';
}
}
}
window.addEventListener('scroll',checkPosition,false);
.screen {
position: absolute;
display: block;
left: 0;
width: 100%;
height: 100vh;
}
.red {
position: fixed;
top: 0;
background-color: rgb(255,0,0);
}
.orange {
top: 200vh;
background-color: rgb(255,140,0);
}
.yellow {
top: 400vh;
background-color: rgb(255,255,0);
}
.green {
top: 600vh;
background-color: rgb(0,191,0);
}
.blue {
top: 800vh;
background-color: rgb(0,0,127);
}
p {
font-size: 20vh;
line-height: 20vh;
text-align: center;
color: rgba(255,255,255,0.4);
}
<div class="red screen">
<p>Screen One</p>
</div>
<div class="orange screen">
<p>Screen Two</p>
</div>
<div class="yellow screen">
<p>Screen Three</p>
</div>
<div class="green screen">
<p>Screen Four</p>
</div>
<div class="blue screen">
<p>Screen Five</p>
</div>

Categories