scrolling animation for elements of certain class using js - javascript

I'm trying to make a scrolling animation for each element of class js-scroll. Inside the style code, I have a class .scrolled-proj which changes the opacity of a project from 0 to 1. The js code adds this class to each js-scroll element when it appears in the window (within 100 pixels, based on the offset input). Relevant bits of my code are as follows:
const scroll_elem = document.querySelectorAll(".js-scroll");
scroll_elem.forEach( (el) => {el.style.opacity = "0";} );
// returns true if elem is "in view"
const in_view = (el, off) => {
const top = el.getBoundingClientRect().top;
return ( top <= (window.innerHeight - offset) );
}
const scroll_animation = () => {
scroll_elem.forEach((el) => {
if(in_view(el, 100)){ el.classList.add("scrolled-proj"); }
else{ el.classList.remove("scrolled-proj"); }
})
}
window.addEventListener("scroll", () => {
scroll_animation();
});
.project-elem {
background-color: greenyellow;
margin: 5rem 5rem;
--height: 300px;
}
.projects {
margin: 0;
padding: 3rem;
background-color: #DDCDE8;
font: Asap, sans-serif;
height: 5*var(--height);
text-align: center;
}
.project-n {
background-color: green;
text-align: center;
width: 60%;
height: 250px;
float: left;
padding: 3rem;
}
.img {
background-color: blue;
text-align: center;
margin-left: 40%;
height: 250px;
}
.scrolled-proj{
opacity: 1;
}
<div class="projects" id=#projects>
<h2>My Projects</h2>
<article class="project-elem">
<div class="project-n js-scroll" id="dictocounter">
<h3>Dictation Counter</h3>
<p>info about proj</p>
<img src="dictocounter1.jpg" alt="Dictocounter in Action">
</div>
<div class="img js-scroll">
<p>heres SOME IMAGE</p>
</div>
</article>
<article class="project-elem">
<div class="project-n js-scroll" id="calc">
<h3>RPN Calculator</h3>
<p>info about proj</p>
<img src="calc.jpg" alt="RPN Calculator Decoding Input">
</div>
<div class="img js-scroll">
<p>heres SOME IMAGE</p>
</div>
</article>
<article class="project-elem">
<div class="project-n js-scroll" id="markov">
<h3>Markov Chain Text Generation</h3>
<p>info about proj</p>
<img src="calc.jpg" alt="Markov Chain Text Generation">
</div>
<div class="img js-scroll">
<p>heres SOME IMAGE</p>
</div>
</article>
<article class="project-elem">
<div class="project-n js-scroll" id="audio">
<h3>Song Similarities</h3>
<p>info about proj</p>
<img src="calc.jpg" alt="Audio Spectral Analysis">
</div>
<div class="img js-scroll">
<p>heres SOME IMAGE</p>
</div>
</article>
<article class="project-elem">
<div class="project-n js-scroll" id="tree">
<h3>DFS/BFS Search Tree</h3>
<p>info about proj</p>
<img src="calc.jpg" alt="Simple Trees">
</div>
<div class="img js-scroll">
<p>heres SOME IMAGE</p>
</div>
</article>
</div>
Upon refreshing the webpage, each js-scroll element is indeed initialized to opacity 0, but scrolling does not change the opacity of any of the js-scroll elements. As a sanity check, I made the in_view function always return true, but all js-scroll elements remained transparent. This seems to suggest that scroll_animation is not being called (since in_view is not changing the opacity of any elements), but I don't know why this would be the case.

