Animation when changing divs - javascript

I'm struggling on changing gallery sets animation.
So far I've reached just a simple "fade" effect using opacity in #keyframes applied on .gallery-set.
I know it's a very common thing, but I can't find anything that would help me and make me understand how it works. I don't want any plugins or libraries for it. I just want to learn how to do that in pure html, css and js.
My goal is : When clicking on the menu, gallery set will change - current will slide to left and fadeout and new one will slide from right to place where previous were. (Hope I've explained it well :D ).
I've tried to add in #keyframes galleryfade transform : translateX, but I don't know what to do next.
I'm new to these things, learning JS at home on my own, so every bit of advise would be helpful to me. Thanks to everybody who will spend time on this.
CodePen link : https://codepen.io/pinnci/pen/YzydPdq
let menuLinks = document.querySelectorAll('.work-menu li a');
let gallerySets = document.querySelectorAll('.gallery-set');
gallerySets.forEach(set => {
set.classList.add('displayNone');
});
function showGallery(id){
gallerySets.forEach(set => {
if(set.id == id){
set.classList.remove('displayNone');
set.style.opacity = '1';
}else{
set.classList.add('displayNone');
set.style.opacity = '0';
}
});
menuLinks.forEach(link => {
if(link.id == id){
link.classList.add('selected');
}else{
link.classList.remove('selected');
}
});
}
menuLinks.forEach(item => {
item.addEventListener('click',function(e){
e.preventDefault();
showGallery(item.id);
});
});
showGallery('healthcare');
body{
margin: 0;
padding:0;
font-family: 'Roboto', sans-serif;
font-size: 100%;
}
.container{
width: 90%;
margin: 0 auto;
text-align: center;
}
.o-hidden{
overflow: hidden;
}
img{
max-width: 100%;
height: auto;
}
.works{
padding:1em 0 3em 0 ;
}
.works h2{
font-size: 2em;
}
.work-menu ul{
list-style: none;
padding-left: 0;
}
.work-menu a{
text-decoration: none;
color:black;
transition: 0.1s;
padding: 0.2em 0 ;
}
.selected{
border-bottom: 0.1em solid #f3bb28;
}
.work-menu li {
display: inline-block;
margin: 1em;
}
.work-menu a:hover{
color:#f3bb28;
}
.gallery-set img{
margin: 0.5em;
transition: 0.2s ease-in-out;
width: 20%;
}
.gallery-set img:hover{
transform: scale(1.03);
cursor: pointer;
}
/*GALLERY SETS*/
.displayNone{
display: none;
transition: opacity 1s ease-in-out;
}
.gallery-set{
animation: galleryFade .4s ease-in-out;
}
#keyframes galleryFade{
from{
opacity: 0.3;
}
to{
opacity: 1;
}
}
<div class="works">
<div class="container">
<h2>RECENT WORKS</h2>
<div class="work-menu">
<ul>
<li>Healthcare</li>
<li>Education</li>
<li>Goverment</li>
<li>Commercial</li>
</ul>
</div>
<div class="gallery-set" id="healthcare">
<img src="https://cdn3.wpbeginner.com/wp-content/uploads/2020/03/ultimate-small-business-resource-coronavirus.png" id="1">
<img src="https://cdn3.wpbeginner.com/wp-content/uploads/2020/03/ultimate-small-business-resource-coronavirus.png" id="2">
<img src="https://cdn3.wpbeginner.com/wp-content/uploads/2020/03/ultimate-small-business-resource-coronavirus.png" id="3">
<img src="https://cdn3.wpbeginner.com/wp-content/uploads/2020/03/ultimate-small-business-resource-coronavirus.png" id="4">
<img src="https://cdn3.wpbeginner.com/wp-content/uploads/2020/03/ultimate-small-business-resource-coronavirus.png" id="5">
<img src="https://cdn3.wpbeginner.com/wp-content/uploads/2020/03/ultimate-small-business-resource-coronavirus.png" id="6">
<img src="https://cdn3.wpbeginner.com/wp-content/uploads/2020/03/ultimate-small-business-resource-coronavirus.png" id="7">
<img src="https://cdn3.wpbeginner.com/wp-content/uploads/2020/03/ultimate-small-business-resource-coronavirus.png" id="8">
</div>
<div class="gallery-set" id="education">
<img src="https://blog.mares.com/wp-content/uploads/2018/09/photo-by-Janez-Kranjc-3-Large-550x320.jpg" id="9">
<img src="https://blog.mares.com/wp-content/uploads/2018/09/photo-by-Janez-Kranjc-3-Large-550x320.jpg" id="10">
<img src="https://blog.mares.com/wp-content/uploads/2018/09/photo-by-Janez-Kranjc-3-Large-550x320.jpg" id="11">
<img src="https://blog.mares.com/wp-content/uploads/2018/09/photo-by-Janez-Kranjc-3-Large-550x320.jpg" id="12">
<img src="https://blog.mares.com/wp-content/uploads/2018/09/photo-by-Janez-Kranjc-3-Large-550x320.jpg" id="13">
<img src="https://blog.mares.com/wp-content/uploads/2018/09/photo-by-Janez-Kranjc-3-Large-550x320.jpg" id="14">
<img src="https://blog.mares.com/wp-content/uploads/2018/09/photo-by-Janez-Kranjc-3-Large-550x320.jpg" id="15">
<img src="https://blog.mares.com/wp-content/uploads/2018/09/photo-by-Janez-Kranjc-3-Large-550x320.jpg" id="16">
</div>
<div class="gallery-set" id="goverment">
<img src="https://bsscommerce.com/blog/wp-content/uploads/2015/06/how-to-customize-order-id-550x320.png" id="17">
<img src="https://bsscommerce.com/blog/wp-content/uploads/2015/06/how-to-customize-order-id-550x320.png" id="18">
<img src="https://bsscommerce.com/blog/wp-content/uploads/2015/06/how-to-customize-order-id-550x320.png" id="19">
<img src="https://bsscommerce.com/blog/wp-content/uploads/2015/06/how-to-customize-order-id-550x320.png" id="20">
<img src="https://bsscommerce.com/blog/wp-content/uploads/2015/06/how-to-customize-order-id-550x320.png" id="21">
<img src="https://bsscommerce.com/blog/wp-content/uploads/2015/06/how-to-customize-order-id-550x320.png" id="22">
<img src="https://bsscommerce.com/blog/wp-content/uploads/2015/06/how-to-customize-order-id-550x320.png" id="23">
<img src="https://bsscommerce.com/blog/wp-content/uploads/2015/06/how-to-customize-order-id-550x320.png" id="24">
</div>
<div class="gallery-set" id="commercial">
<img src="https://lh3.googleusercontent.com/proxy/2GOR8jFYc-c4ueS2RnoQdshYBKcSa8Vt2UsL3VMqiFbjCqn1y0Xl_l4RalzP-rYmGYyq3oKJp_pjzcyfvG_oAowHWWi2fAxFmrp8ccbzlCSDsRxOfUtuOSpqHbepUoqSloxWZVWsKMDrmkWaLV09utnR2ACHfrQ0FS1yeSKkQNevmk8g" id="25">
<img src="https://lh3.googleusercontent.com/proxy/2GOR8jFYc-c4ueS2RnoQdshYBKcSa8Vt2UsL3VMqiFbjCqn1y0Xl_l4RalzP-rYmGYyq3oKJp_pjzcyfvG_oAowHWWi2fAxFmrp8ccbzlCSDsRxOfUtuOSpqHbepUoqSloxWZVWsKMDrmkWaLV09utnR2ACHfrQ0FS1yeSKkQNevmk8g" id="26">
<img src="https://lh3.googleusercontent.com/proxy/2GOR8jFYc-c4ueS2RnoQdshYBKcSa8Vt2UsL3VMqiFbjCqn1y0Xl_l4RalzP-rYmGYyq3oKJp_pjzcyfvG_oAowHWWi2fAxFmrp8ccbzlCSDsRxOfUtuOSpqHbepUoqSloxWZVWsKMDrmkWaLV09utnR2ACHfrQ0FS1yeSKkQNevmk8g" id="27">
<img src="https://lh3.googleusercontent.com/proxy/2GOR8jFYc-c4ueS2RnoQdshYBKcSa8Vt2UsL3VMqiFbjCqn1y0Xl_l4RalzP-rYmGYyq3oKJp_pjzcyfvG_oAowHWWi2fAxFmrp8ccbzlCSDsRxOfUtuOSpqHbepUoqSloxWZVWsKMDrmkWaLV09utnR2ACHfrQ0FS1yeSKkQNevmk8g" id="28">
<img src="https://lh3.googleusercontent.com/proxy/2GOR8jFYc-c4ueS2RnoQdshYBKcSa8Vt2UsL3VMqiFbjCqn1y0Xl_l4RalzP-rYmGYyq3oKJp_pjzcyfvG_oAowHWWi2fAxFmrp8ccbzlCSDsRxOfUtuOSpqHbepUoqSloxWZVWsKMDrmkWaLV09utnR2ACHfrQ0FS1yeSKkQNevmk8g" id="29">
<img src="https://lh3.googleusercontent.com/proxy/2GOR8jFYc-c4ueS2RnoQdshYBKcSa8Vt2UsL3VMqiFbjCqn1y0Xl_l4RalzP-rYmGYyq3oKJp_pjzcyfvG_oAowHWWi2fAxFmrp8ccbzlCSDsRxOfUtuOSpqHbepUoqSloxWZVWsKMDrmkWaLV09utnR2ACHfrQ0FS1yeSKkQNevmk8g" id="30">
<img src="https://lh3.googleusercontent.com/proxy/2GOR8jFYc-c4ueS2RnoQdshYBKcSa8Vt2UsL3VMqiFbjCqn1y0Xl_l4RalzP-rYmGYyq3oKJp_pjzcyfvG_oAowHWWi2fAxFmrp8ccbzlCSDsRxOfUtuOSpqHbepUoqSloxWZVWsKMDrmkWaLV09utnR2ACHfrQ0FS1yeSKkQNevmk8g" id="31">
<img src="https://lh3.googleusercontent.com/proxy/2GOR8jFYc-c4ueS2RnoQdshYBKcSa8Vt2UsL3VMqiFbjCqn1y0Xl_l4RalzP-rYmGYyq3oKJp_pjzcyfvG_oAowHWWi2fAxFmrp8ccbzlCSDsRxOfUtuOSpqHbepUoqSloxWZVWsKMDrmkWaLV09utnR2ACHfrQ0FS1yeSKkQNevmk8g" id="32">
</div>
</div>
</div>

I modified the code in order to execute the second part and show you the code so that you can modify it to your liking by adding other animations ;)
The main change was made by changing the animation with a lateral movement and 0 opacity as it already was.
let menuLinks = document.querySelectorAll('.work-menu li a');
let gallerySets = document.querySelectorAll('.gallery-set');
gallerySets.forEach(set => {
set.classList.add('displayNone');
});
function showGallery(id){
gallerySets.forEach(set => {
if(set.id == id){
set.classList.remove('displayNone');
set.style.opacity = '1';
}else{
set.classList.add('displayNone');
set.style.opacity = '0';
}
});
menuLinks.forEach(link => {
if(link.id == id){
link.classList.add('selected');
}else{
link.classList.remove('selected');
}
});
}
menuLinks.forEach(item => {
item.addEventListener('click',function(e){
e.preventDefault();
showGallery(item.id);
});
});
showGallery('healthcare');
body{
margin: 0;
padding:0;
font-family: 'Roboto', sans-serif;
font-size: 100%;
}
.container{
width: 90%;
margin: 0 auto;
text-align: center;
}
.o-hidden{
overflow: hidden;
}
img{
max-width: 100%;
height: auto;
}
.works{
padding:1em 0 3em 0 ;
}
.works h2{
font-size: 2em;
}
.work-menu ul{
list-style: none;
padding-left: 0;
}
.work-menu a{
text-decoration: none;
color:black;
transition: 0.1s;
padding: 0.2em 0 ;
}
.selected{
border-bottom: 0.1em solid #f3bb28;
}
.work-menu li {
display: inline-block;
margin: 1em;
}
.work-menu a:hover{
color:#f3bb28;
}
.gallery-set img{
margin: 0.5em;
transition: 0.2s ease-in-out;
width: 20%;
}
.gallery-set img:hover{
transform: scale(1.03);
cursor: pointer;
}
/*GALLERY SETS*/
.displayNone{
display: none;
transition: opacity 1s ease-in-out;
}
.gallery-set{
animation: galleryFade .4s ease-in-out;
}
#keyframes galleryFade{
from{
transform: translateX(450px);
opacity: 0;
}
to{
opacity: 1;
}
}
<div class="works">
<div class="container">
<h2>RECENT WORKS</h2>
<div class="work-menu">
<ul>
<li>Healthcare</li>
<li>Education</li>
<li>Goverment</li>
<li>Commercial</li>
</ul>
</div>
<div class="gallery-set" id="healthcare">
<img src="https://cdn3.wpbeginner.com/wp-content/uploads/2020/03/ultimate-small-business-resource-coronavirus.png" id="1">
<img src="https://cdn3.wpbeginner.com/wp-content/uploads/2020/03/ultimate-small-business-resource-coronavirus.png" id="2">
<img src="https://cdn3.wpbeginner.com/wp-content/uploads/2020/03/ultimate-small-business-resource-coronavirus.png" id="3">
<img src="https://cdn3.wpbeginner.com/wp-content/uploads/2020/03/ultimate-small-business-resource-coronavirus.png" id="4">
<img src="https://cdn3.wpbeginner.com/wp-content/uploads/2020/03/ultimate-small-business-resource-coronavirus.png" id="5">
<img src="https://cdn3.wpbeginner.com/wp-content/uploads/2020/03/ultimate-small-business-resource-coronavirus.png" id="6">
<img src="https://cdn3.wpbeginner.com/wp-content/uploads/2020/03/ultimate-small-business-resource-coronavirus.png" id="7">
<img src="https://cdn3.wpbeginner.com/wp-content/uploads/2020/03/ultimate-small-business-resource-coronavirus.png" id="8">
</div>
<div class="gallery-set" id="education">
<img src="https://blog.mares.com/wp-content/uploads/2018/09/photo-by-Janez-Kranjc-3-Large-550x320.jpg" id="9">
<img src="https://blog.mares.com/wp-content/uploads/2018/09/photo-by-Janez-Kranjc-3-Large-550x320.jpg" id="10">
<img src="https://blog.mares.com/wp-content/uploads/2018/09/photo-by-Janez-Kranjc-3-Large-550x320.jpg" id="11">
<img src="https://blog.mares.com/wp-content/uploads/2018/09/photo-by-Janez-Kranjc-3-Large-550x320.jpg" id="12">
<img src="https://blog.mares.com/wp-content/uploads/2018/09/photo-by-Janez-Kranjc-3-Large-550x320.jpg" id="13">
<img src="https://blog.mares.com/wp-content/uploads/2018/09/photo-by-Janez-Kranjc-3-Large-550x320.jpg" id="14">
<img src="https://blog.mares.com/wp-content/uploads/2018/09/photo-by-Janez-Kranjc-3-Large-550x320.jpg" id="15">
<img src="https://blog.mares.com/wp-content/uploads/2018/09/photo-by-Janez-Kranjc-3-Large-550x320.jpg" id="16">
</div>
<div class="gallery-set" id="goverment">
<img src="https://bsscommerce.com/blog/wp-content/uploads/2015/06/how-to-customize-order-id-550x320.png" id="17">
<img src="https://bsscommerce.com/blog/wp-content/uploads/2015/06/how-to-customize-order-id-550x320.png" id="18">
<img src="https://bsscommerce.com/blog/wp-content/uploads/2015/06/how-to-customize-order-id-550x320.png" id="19">
<img src="https://bsscommerce.com/blog/wp-content/uploads/2015/06/how-to-customize-order-id-550x320.png" id="20">
<img src="https://bsscommerce.com/blog/wp-content/uploads/2015/06/how-to-customize-order-id-550x320.png" id="21">
<img src="https://bsscommerce.com/blog/wp-content/uploads/2015/06/how-to-customize-order-id-550x320.png" id="22">
<img src="https://bsscommerce.com/blog/wp-content/uploads/2015/06/how-to-customize-order-id-550x320.png" id="23">
<img src="https://bsscommerce.com/blog/wp-content/uploads/2015/06/how-to-customize-order-id-550x320.png" id="24">
</div>
<div class="gallery-set" id="commercial">
<img src="https://lh3.googleusercontent.com/proxy/2GOR8jFYc-c4ueS2RnoQdshYBKcSa8Vt2UsL3VMqiFbjCqn1y0Xl_l4RalzP-rYmGYyq3oKJp_pjzcyfvG_oAowHWWi2fAxFmrp8ccbzlCSDsRxOfUtuOSpqHbepUoqSloxWZVWsKMDrmkWaLV09utnR2ACHfrQ0FS1yeSKkQNevmk8g" id="25">
<img src="https://lh3.googleusercontent.com/proxy/2GOR8jFYc-c4ueS2RnoQdshYBKcSa8Vt2UsL3VMqiFbjCqn1y0Xl_l4RalzP-rYmGYyq3oKJp_pjzcyfvG_oAowHWWi2fAxFmrp8ccbzlCSDsRxOfUtuOSpqHbepUoqSloxWZVWsKMDrmkWaLV09utnR2ACHfrQ0FS1yeSKkQNevmk8g" id="26">
<img src="https://lh3.googleusercontent.com/proxy/2GOR8jFYc-c4ueS2RnoQdshYBKcSa8Vt2UsL3VMqiFbjCqn1y0Xl_l4RalzP-rYmGYyq3oKJp_pjzcyfvG_oAowHWWi2fAxFmrp8ccbzlCSDsRxOfUtuOSpqHbepUoqSloxWZVWsKMDrmkWaLV09utnR2ACHfrQ0FS1yeSKkQNevmk8g" id="27">
<img src="https://lh3.googleusercontent.com/proxy/2GOR8jFYc-c4ueS2RnoQdshYBKcSa8Vt2UsL3VMqiFbjCqn1y0Xl_l4RalzP-rYmGYyq3oKJp_pjzcyfvG_oAowHWWi2fAxFmrp8ccbzlCSDsRxOfUtuOSpqHbepUoqSloxWZVWsKMDrmkWaLV09utnR2ACHfrQ0FS1yeSKkQNevmk8g" id="28">
<img src="https://lh3.googleusercontent.com/proxy/2GOR8jFYc-c4ueS2RnoQdshYBKcSa8Vt2UsL3VMqiFbjCqn1y0Xl_l4RalzP-rYmGYyq3oKJp_pjzcyfvG_oAowHWWi2fAxFmrp8ccbzlCSDsRxOfUtuOSpqHbepUoqSloxWZVWsKMDrmkWaLV09utnR2ACHfrQ0FS1yeSKkQNevmk8g" id="29">
<img src="https://lh3.googleusercontent.com/proxy/2GOR8jFYc-c4ueS2RnoQdshYBKcSa8Vt2UsL3VMqiFbjCqn1y0Xl_l4RalzP-rYmGYyq3oKJp_pjzcyfvG_oAowHWWi2fAxFmrp8ccbzlCSDsRxOfUtuOSpqHbepUoqSloxWZVWsKMDrmkWaLV09utnR2ACHfrQ0FS1yeSKkQNevmk8g" id="30">
<img src="https://lh3.googleusercontent.com/proxy/2GOR8jFYc-c4ueS2RnoQdshYBKcSa8Vt2UsL3VMqiFbjCqn1y0Xl_l4RalzP-rYmGYyq3oKJp_pjzcyfvG_oAowHWWi2fAxFmrp8ccbzlCSDsRxOfUtuOSpqHbepUoqSloxWZVWsKMDrmkWaLV09utnR2ACHfrQ0FS1yeSKkQNevmk8g" id="31">
<img src="https://lh3.googleusercontent.com/proxy/2GOR8jFYc-c4ueS2RnoQdshYBKcSa8Vt2UsL3VMqiFbjCqn1y0Xl_l4RalzP-rYmGYyq3oKJp_pjzcyfvG_oAowHWWi2fAxFmrp8ccbzlCSDsRxOfUtuOSpqHbepUoqSloxWZVWsKMDrmkWaLV09utnR2ACHfrQ0FS1yeSKkQNevmk8g" id="32">
</div>
</div>
</div>