A couple of issues.
You are passing the param off into the in_view() function, however the functions return statement is referencing offset which is undefined.
Then you are placing an inline style to the .js-scroll elements for an opacity of 0 using JS in the forEach loop. That inline style will override the computed style coming fromt he class when it is added, therefor your opacity will never actually be set to 1 regardless of the addition of the class that defines the opacity property to 1.
TEST: First fix your parameter naming issue and rename the return in the in_view function to off, then you can run your scroll event and then look at the inspector and it will be right there in the inline style attribute, style="opacity:0; along with the class,scrolled-proj that is supposed to change the opacity to 1.
To fix this create a helper css rule that initializes the opacity property using a class and not an inline style created with javascript.
So change the in_view function to reference the correct param, off, then add a CSS class that sets opacity to 0. => a class to the initial loop that iterates over the .js-scroll elements like this...
// reference the proper param in your return here
const in_view = (el, off) => {
const top = el.getBoundingClientRect().top;
return (top <= (window.innerHeight - off));
}
/* add a helper class that will set your opacity to 0 intially */
.scrolled-proj-hidden {
opacity: 0;
transition: opacity 500ms linear; /* optional .5 second animation for opacity */
Then JS
// Now instead of inline style, we add the helper class using el.classList.add()
const scroll_elem = document.querySelectorAll(".js-scroll");
scroll_elem.forEach((el) => {
el.classList.add("scrolled-proj-hidden");
});
Then on your scroll_animation function set the proper classes in your conditional like this...
const scroll_animation = () => {
scroll_elem.forEach((el) => {
if (in_view(el, 100)) {
el.classList.add("scrolled-proj");
el.classList.remove("scrolled-proj-hidden");
} else {
el.classList.remove("scrolled-proj");
el.classList.add("scrolled-proj-hidden");
}
})
}
const scroll_elem = document.querySelectorAll(".js-scroll");
scroll_elem.forEach((el) => {
el.classList.add("scrolled-proj-hidden");
});
// returns true if elem is "in view"
const in_view = (el, off) => {
const top = el.getBoundingClientRect().top;
return (top <= (window.innerHeight - off));
}
const scroll_animation = () => {
scroll_elem.forEach((el) => {
if (in_view(el, 100)) {
el.classList.add("scrolled-proj");
el.classList.remove("scrolled-proj-hidden");
} else {
el.classList.remove("scrolled-proj");
el.classList.add("scrolled-proj-hidden");
}
})
}
window.addEventListener("scroll", scroll_animation);
.project-elem {
background-color: greenyellow;
margin: 5rem 5rem;
--height: 300px;
}
.projects {
margin: 0;
padding: 3rem;
background-color: #DDCDE8;
font: Asap, sans-serif;
height: 5*var(--height);
text-align: center;
}
.project-n {
background-color: green;
text-align: center;
width: 60%;
height: 250px;
float: left;
padding: 3rem;
}
.img {
background-color: blue;
text-align: center;
margin-left: 40%;
height: 250px;
}
.scrolled-proj {
opacity: 1;
transition: opacity 500ms linear;
}
.scrolled-proj-hidden {
opacity: 0;
transition: opacity 500ms linear;
}
<div class="projects" id=#projects>
<h2>My Projects</h2>
<article class="project-elem">
<div class="project-n js-scroll" id="dictocounter">
<h3>Dictation Counter</h3>
<p>info about proj</p>
<img src="dictocounter1.jpg" alt="Dictocounter in Action">
</div>
<div class="img js-scroll">
<p>heres SOME IMAGE</p>
</div>
</article>
<article class="project-elem">
<div class="project-n js-scroll" id="calc">
<h3>RPN Calculator</h3>
<p>info about proj</p>
<img src="calc.jpg" alt="RPN Calculator Decoding Input">
</div>
<div class="img js-scroll">
<p>heres SOME IMAGE</p>
</div>
</article>
<article class="project-elem">
<div class="project-n js-scroll" id="markov">
<h3>Markov Chain Text Generation</h3>
<p>info about proj</p>
<img src="calc.jpg" alt="Markov Chain Text Generation">
</div>
<div class="img js-scroll">
<p>heres SOME IMAGE</p>
</div>
</article>
<article class="project-elem">
<div class="project-n js-scroll" id="audio">
<h3>Song Similarities</h3>
<p>info about proj</p>
<img src="calc.jpg" alt="Audio Spectral Analysis">
</div>
<div class="img js-scroll">
<p>heres SOME IMAGE</p>
</div>
</article>
<article class="project-elem">
<div class="project-n js-scroll" id="tree">
<h3>DFS/BFS Search Tree</h3>
<p>info about proj</p>
<img src="calc.jpg" alt="Simple Trees">
</div>
<div class="img js-scroll">
<p>heres SOME IMAGE</p>
</div>
</article>
</div>
If this is not what you were looking for, let me know and I can edit or delete this answer.

Related

Hide an element per multiple scrollable divs

I am trying to fade out a logo at the top of three divs onscroll.
I would like it so when a user scrolls one div, the logo fades from div that is being scrolled, not all of them.
There is also a problem with scrolling to the top again, the logo is faded. It should return to full opacity.
Here is what I have so far.
$("#col1").scroll(function(){
var scroll = $("#col1").scrollTop();
$('img').css('opacity', (10-scroll)/100)
});
$("#col2").scroll(function(){
var scroll = $("#col2").scrollTop();
$('img').css('opacity', (100-scroll)/100)
});
$("#col3").scroll(function(){
var scroll = $("#col3").scrollTop();
$('img').css('opacity', (100-scroll)/100)
});
#wrapper { border: 2px solid red;overflow:hidden;height:100%;}
.column {width: 33.333%;height:500px; float:left; overflow:scroll;}
#col1 { background-color: grey; }
#col2 { background-color: green; }
#col3 { background-color: yellow;}
img{ height:100px;transition: all 0.1s ease-in;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="column" id="col1">
<img class="logo" src="https://static.vecteezy.com/system/resources/previews/001/191/989/non_2x/circle-logo-png.png"/>
<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>
</div>
<div class="column" id="col2">
<img class="logo" src="https://static.vecteezy.com/system/resources/previews/001/191/989/non_2x/circle-logo-png.png"/>
<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>
</div>
<div class="column" id="col3">
<img class="logo" src="https://static.vecteezy.com/system/resources/previews/001/191/989/non_2x/circle-logo-png.png"/>
<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>
</div>
The scroll function below chooses the proper logo, depending on which <div/> is scrolled. It also consolidates the 3 scroll event handlers into one.
The problem you had in fading back to full opacity is because your first scroll handler had (10-scroll)/100) instead of (100-scroll)/100).
$("#col1,#col2,#col3").scroll(function(){
var col = $(this);
var scroll = col.scrollTop();
col.find('img').css('opacity', (100-scroll)/100);
});
#wrapper { border: 2px solid red;overflow:hidden;height:100%;}
.column {width: 33.333%;height:500px; float:left; overflow:scroll;}
#col1 { background-color: grey; }
#col2 { background-color: green; }
#col3 { background-color: yellow;}
img{ height:100px;transition: all 0.1s ease-in;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="column" id="col1">
<img class="logo" src="https://static.vecteezy.com/system/resources/previews/001/191/989/non_2x/circle-logo-png.png"/>
<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>
</div>
<div class="column" id="col2">
<img class="logo" src="https://static.vecteezy.com/system/resources/previews/001/191/989/non_2x/circle-logo-png.png"/>
<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>
</div>
<div class="column" id="col3">
<img class="logo" src="https://static.vecteezy.com/system/resources/previews/001/191/989/non_2x/circle-logo-png.png"/>
<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>Line<br>
</div>

On scroll down images are moving up

I want on scroll down, that the images are moving up a bit, like on this website:
example site (digital does)
Down the website on digitaldoes you can see what i mean. The images are moving up a bit if you scroll down. Is it maby a lazy-load with images that are fading in or an animation where the images moving for example 5px up?
Here is a: jsfiddle updated!!!
$(document).ready(function () {
$(".img-scroll").css("display", "none");
$(window).scroll(function() {
$( ".img-scroll" ).addClass("animate");
$( ".img-scroll" ).css("display", "block");
console.log("Hey");
});
});
.img-scroll {
-moz-transition: top 10s;
transition: top 10s;
}
.img-scroll.animate {
top: 5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.0.1/dist/css/bootstrap.min.css" rel="stylesheet"/>
<div class="row">
<header class="arbeiten">
<h2>{ Logos }</h2>
</header>
</div>
<div id="links">
<div class="row">
<div class="col-xxl-1"></div>
<div class="col-12 col-md-6 col-lg-4 col-xxl-5">
<div class="card shadow-sm first-image">
<a href="https://www.fillmurray.com/1000/1000" title="Test - Logo #1">
<img src="https://www.fillmurray.com/300/150" alt="Test - Logo #1" class="card-img-top logo-hover">
</a>
<div class="card-body">
<p class="card-text">Test - Logo #1</p>
<div class="d-flex justify-content-between align-items-center"></div>
</div>
</div>
</div>
<div class="col-12 col-md-6 col-lg-4 col-xxl-5">
<div class="card shadow-sm">
<a href="https://www.fillmurray.com/1000/1000" title="Test - Logo #2">
<img src="https://www.fillmurray.com/300/150" alt="Test - Logo #2" class="card-img-top logo-hover">
</a>
<div class="card-body">
<p class="card-text">Test - Logo #2</p>
<div class="d-flex justify-content-between align-items-center"></div>
</div>
</div>
<div class="col-12 col-md-6 col-lg-4 col-xxl-5 img-scroll">
<div class="card shadow-sm first-image">
<a href="https://www.fillmurray.com/1000/1000" title="Test - Logo #3">
<img src="https://www.fillmurray.com/300/150" alt="Test - Logo #3" class="card-img-top logo-hover">
</a>
<div class="card-body">
<p class="card-text">Test - Logo #3</p>
<div class="d-flex justify-content-between align-items-center"></div>
</div>
</div>
</div>
<div class="col-xxl-1"></div>
<div class="col-xxl-1"></div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.0.1/dist/js/bootstrap.bundle.min.js"></script>
I hope, someone can help me...
The most important step is to check if an <img> element is entering the current viewport.
We can use the Intersection Observer API.
const options = {
rootMargin: "0px",
threshold: 0.5
};
const inViewPortObserver = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
let target = entry.target;
let dataSrc = target.getAttribute('data-src');
target.src = dataSrc;
target.classList.replace('lazyload', 'lazyloaded');
}
});
}, options);
By adjusting the threshold value we can define when the intersecting value returns true:
E.g treshold:0.5 => element is intersection if 50% of it's height is in viewport.
Now we can define a callback:
if(entry.isIntersecting){}
If element is in viewport – set the src attribute from data-src and toggle css classes from 'lazyload' to 'lazyloaded'.
Most lazyload libraries use a similar syntax or api concept like this:
<img data-src="https://www.fillmurray.com/480/480" class="lazyload">
The actual image src/URL is defined by a data attribute: data-src.
Lazy loading can significantly improve the overall performance and user experience by loading images only if they are really required.
The animation is done by toggling between css classes:
E.g .lazyload (not loaded yet) and lazyloaded (loaded)
.lazyload {
opacity: 0;
transform: translateY(100%);
}
.lazyloaded {
opacity: 1;
transform: translateY(0%);
}
Simple Example: using js IntersectionObserver()
const options = {
rootMargin: "0px",
threshold: 0.5
};
const inViewPortObserver = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
let target = entry.target;
let dataSrc = target.getAttribute('data-src');
target.src = dataSrc;
target.classList.replace('lazyload', 'lazyloaded');
}
});
}, options);
const images = document.querySelectorAll('.lazyload');
images.forEach(function(img, i) {
inViewPortObserver.observe(img);
})
* {
box-sizing: border-box
}
header {
margin-bottom: 40vmin;
}
main {
padding-bottom: 50em;
}
section {
margin-bottom: 20em;
}
.row {
display: flex;
}
.row>* {
flex: 1;
}
.card-img-top {
transition: 2s;
}
.lazyload {
opacity: 0;
transform: translateY(100%);
}
.lazyloaded {
opacity: 1;
transform: translateY(0%);
}
img {
aspect-ratio: 2/1;
display: block;
background-color: #ccc;
width: 100%;
max-width: 100%;
object-fit: cover;
object-position: 50% 50%;
}
<div class="row">
<header class="arbeiten">
<h2>{ Logos }</h2>
<p>Please scroll down …</p>
</header>
</div>
<main>
<section>
<div class="row">
<figure>
<img data-src="https://www.fillmurray.com/480/480" alt="Test - Logo #1" class="lazyload card-img-top logo-hover">
</figure>
<figure>
<img data-src="https://www.fillmurray.com/300/150" alt="Test - Logo #1" class="lazyload card-img-top logo-hover">
</figure>
</div>
<div class="row">
<figure>
<img data-src="https://www.fillmurray.com/300/200" alt="Test - Logo #1" class="lazyload card-img-top logo-hover">
</figure>
<figure>
<img data-src="https://www.fillmurray.com/200/300" alt="Test - Logo #1" class="lazyload card-img-top logo-hover">
</figure>
<figure>
<img data-src="https://www.fillmurray.com/400/240" alt="Test - Logo #1" class="lazyload card-img-top logo-hover">
</figure>
</div>
</section>
<section>
<div class="row">
<figure>
<img data-src="https://www.fillmurray.com/320/240" alt="Test - Logo #1" class="lazyload card-img-top logo-hover">
</figure>
<figure>
<img data-src="https://www.fillmurray.com/300/150" alt="Test - Logo #1" class="lazyload card-img-top logo-hover">
</figure>
<figure>
<img data-src="https://www.fillmurray.com/333/111" alt="Test - Logo #1" class="lazyload card-img-top logo-hover">
</figure>
<figure>
<img data-src="https://www.fillmurray.com/444/333" alt="Test - Logo #1" class="lazyload card-img-top logo-hover">
</figure>
</div>
</section>
</main>
Example 2: observe a parent element and lazyload images
The main difference: we're observing viewport intersections for parent elements like the .card class.
const options = {
rootMargin: "0px",
threshold: 0.1
};
const inViewPortObserver = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
let target = entry.target;
let img = target.querySelector('img');
let dataSrc = img.getAttribute('data-src');
img.src = dataSrc;
target.classList.add('inViewPort');
}
});
}, options);
const cards = document.querySelectorAll('.card');
cards.forEach(function(card, i) {
inViewPortObserver.observe(card);
})
* {
box-sizing: border-box
}
header {
margin-bottom: 60vmin;
}
main {
padding-bottom: 50em;
}
section {
margin-bottom: 20em;
}
.row {
display: flex;
gap: 1em;
}
.row>* {
flex: 1;
}
.card {
transition: 2s;
transform: translateY(100%);
border: 2px solid red;
opacity: 0;
}
/** optional sibling delay */
.row .card:nth-of-type(2) {
transition-delay: 0.5s;
}
.row .card:nth-of-type(3) {
transition-delay: 0.75s;
}
.row .card:nth-of-type(4) {
transition-delay: 1s;
}
.row .card:nth-of-type(5) {
transition-delay: 1.25s;
}
.row .card:nth-of-type(6) {
transition-delay: 1.5s;
}
.inViewPort {
opacity: 1;
transform: translateY(0%);
}
img {
aspect-ratio: 2/1;
display: block;
background-color: #ccc;
width: 100%;
max-width: 100%;
object-fit: cover;
object-position: 50% 50%;
}
<div class="row">
<header class="arbeiten">
<h2>{ Logos }</h2>
<p>Please scroll down …</p>
</header>
</div>
<main>
<section>
<div class="row row1">
<div class="card">
<a href="#">
<img data-src="https://www.fillmurray.com/480/480" alt="" class="lazyload card-img-top logo-hover">
</a>
</div>
<div class="card">
<a href="#">
<img data-src="https://www.fillmurray.com/300/150" alt="" class="lazyload card-img-top logo-hover">
</a>
</div>
<div class="card">
<a href="#">
<img data-src="https://www.fillmurray.com/300/222" alt="" class="lazyload card-img-top logo-hover">
</a>
</div>
<div class="card">
<a href="#">
<img data-src="https://www.fillmurray.com/300/247" alt="" class="lazyload card-img-top logo-hover">
</a>
</div>
</div>
</section>
<section>
<div class="row row2">
<div class="card">
<a href="#">
<img data-src="https://www.fillmurray.com/320/240" alt="" class="lazyload card-img-top logo-hover">
</a>
</div>
<div class="card">
<a href="#">
<img data-src="https://www.fillmurray.com/300/111" alt="" class="lazyload card-img-top logo-hover">
</a>
</div>
<div class="card">
<a href="#">
<img data-src="https://www.fillmurray.com/300/112" alt="" class="lazyload card-img-top logo-hover">
</a>
</div>
</div>
</section>
<section>
<div class="row row2">
<div class="card">
<a href="#">
<img data-src="https://www.fillmurray.com/320/240" alt="" class="lazyload card-img-top logo-hover">
</a>
</div>
<div class="card">
<a href="#">
<img data-src="https://www.fillmurray.com/300/111" alt="" class="lazyload card-img-top logo-hover">
</a>
</div>
<div class="card">
<a href="#">
<img data-src="https://www.fillmurray.com/300/112" alt="" class="lazyload card-img-top logo-hover">
</a>
</div>
</div>
</section>
They have build the gallery with gridster and scrollmagic. Scrollmagic lets you do all kind of things when scrolling.
you can checkout the package at https://scrollmagic.io
You can animate with jQuery. Here is tutorial with example.
http://talkerscode.com/webtricks/move-elements-on-page-scroll-using-jquery-and-css.php
The animation on the site that you provided is triggered when the load event on the images is emitted. The load event is emitted when an image has completed loading. This is combined with lazy loading to load the images as you scroll down on the page.
To implement something like this, you need to enable lazy loading for the images and listen for a load event on them. When the load event is emitted, use Javascript to complete the animation.
The javascript would look something like this:
$(".img-scroll").one("load", () => {
// do animation here
})
Just make sure the images have lazy loading enabled by setting their loading attribute to lazy
there is a very good library for scroll effect called AOS.I linked it down here
it .You can find setup guide at the end of the page. Just add those styles to your image or any other html tag!. Make sure that you check it out.
link to AOS library
I am using TweenMax.min.js, TimelineMax.min.js, ScrollMagic.min.js
List item
const tl = new TimelineMax();
const tl2 = new TimelineMax();
const controller = new ScrollMagic.Controller();
tl.from('#first-fig', .3, {y:200, opacity: 0});
tl.from('#second-fig', .3, {scale: 0}, "=-.5");
tl.from('#third-fig', .3, {y:200, opacity: 0});
tl2.from('#fourth-fig', .5, {y:200, opacity: 0});
tl2.from('#fifth-fig', .5, {y:200,opacity: 0});
tl2.from('#sixth-fig', .5, {y:200, opacity: 0});
const firstScene = new ScrollMagic.Scene({
triggerElement: "#second-h1"
})
.setTween(tl)
.addTo(controller);
const secondScene = new ScrollMagic.Scene({
triggerElement: "#first-img"
})
.setTween(tl2)
.addTo(controller);
#import url("https://fonts.googleapis.com/css?family=Arapey");
*,
*::after,
*::before {
margin: 0;
padding: 0;
box-sizing: inherit;
}
html {
box-sizing: border-box;
font-size: 62.5%;
}
body {
font-family: "Arapey";
font-weight: 700;
background: #dfe6e9;
}
.container {
position: relative;
}
h1 {
margin: 0 auto;
width: 100rem;
text-align: center;
font-size: 6rem;
}
.section--1 {
height: 100rem;
background: #bdc3c7;
}
.section--2 {
margin: 0 auto;
width: 100rem;
}
.images {
display: grid;
padding: 0.5rem;
margin: 2rem auto;
width: 100%;
grid-template-rows: repeat(auto-fill, 25rem);
grid-template-columns: repeat(3, 1fr);
grid-gap: 0.8rem;
grid-auto-columns: 1fr;
grid-auto-rows: 25rem;
}
.images--img {
width: 100%;
height: 100%;
object-fit: cover;
display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/2.0.2/TweenMax.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/2.0.2/TimelineMax.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ScrollMagic/2.0.6/ScrollMagic.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ScrollMagic/2.0.6/plugins/animation.gsap.min.js"></script>
<div class="container">
<section class="section--1">
<h1>Scroll down to see the animations</h1>
</section>
<section class="section--2">
<h1 id="second-h1">
hello there I love code and music
</h1>
<div class="images">
<figure class="images--fig" id="first-fig"><img src="https://images.unsplash.com/photo-1485170536212-67180b105ff6?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1050&q=80" alt="" class="images--img" id="first-img"></figure>
<figure class="images--fig" id="second-fig"><img src="https://images.unsplash.com/photo-1518257678582-d5c9bb2e6ec9?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=588&q=80" alt="" class="images--img"></figure>
<figure class="images--fig" id="third-fig"><img src="https://images.unsplash.com/photo-1540821924489-7690c70c4eac?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=991&q=80" alt="" class="images--img"></figure>
<figure class="images--fig" id="fourth-fig"><img src="https://images.unsplash.com/photo-1484755560615-a4c64e778a6c?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=980&q=80" alt="" class="images--img" id="fourth-img"></figure>
<figure class="images--fig" id="fifth-fig"><img src="https://images.unsplash.com/photo-1481207727306-1a9f151fca7d?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1050&q=80" alt="" class="images--img"></figure>
<figure class="images--fig" id="sixth-fig">
<img src="https://images.unsplash.com/photo-1517852058149-07c7a2e65cc6?ixlib=rb-1.2.1&auto=format&fit=crop&w=1050&q=80" alt="" class="images--img">
</figure>
</div>
</section>
<section class="section--1"></section>
</div>
Here is barebone structure similar to the example website using a tiny library #opuu/inview.
The parallax effect and animation on scroll both can be done with this same library very easily.
body {
margin: 0;
padding: 0;
}
#container {
position: relative;
width: 100%;
}
#background {
background: url('https://picsum.photos/seed/picsum/700/500');
background-size: cover;
background-position: center;
height: 150vh;
width: 100%;
}
#foreground {
background-color: blue;
transition: margin-top 0.1s;
height: 200vh;
width: 70%;
margin: 0 auto;
}
#effect {
padding: 20px;
width: 100%;
background-color: brown;
display: flex;
justify-content: space-around;
align-items: center;
}
.aos {
transform: translateY(500px);
transition: all 0.5s;
}
.aos.active {
transform: translateY(0);
transition: all 0.5s;
}
#empty {
height: 100vh;
width: 100%;
background-color: green;
}
<div id="container">
<div id="background">
Background with image
</div>
<div id="foreground">
Content that overlays the background
</div>
<div id="effect">
<img class="aos" loading="lazy" src="https://picsum.photos/seed/picsum/700/500" alt="">
<img class="aos" loading="lazy" src="https://picsum.photos/seed/picsum/700/500" alt="">
</div>
<div id="effect">
<img class="aos" loading="lazy" src="https://picsum.photos/seed/picsum/700/500" alt="">
<img class="aos" loading="lazy" src="https://picsum.photos/seed/picsum/700/500" alt="">
</div>
<div id="empty">
</div>
</div>
<script type="module">
import InView from "https://unpkg.com/#opuu/inview#1.0.2/dist/inview.js";
let hero = new InView("#background");
hero.on("enter", (event) => {
document.querySelector("#foreground").style.marginTop = `-${100 - event.percentage}vh`;
});
let effect = new InView(".aos");
let queue = 0;
effect.on("enter", (event) => {
if (queue == 0) {
event.target.style.transitionDelay = "0.2s";
event.target.classList.add("active");
queue = 1;
} else {
event.target.classList.add("active");
queue = 0;
}
});
// effect.on('exit', (event) => {
// event.target.classList.remove("active"); // you can also add remove animation
// });
</script>
Note: I am the author of this library.