Related

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.

Dynamic Image Modal with active state

I have image folders that expand when clicked on to view the whole album. I've been able to make the first album work, but I cant seem to get the active state to carry over to the other albums.
My JavaScript knowledge is quite limited so I'm unsure where I'm going wrong with this, but the goal here is to have a grid showcasing thumbnails for different image collections and when a collection is clicked on, the modal will popup and dynamically display the collection of images that was clicked on.
const modal = document.querySelector(".modal");
const buttons = document.querySelectorAll("[data-carousel-button]");
const carousel = document.querySelector(".carousel");
const closeButton = document.querySelector(".close");
const gridImages = document.querySelectorAll(".grid-img img");
const slide = document.querySelector(".slide");
const blueLotusFineArt = document.querySelector(".one");
const blueLotusModal = document.querySelector(".blue-lotus");
const greenWomenFineArt = document.querySelector(".two");
const greenWomenModal = document.querySelector(".green-women");
buttons.forEach((button) => {
button.addEventListener("click", () => {
const offset = button.dataset.carouselButton === "next" ? 1 : -1;
const slides = button
.closest("[data-carousel]")
.querySelector("[data-slides]");
const activeSlide = slides.querySelector("[data-active]");
let newIndex = [...slides.children].indexOf(activeSlide) + offset;
if (newIndex < 0) newIndex = slides.children.length - 1;
if (newIndex >= slides.children.length) newIndex = 0;
slides.children[newIndex].dataset.active = true;
delete activeSlide.dataset.active;
});
});
// select image from grid
// only display selected gallery
gridImages.forEach((gridImage) => {
gridImage.addEventListener("click", () => {
modal.classList.add("open");
closeButton.classList.add("open");
carousel.style.display = "block";
});
});
blueLotusFineArt.addEventListener("click", () => {
blueLotusModal.style.display = "block";
});
greenWomenFineArt.addEventListener("click", () => {
greenWomenModal.style.display = "block";
slide.style.opacity = "1";
});
closeButton.addEventListener("click", () => {
carousel.style.display = "none";
closeButton.classList.remove("open");
modal.classList.remove("open");
blueLotusModal.style.display = "none";
greenWomenModal.style.display = "none";
});
section {
min-height: 100vh;
}
img,
picture {
max-width: 100%;
display: block;
}
.flex {
display: flex;
gap: 4rem;
}
#fine-art {
position: relative;
z-index: 2;
background-color: var(--clr-primary);
min-height: auto;
}
.container {
padding-inline: 4em;
margin-inline: auto;
max-width: 120rem;
}
.wrapper {
grid-template-columns: repeat(3, 1fr);
grid-auto-rows: minmax(100px, auto);
gap: 2rem;
padding: 4rem 0;
}
.grid {
display: grid;
gap: var(--gap, 1rem);
}
.modal {
opacity: 0;
position: fixed;
z-index: 10;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto;
background-color: rgba(43, 43, 43, 0.5);
transition: all 300ms ease-in-out;
pointer-events: none;
backdrop-filter: blur(10px);
display: grid;
place-items: center;
}
.modal.open {
opacity: 1;
pointer-events: all;
}
.close {
position: fixed;
right: 32px;
top: 50px;
width: 50px;
height: 32px;
opacity: 0;
z-index: 20;
pointer-events: none;
transition: all 300ms ease-in-out;
cursor: pointer;
}
.close.open {
opacity: 1;
pointer-events: all;
}
.close:before,
.close:after {
position: absolute;
left: 15px;
content: " ";
height: 50px;
width: 5px;
background-color: var(--clr-primary);
}
.close:before {
transform: rotate(45deg);
}
.close:after {
transform: rotate(-45deg);
}
.blue-lotus,
.green-women {
display: none;
pointer-events: none;
}
.carousel {
width: 100vw;
height: 80vh;
position: absolute;
z-index: 10;
display: none;
}
.slide {
position: absolute;
inset: 0;
opacity: 0;
transition: 200ms opacity ease-in-out;
transition-delay: 200ms;
}
.slide > img {
height: 100%;
object-fit: contain;
object-position: center;
border-radius: 4px;
}
.slide[data-active] {
opacity: 1;
transition-delay: 0ms;
}
.carousel-button {
position: absolute;
background: none;
border: none;
font-size: 4rem;
top: 50%;
z-index: 11;
transform: translateY(-50%);
color: rgba(241, 242, 245, 0.5);
cursor: pointer;
border-radius: 0.25rem;
padding: 0 0.5rem;
background-color: rgba(43, 43, 43, 0.1);
}
.carousel-button:hover,
.carousel-button:focus {
color: rgba(241, 242, 245, 1);
background-color: rgba(43, 43, 43, 0.2);
}
.carousel-button.prev {
left: 1rem;
}
.carousel-button.next {
right: 1rem;
}
<section id="fine-art">
<div class="container fine-art">
<div class="wrapper grid">
<div class="grid-img one">
<img
src="https://source.unsplash.com/random"
alt="Fine Art"
width="450"
height="600"
decoding="async"
loading="lazy"
/>
<p>Blue Lotus</p>
</div>
<div class="grid-img two">
<img
src="https://source.unsplash.com/random"
alt="Fine Art"
width="450"
height="600"
decoding="async"
loading="lazy"
/>
<p>Green Women</p>
</div>
<div class="grid-img three">
<img
src="https://source.unsplash.com/random"
alt="Fine Art"
width="450"
height="600"
decoding="async"
loading="lazy"
/>
<p>Studio</p>
</div>
<div class="grid-img four">
<img
src="https://source.unsplash.com/random"
alt="Fine Art"
width="450"
height="600"
decoding="async"
loading="lazy"
/>
<p>Starlet</p>
</div>
<div class="grid-img five">
<img
src="https://source.unsplash.com/random"
alt="Fine Art"
width="450"
height="600"
decoding="async"
loading="lazy"
/>
<p>Portraits</p>
</div>
<div class="grid-img six">
<img
src="https://source.unsplash.com/random"
alt="Fine Art"
width="450"
height="600"
decoding="async"
loading="lazy"
/>
<p>Chameleon</p>
</div>
<div class="grid-img seven">
<img
src="https://source.unsplash.com/random"
alt="Fine Art"
width="450"
height="600"
decoding="async"
loading="lazy"
/>
<p>De Kelders</p>
</div>
<div class="grid-img eight">
<img
src="https://source.unsplash.com/random"
alt="Fine Art"
width="450"
height="600"
decoding="async"
loading="lazy"
/>
<p>Elementals</p>
</div>
<div class="grid-img nine">
<img
src="https://source.unsplash.com/random"
alt="Fine Art"
width="450"
height="600"
decoding="async"
loading="lazy"
/>
<p>Mosaic</p>
</div>
</div>
</div>
</section>
<a class="close"></a>
<div class="modal">
<div class="carousel" data-carousel>
<button class="carousel-button next" data-carousel-button="next">
⇨
</button>
<button class="carousel-button prev" data-carousel-button="prev">
⇦
</button>
<ul class="blue-lotus" data-slides>
<li class="slide" data-active>
<img
src="https://source.unsplash.com/random"
alt="Blue Lotus 1"
width="2100"
height="1400"
decoding="async"
loading="lazy"
/>
</li>
<li class="slide">
<img
src="https://source.unsplash.com/random"
alt="Blue Lotus 2"
width="2100"
height="1400"
decoding="async"
loading="lazy"
/>
</li>
<li class="slide">
<img
src="https://source.unsplash.com/random"
alt="Blue Lotus 3"
width="2100"
height="1400"
decoding="async"
loading="lazy"
/>
</li>
<li class="slide">
<img
src="https://source.unsplash.com/random"
alt="Blue Lotus 4"
width="2100"
height="1400"
decoding="async"
loading="lazy"
/>
</li>
<li class="slide">
<img
src="https://source.unsplash.com/random"
alt="Blue Lotus 5"
width="2100"
height="1400"
decoding="async"
loading="lazy"
/>
</li>
<li class="slide">
<img
src="https://source.unsplash.com/random"
alt="Blue Lotus 6"
width="2100"
height="1400"
decoding="async"
loading="lazy"
/>
</li>
</ul>
<ul class="green-women" data-slides>
<li class="slide" data-active>
<img
src="https://source.unsplash.com/random"
alt="Green Women 1"
width="2100"
height="1400"
decoding="async"
loading="lazy"
/>
</li>
<li class="slide">
<img
src="https://source.unsplash.com/random"
alt="Green Women 2"
width="2100"
height="1400"
decoding="async"
loading="lazy"
/>
</li>
<li class="slide">
<img
src="https://source.unsplash.com/random"
alt="Green Women 3"
width="2100"
height="1400"
decoding="async"
loading="lazy"
/>
</li>
</ul>
</div>
</div>