Two images change places when hover CSS

I'm looking for an answer to my problem. I have one large image on the top and eight small images on the bottom of my page. I want to make it so when you hover the small image (it's also a link which goes to different place) the large image changes to this small image. So clearly explained, two images change/swap places. And when I unhover the large image changes back.
Here's the picture so you know what I'm talking about!
And I'm looking for CSS, React (if there is any useful components) or just JavaScript-solution (if else statement or something like that).
https://i.ibb.co/C5m5sH3/demonstration.png
Thank you for your time!
You can use jQuery for your case, capture the hover event and update main image source.
$(document).ready(function(){
$('.thumbnail').hover(function(e){
src = $(e.target).data('main');
$("#target_img").attr('src', src);
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="main_image" style="width: 200px; height: 100px">
<img id="target_img" src="#"/>
</div>
<ul>
<li>
<img class="thumbnail" src="https://th.bing.com/th/id/OIP.wx64GmJDu2nd32eO_tieDgHaEK?pid=Api&rs=1" data-main="https://th.bing.com/th/id/OIP.wx64GmJDu2nd32eO_tieDgHaEK?pid=Api&rs=1" width="50px" height="50px"/>
</li>
<li>
<img class="thumbnail" src="https://1.bp.blogspot.com/_138avbqsoJQ/S31zZz9qPZI/AAAAAAAABNQ/ARDHrOa5_pg/s400/Loch_Lomond.JPG" data-main="https://1.bp.blogspot.com/_138avbqsoJQ/S31zZz9qPZI/AAAAAAAABNQ/ARDHrOa5_pg/s400/Loch_Lomond.JPG" width="50px" height="50px"/>
</li>
</ul>
Use mouseover and mouseout event listeners to change the background image of your big div.
The below snippet explains it all -
function change(e){
document.getElementById("main").style.backgroundImage = `url(${e.target.src})`;
}
let imgs = document.getElementsByTagName("img");
for(let i = 0; i<imgs.length; i++){
imgs[i].addEventListener("mouseover", function(){
change(event);
});
imgs[i].addEventListener("mouseout", function(){
document.getElementById("main").style.backgroundImage = `url("https://cdn.pixabay.com/photo/2020/11/28/11/03/advent-5784271__340.jpg")`;
});
}
#main{
height: 150px;
width: 150px;
border: 3px dashed red;
background-image: url("https://cdn.pixabay.com/photo/2020/11/28/11/03/advent-5784271__340.jpg");
}
img{
height: 50px;
width: 50px;
}
<div id="main"></div>
<img src="https://cdn.pixabay.com/photo/2020/03/24/11/21/winter-4963715__340.jpg">
<img src="https://cdn.pixabay.com/photo/2019/12/10/19/15/new-years-eve-4686590__340.jpg">
<img src="https://cdn.pixabay.com/photo/2020/11/17/15/44/cup-5752775__340.jpg">
<img src="https://cdn.pixabay.com/photo/2019/05/18/13/34/branches-4211837__340.jpg">
Currently I don't know what is the structure of your html, but you can tweak this solution to fit your case.
I have created an example of the swap effect that you specified, and created a code pen of it using colors instead:
https://codepen.io/DaudWaqas/pen/xxEgxLm
<section class="main" id="main" style="background-color: #000"></section>
<div>
<Section style="background-color: orange" onmouseover="grabAndSwap(event)"></section>
<Section style="background-color: cyan" onmouseover="grabAndSwap(event)"></section>
<Section style="background-color: maroon" onmouseover="grabAndSwap(event)"></section>
<Section style="background-color: #444" onmouseover="grabAndSwap(event)"></section>
</div>
<div>
<Section style="background-color: #ff0000" onmouseover="grabAndSwap(event)"></section>
<Section style="background-color: #00ff00" onmouseover="grabAndSwap(event)"></section>
<Section style="background-color: #0000ff" onmouseover="grabAndSwap(event)"></section>
<Section style="background-color: magenta" onmouseover="grabAndSwap(event)"></section>
</div>
CSS:
.main {
height: 30vh;
width: 100%;
}
section {
height: 15vh;
width: 25%;
float: left;
}
div {
height: 15vh;
width: 100%;
}
JS:
const main = document.getElementById('main');
function grabAndSwap(event) {
var toSwapWith = event.target;
var mainColor = main.style.backgroundColor;
console.log(mainColor);
var otherColor = toSwapWith.style.backgroundColor;
console.log(otherColor);
main.style.backgroundColor = otherColor;
toSwapWith.style.backgroundColor = mainColor;
}
You can capture mouseover in Javascript and simply swap the background-image and swap back on mouseout.
const picEls= document.getElementsByClassName('small');
const largeEl = document.getElementsByClassName('large')[0];
for (let i=0; i<picEls.length; i++) {
picEls[i].addEventListener('mouseover', hovered);
picEls[i].addEventListener('mouseout', hovered);
}
function hovered(event) {
const bg = event.target.style.backgroundImage;
this.style.backgroundImage = largeEl.style.backgroundImage;
largeEl.style.backgroundImage = bg;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.pic {
border-style: solid;
border-radius: 50%;
background-size: cover;
}
.large {
width: 40vw;
height: 30vw;
margin: 0 auto 0 auto;
}
.small {
display: inline-block;
width: 20vw;
height: 15vw;
margin: 2vw;
}
<div class="container">
<div class="large pic" style="background-image: linear-gradient(red,yellow);"></div>
<div class="small pic" style="background-image: linear-gradient(red,green);"></div>
<div class="small pic" style="background-image: linear-gradient(green,blue);"></div>
<div class="small pic" style="background-image: linear-gradient(blue,red);"></div>
<div class="small pic" style="background-image: linear-gradient(cyan,yellow);"></div>
<div class="small pic" style="background-image: linear-gradient(yellow,magenta);"></div>
<div class="small pic" style="background-image: linear-gradient(magenta,cyan);"></div>
<div class="small pic" style="background-image: linear-gradient(cyan,red);"></div>
<div class="small pic" style="background-image: linear-gradient(yellow, green);"></div>
</div>

Pages of my webpage positioned on each other

I am creating a website where the homepage has an automatic image slider, I have this issue where the other pages (service page) overlap and stay right on the home page. I tried fixing this issue setting the homepage to 100vh and the image from the service stays right on top.
I tried removing the absolute positioning on the slider and desc and that disfigured the outlook. I tried forcing the code to work by creating a dummy div and setting a height to push down the service page div and it kinda worked but I want my code as clean as possible, I know someone has a better to deal with this please help out.
I also want the images to be positioned next to each as inline and that is not working.
The three pictures you see on the automatic slider are a separate page and I am trying to set to it below the home page (automatic image slider)
var slideIndex = 0;
var slides = document.getElementsByClassName("mySlides");
showSlides();
function showSlides() {
var slideLength = slides.length;
// Fade in the slide
setTimeout(function(){
if(slideIndex == slideLength) {
slideIndex = 0;
}
slides[slideIndex].classList.add("fadeIn");
}, 10);
//Fade out the SLide
setTimeout(function(){
if(slideIndex == slideLength) {
slideIndex = 0;
}
slides[slideIndex].classList.remove("fadeIn");
}, 3980);
slideIndex++;
setTimeout(showSlides, 4000);
}
.desc-container {
position: absolute;
bottom: 25%;
left: 23%;
}
.desc {
margin: auto;
width: 450px;
height: 250px;
position: relative;
}
.mySlides {
-webkit-transition: all 0.5s linear;
-moz-transition: all 0.5s linear;
-o-transition: all 0.5s linear;
transition: all 0.5s linear;
position: absolute;
top:0;
left:0;
opacity: 0;
}
/*----------------------------------------------------
#Home page
-----------------------------------------------------*/
.main{
width:calc(100%- 300px);
}
.homePage {
overflow: auto;
}
.menu {
text-align: center;
}
.slideshow-container {
margin: auto;
}
.fadeIn {
opacity:1;
}
/*----------------------------------------------------
#Service Page
-----------------------------------------------------*/
div .services {
width:100%;
overflow: auto;
}
.column {
float: left;
width: 350px;
height: auto;
overflow-x: hidden;
padding:10px;
margin-left: 300px;
}
.row {
}
.row:after {
content: "";
clear: both;
display: table;
}
<div class="main">
<section id="homePage">
<div class="homePage">
<div class="slideshow-container">
<div class="mySlides">
<img src="Images/eventbg1.jpg" style="width:100%">
<div class="desc-container">
<div class="desc p30 whitebg">
<h6 class="greytxt">Luxury Events</h6>
<h1 class="blacktxt">WE CREATE BEAUTIFUL EVENTS</h1>
<p class="greytxt">Join us for a “No Question too Small, Large or Outrageous” Chat about All things Bridal! This is your chance to have two industry experts answer your queries on any topic that is keeping you up at night.</p>
</div>
</div>
</div>
<div class="mySlides">
<img src="Images/restaurantbg1.jpg" style="width:100%">
<div class="desc-container">
<div class="desc p30 whitebg">
<h6 class="greytxt">Creating Impact</h6>
<h1 class="blacktxt"> STRATEGY AND SALES</h1>
<p class="greytxt"></p>
</div>
</div>
</div>
<div class="mySlides">
<img src="Images/memorialbg1.jpg" style="width:100%">
<div class="desc-container">
<div class="desc p30 whitebg">
<h6 class="greytxt">Lasting Memories</h6>
<h1 class="blacktxt">SERVING WITH LOVE</h1>
<p class="greytxt"></p>
</div>
</div>
</div>
</div>
</div>
<div>
<span class="dot"></span>
<span class="dot"></span>
<span class="dot"></span>
</div>
</section>
<section>
<div class="services">
<div class="row">
<div class="column">
<img src="Images/eventbg2.jpg" alt="" style="width:100%">
</div>
<div class="column">
<img src="Images/restaurantbg2.jpg" alt="" style="width:100%">
</div>
<div class="column">
<img src="Images/memorialbg2.jpg" alt="" style="width:100%">
</div>
</div>
</div>
</section>
</div>

Hover over image to add effect, hover again to make it dissapear

I have a few images displayed. First, they are all black grayscaled and I want to add effects so that when you hover over an image its grayscale becomes 0 and stays 0 until I hover over that image again.
I saw that a few people use javascript to add a class but I am not sure how to revert back to grayscale 100% after the first hover.
<div id="photos">
<div class="images">
<img src="/photographs/clouds.jpg" />
</div>
<div class="images">
<img src="/photographs/DogPrint.jpg" />
</div>
<div class="images">
<img src="/photographs/euro.jpg" />
</div>
<div class="images">
<img src="/photographs/FireHead.jpg" />
</div>
<div class="images">
<img src="/photographs/wasabi.jpg" />
</div>
<div class="images">
<img src="/photographs/sam.jpg" />
</div>
<div class="images">
<img src="/photographs/roli.jpg" />
</div>
</div>
img {
width: 100%;
filter: grayscale(100%);
border-radius: 2px;
transition: all 0.25s ease-in-out;
}
#photos {
columns: 5 200px;
column-gap: 1.5rem;
width: 90%;
margin-top: 200px;
margin-left: 200px;
}
I just added a little bit of Javascript to make it work, and even a transition.
JSFiddle - https://jsfiddle.net/8850s/oj5rcv8n/
HTML -
<div id="photos">
<div class="images">
<img src="/photographs/clouds.jpg" />
<div>
Text
</div>
</div>
<div class="images">
<img src="/photographs/DogPrint.jpg" />
<div>
Text
</div>
</div>
<div class="images">
<img src="/photographs/euro.jpg" />
<div>
Text
</div>
</div>
<div class="images">
<img src="/photographs/FireHead.jpg" />
<div>
Text
</div>
</div>
<div class="images">
<img src="/photographs/wasabi.jpg" />
<div>
Text
</div>
</div>
<div class="images">
<img src="/photographs/sam.jpg" />
<div>
Text
</div>
</div>
<div class="images">
<img src="/photographs/roli.jpg" />
<div>
Text
</div>
</div>
</div>
JS -
var images = document.querySelectorAll('#photos > .images > img')
for (var i = 0; i < images.length; i ++) {
images[i].style.transitionDuration = '0.1s'
images[i].nextElementSibling.style.transitionDuration = '0.1s'
images[i].nextElementSibling.style.opacity = '0'
images[i].addEventListener('mouseenter', function() {
if (this.style.filter === "grayscale(100%)") {
this.style.filter = "grayscale(0%)";
this.nextElementSibling.style.opacity = "0";
} else {
this.style.filter = "grayscale(100%)";
this.nextElementSibling.style.opacity = "1";
}
})
}
CSS -
img {
width: 100%;
filter: grayscale(100%);
border-radius: 2px;
transition: all 0.25s ease-in-out;
}
#photos {
columns: 5 200px;
column-gap: 1.5rem;
width: 90%;
margin-top: 200px;
margin-left: 200px;
}
You can attach a 'mouseover' event listener on each image element.
When this event is triggered you can just add or remove a className using element.classList.toggle('classname').
Live example
<body>
<div id="photos">
<div class="images">
<img
class="grayscale-image"
src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/b6/Image_created_with_a_mobile_phone.png/500px-Image_created_with_a_mobile_phone.png"
/>
</div>
</div>
</body>
<script>
const imgs = document.getElementsByClassName("grayscale-image");
for (let i in imgs) {
const currentImg = imgs[i];
currentImg.addEventListener("mouseover", e => {
currentImg.classList.toggle("image-color");
});
}
</script>
img {
width: 100%;
filter: grayscale(100%);
border-radius: 2px;
transition: all 0.25s ease-in-out;
}
#photos {
columns: 5 200px;
column-gap: 1.5rem;
width: 90%;
margin-top: 200px;
}
.image-color {
filter: grayscale(0%);
}

Categories

Resources