Image on back card not showing when flipped, JS memory game

When the user clicks on one of playing cards in this memory game, it fires off a flipCard function that transforms the card along the Y axis by 180deg, essentially showing the rotating the image that is hidden on the back and making it visible in the front. My eventListener and the flipCard function is working but there's a problem with the CSS because the back image won't appear. Despite it only supposed to rotate 180deg, the image on the front rotates and still appears on the front after flipCard is invoked. Can someone take a look at my CSS and suggest how to make the back image appear?
const cards = document.querySelectorAll('.card');
function flipCard(){
this.classList.toggle('flip');
}
cards.forEach(card => card.addEventListener('click', flipCard));
*{
margin: 0px;
padding: 0px;
box-sizing: border-box;
font-family: 'Bungee Shade', cursive;
background-color: cornflowerblue;
}
body{
height: 100vh;
text-align: center;
font-size: 40px;
overflow: hidden;
}
h1{
color: black
}
h1:hover{
color:blue;
}
.card{
display: inline-block;
position: relative;
transform: scale(1);
transition: transform .5s;
width: 130px;
height: 130px;
background-color: black;
border: 5px double #000000;
border-radius: 10px;
cursor: pointer;
margin: auto;
perspective: 500px;
transition: transform 500ms ease-in-out;
}
.card.flip {
transform: rotateY(-180deg);
}
.card-back{
position: absolute;
width: 100%;
height: 100%;
backface-visibility: hidden;
border-radius: 10px;
background-color: black;
transform: rotateY(180deg);
}
/*
.card .card-back,
.card .card-front{
transition: transform 300ms ease-in;
}
.card-front, .card-back{
position: absolute;
justify-content: center;
align-items: center;
display: flex;
backface-visibility: hidden;
}
*/
.overlay{
font-size: 20px;
visibility: hidden;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Bungee+Shade&display=swap" rel="stylesheet">
<link rel="stylesheet" href="index.css">
<title></title>
</head>
<body>
<h1>Memory Game</h1>
<section class="gameboard">
<div class="row">
<div class="card" id = "monster1">
<img class="card-front" img src="logo.png" height="120px" width="120px">
<img class="card-back" type="1" img src="monster1.png">
</div>
<div class="card" id = "monster8">
<img class="card-front" img src="logo.png" height="120px" width="120px">
<img class="card-back" type="2" img src="monster8.png">
</div>
<div class="card" id = "monster3">
<img class="card-front" img src="logo.png" height="120px" width="120px">
<img class="card-back" type="3" img src="monster3.png">
</div>
<div class="card" id = "monster5">
<img class="card-front" img src="logo.png" height="120px" width="120px">
<img class="card-back" type="5" img src="monster5.jpg">
</div>
</div>
<div class="row">
<div class="card" id = "monster6" >
<img class="card-front" img src="logo.png" height="120px" width="120px">
<img class="card-back" type="6" img src="monster6.png">
</div>
<div class="card" id = "monster4">
<img class="card-front" img src="logo.png" height="120px" width="120px">
<img class="card-back" type="4" img src="monster4.jpg">
</div>
<div class="card" id = "monster8">
<img class="card-front" img src="logo.png" height="120px" width="120px">
<img class="card-back" type="2" img src="monster8.png">
</div>
<div class="card" id = "monster1">
<img class="card-front" img src="logo.png" height="120px" width="120px">
<img class="card-back" type="1" img src="monster1.png">
</div>
</div>
<div class="row">
<div class="card" id = "monster3">
<img class="card-front" img src="logo.png" height="120px" width="120px">
<img class="card-back" type="3" img src="monster3.png">
</div>
<div class="card" id = "monster5">
<img class="card-front" img src="logo.png" height="120px" width="120px">
<img class="card-back" type="5" img src="monster5.jpg">
</div>
<div class="card" id = "monster4">
<img class="card-front" img src="logo.png" height="120px" width="120px">
<img class="card-back" type="4" img src="monster4.jpg">
</div>
<div class="card" id = "monster6">
<img class="card-front" img src="logo.png" height="120px" width="120px">
<img class="card-back" type="6" img src="monster6.png">
</div>
</div>
</section>
<div class="overlay">
<h1>Great job! 🥳 </h1>
</div>
<script src="index.js"></script>
</body>
</html>

How to get the images to be the same size using Isotope JS

I am using Isotope JS and I am trying to get an evenly spaced, proportional gallery layout but I am not sure what is wrong. My code isn't cooperating with isotope. I would be very grateful if someone could help me figure out what I am doing wrong.
I created a codepen if that would help as well: https://codepen.io/jaytb95/pen/vYxMGqP
$(document).ready(function() {
$grid = $('.grid').isotope({
filter: '*',
itemSelector: '.grid-item',
layoutMode: 'fitRows',
percentPosition: true
});
$filters = $('.list');
$filters.click(function() {
$value = $(this).attr('data-filter');
if ($value == 'all') {
$grid.isotope({ filter: '*' });
} else {
$grid.isotope({ filter: '.' + $value });
}
});
});
ul {
display: flex;
list-style: none;
justify-content: center;
margin-top: 25px;
}
ul > li {
margin-left: 15px;
cursor: pointer;
padding: 0.5rem 1rem;
background-color: crimson;
color: white;
font-family: 'Calibri',sans-serif;
}
.container {
max-width: 90%;
margin: 0 auto;
}
.grid {
columns: 4 25vh;
}
.grid-item img {
object-fit: cover;
width: 100%;
height: auto;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://unpkg.com/isotope-layout#3.0.6/dist/isotope.pkgd.min.js"></script>
<ul>
<li class="list" data-filter="all">All</li>
<li class="list" data-filter="phone">Phone</li>
<li class="list" data-filter="camera">Camera</li>
<li class="list" data-filter="watch">Watch</li>
</ul>
<div class="container">
<div class="grid">
<div class="grid-item phone">
<img src="https://picsum.photos/500/300" alt="" />
</div>
<div class="grid-item camera">
<img src="https://picsum.photos/400/200" alt="" />
</div>
<div class="grid-item watch">
<img src="https://picsum.photos/500/300" alt="" />
</div>
<div class="grid-item camera">
<img src="https://picsum.photos/400/200" alt="" />
</div>
<div class="grid-item watch">
<img src="https://picsum.photos/500/300" alt="" />
</div>
<div class="grid-item camera">
<img src="https://picsum.photos/400/200" alt="" />
</div>
<div class="grid-item watch">
<img src="https://picsum.photos/500/300" alt="" />
</div>
</div>
</div>
You should initialize Isotope after all the images have loaded. This means that you also have to include the imagesLoaded library in your code.
Also, to make the images proportional and evenly spaced, set the width of each .grid-item class to 50%, set the width of each image to calc(100% - 0.25rem), and change the layout mode to masonry. Your "image gallery" should work just fine after this:
$(document).ready(function() {
$grid = $(".grid").imagesLoaded(function() {
$grid.isotope({
filter: "*",
itemSelector: ".grid-item",
layoutMode: "masonry",
percentPosition: true
});
});
$filters = $(".list");
$filters.click(function() {
$value = $(this).attr("data-filter");
if ($value == "all") {
$grid.imagesLoaded(function() {
$grid.isotope({ filter: "*" });
});
} else {
$grid.imagesLoaded(function() {
$grid.isotope({ filter: "." + $value });
});
}
});
});
ul {
display: flex;
list-style: none;
justify-content: center;
margin-top: 25px;
}
ul > li {
margin-left: 15px;
cursor: pointer;
padding: 0.5rem 1rem;
background-color: #dc143c; /* crimson */
color: #fff; /* white */
font-family: "Calibri", sans-serif;
}
.container {
max-width: 90%;
margin: 0 auto;
}
.grid {
columns: 4 25vw;
}
.grid-item {
width: 50%;
}
.grid-item img {
object-fit: cover;
-o-object-fit: cover;
width: calc(100% - 0.25rem);
height: auto;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script src="https://unpkg.com/isotope-layout#3.0.6/dist/isotope.pkgd.min.js"></script>
<script src="https://unpkg.com/imagesloaded#4.1.4/imagesloaded.pkgd.min.js"></script>
<ul>
<li class="list" data-filter="all">All</li>
<li class="list" data-filter="phone">Phone</li>
<li class="list" data-filter="camera">Camera</li>
<li class="list" data-filter="watch">Watch</li>
</ul>
<div class="container">
<div class="grid">
<div class="grid-item phone">
<img src="https://picsum.photos/500/300" alt="">
</div>
<div class="grid-item camera">
<img src="https://picsum.photos/400/200" alt="">
</div>
<div class="grid-item watch">
<img src="https://picsum.photos/500/300" alt="">
</div>
<div class="grid-item camera">
<img src="https://picsum.photos/400/200" alt="">
</div>
<div class="grid-item watch">
<img src="https://picsum.photos/500/300" alt="">
</div>
<div class="grid-item camera">
<img src="https://picsum.photos/400/200" alt="">
</div>
<div class="grid-item watch">
<img src="https://picsum.photos/500/300" alt="">
</div>
</div>
</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