On scroll down images are moving up - javascript

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.

Related

How can I get my img src to keep changing between 3-4 images when hovered?

I am currently working on a college project for a clothing website, so what I want is that when the user hovers over a product image on the main feed, the product image keeps changing between 3-4 images of that product with a few milliseconds of transition.
this is my HTML code
<div class="imagebox">
<img src="../img/Mom Sarees/5pcs/A93A5321.JPG" alt="Saree no: A93A5321 ">
</div>
this is the CSS
.imagebox{
display: inline-block;}
.imagebox img{
margin-top: 20px;
height: 400px;
margin-right: 10px;}
Is there a way to do that using CSS or JS?
I've implemented an example by JS, I hope this will be helpful.
let intervalId;
let i = 0;
document.querySelectorAll('.product-images').forEach((poroduct) => {
const productImages = poroduct.querySelectorAll('img');
poroduct.addEventListener('mouseenter', function() {
fadeImg(productImages);
intervalId = setInterval(() => fadeImg(productImages), 1500);
});
poroduct.addEventListener('mouseleave', function() {
clearInterval(intervalId);
productImages[i].classList.remove('active');
productImages[0].classList.add('active');
i = 0;
});
});
function fadeImg(productImages) {
productImages[i].classList.remove('active');
i = (i + 1) % 4;
productImages[i].classList.add('active');
}
.container {
display: flex;
}
.imagebox {
position: relative;
flex: 1;
margin: 15px;
}
.imagebox img {
max-height: 200px;
max-width: 100%;
position: absolute;
opacity: 0;
transition: opacity 500ms;
}
.imagebox img.active {
opacity: 1;
}
<div class="container">
<div class="imagebox">
<a href="#" class="product-images">
<img class="active" src="https://fakeimg.pl/350x200/550000/?text=Image1" />
<img src="https://fakeimg.pl/350x200/005500/?text=Image2" />
<img src="https://fakeimg.pl/350x200/000055/?text=Image3" />
<img src="https://fakeimg.pl/350x200/005555/?text=Image4" />
</a>
</div>
<div class="imagebox">
<a href="#" class="product-images">
<img class="active" src="https://fakeimg.pl/350x200/000000/?text=Image1" />
<img src="https://fakeimg.pl/350x200/faaa22/?text=Image2" />
<img src="https://fakeimg.pl/350x200/885500/?text=Image3" />
<img src="https://fakeimg.pl/350x200/f500aa/?text=Image4" />
</a>
</div>
<div class="imagebox">
<a href="#" class="product-images">
<img class="active" src="https://fakeimg.pl/350x200/0000ff/?text=Image1" />
<img src="https://fakeimg.pl/350x200/00ff00/?text=Image2" />
<img src="https://fakeimg.pl/350x200/ff0000/?text=Image3" />
<img src="https://fakeimg.pl/350x200/ffff00/?text=Image4" />
</a>
</div>
</div>

scrolling animation for elements of certain class using js

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.

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%);
}

Create slider like infinite scrolling with CSS

I am trying to create CSS slider infinite scroll, but without appending/adding/creating DOM elements. Infinite scroll as in when the last slide is reached, the first slide should be shown again after it.
I have a fixed width slide, so the use of slick and box slider plugin does not work for me.
.slider-wrap {
white-space: nowrap;
overflow-x: auto;
overflow-y: hidden;
border: 1px solid red;
}
.slider-wrap .slide {
display: inline-block;
width: 200px;
margin: 5px;
}
.slider-wrap .slide img {
width: 100%;
}
<div class="slider-wrap">
<div class="slide">
<img src="http://via.placeholder.com/350x150">
</div>
<div class="slide">
<img src="http://via.placeholder.com/350x150">
</div>
<div class="slide">
<img src="http://via.placeholder.com/350x150">
</div>
<div class="slide">
<img src="http://via.placeholder.com/350x150">
</div>
<div class="slide">
<img src="http://via.placeholder.com/350x150">
</div>
<div class="slide">
<img src="http://via.placeholder.com/350x150">
</div>
<div class="slide">
<img src="http://via.placeholder.com/350x150">
</div>
</div>
Here are two options:
clone the items: you get a more natural approach (cloning isn't that bad). That's the system you would usually find on websites to add more content.
revert the position scroll position to another position to make it seem the slider never ends. Beware this will not make the scroll bar smaller as the content of the slider never gets changed
(a) Cloning
As you said you can clone the images.
The trick is to determine when the scroll has reached the end of the slider to clone more images in:
$(function() {
$('.slider-wrap').scroll(function() {
const slider = $(this);
width = slider.innerWidth()
scrollWidth = slider[0].scrollWidth;
scrollLeft = slider.scrollLeft();
if(scrollWidth - width == scrollLeft) {
slider.children().clone().appendTo(slider);
}
});
});
.slider-wrap {
white-space: nowrap;
overflow-x: auto;
overflow-y: hidden;
border: 1px solid red;
}
.slider-wrap .slide {
display: inline-block;
width: 200px;
margin: 5px;
}
.slider-wrap .slide img {
width: 100%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="slider-wrap">
<div class="slide">
<img src="http://via.placeholder.com/350x150">
</div>
<div class="slide">
<img src="http://via.placeholder.com/350x150">
</div>
<div class="slide">
<img src="http://via.placeholder.com/350x150">
</div>
<div class="slide">
<img src="http://via.placeholder.com/350x150">
</div>
<div class="slide">
<img src="http://via.placeholder.com/350x150">
</div>
<div class="slide">
<img src="http://via.placeholder.com/350x150">
</div>
<div class="slide">
<img src="http://via.placeholder.com/350x150">
</div>
</div>
And here's a demo:
$(function(){$('.slider-wrap').scroll(function(){const slider=$(this);var $width=slider.innerWidth()
var $scrollWidth=slider[0].scrollWidth;var $scrollLeft=slider.scrollLeft();if($scrollWidth-$width==$scrollLeft){slider.children().clone().appendTo(slider)}})})
.slider-wrap{white-space:nowrap;overflow-x:auto;overflow-y:hidden;border:1px solid red}.slider-wrap .slide{display:inline-block;margin:5px}.slider-wrap .slide img{height:120px}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><div class="slider-wrap"> <div class="slide"> <img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTa4e2VF6cfou9oL0cc5OAzVTEbmAgFjIW2r-7lTkpOljG9k38N"> </div><div class="slide"> <img src="https://nbocdn.akamaized.net/Assets/Images_Upload/2018/01/06/0060bbce-f2f2-11e7-bf60-029def90d6d6_web_scale_0.0542636_0.0542636__.jpg?maxheight=460&maxwidth=638&scale=both"> </div><div class="slide"> <img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQr0xQ-gVF1Sy1a1sHoUyfGdrBwyz-5u0Tirkt-uNCKd-AzNXY1ww"> </div><div class="slide"> <img src="https://cdn.pixabay.com/photo/2017/05/29/15/34/kitten-2354016_960_720.jpg"> </div><div class="slide"> <img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTJLwVbVu6tjubsduR43je-Muk7p8lAKDu569GuL_yDWGzrZwp2"> </div><div class="slide"> <img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQRHeW6zNDdDQBwtpuu3RvLW1ihM3Za-OLBoOMRR_4z7GvwYor2eQ"> </div><div class="slide"> <img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRKeCmurlUrTtd4CjvXYskGVAUAiDq5X49iNb3XhOcMss2vN8c6"> </div></div>
(b) A hack with scrollLeft
You could also go straight back to the first slide container by setting the scrollLeft to the position when it first added a new slide container:
let firstPos = undefined;
$('.slider').scroll(function() {
const slider = $(this);
width = slider.innerWidth()
scrollWidth = slider[0].scrollWidth;
scrollLeft = slider.scrollLeft();
isEndOfSlider = (scrollWidth - width) == scrollLeft;
numberOfWraps = slider.children().length;
if(isEndOfSlider) {
if(numberOfWraps == 1) {
firstPos = scrollLeft;
slider.children().first().clone().appendTo(slider);
} else {
slider.scrollLeft(firstPos);
}
}
});
.slider {
white-space: nowrap;
overflow-x: auto;
overflow-y: hidden;
border: 1px solid red;
}
.slider-wrap {
display: inline-block;
}
.slider-wrap .slide {
display: inline-block;
width: 200px;
margin: 5px;
}
.slider-wrap .slide img {
width: 100%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="slider">
<div class="slider-wrap">
<div class="slide">1
<img src="http://via.placeholder.com/350x150">
</div>
<div class="slide">2
<img src="http://via.placeholder.com/350x150">
</div>
<div class="slide">3
<img src="http://via.placeholder.com/350x150">
</div>
<div class="slide">...
<img src="http://via.placeholder.com/350x150">
</div>
<div class="slide">...
<img src="http://via.placeholder.com/350x150">
</div>
<div class="slide">-2
<img src="http://via.placeholder.com/350x150">
</div>
<div class="slide">-1
<img src="http://via.placeholder.com/350x150">
</div>
</div>
</div>
Here's a demo:
let firstPos=undefined;$('.slider').scroll(function(){const slider=$(this);width=slider.innerWidth()
scrollWidth=slider[0].scrollWidth;scrollLeft=slider.scrollLeft();isEndOfSlider=(scrollWidth-width)==scrollLeft;numberOfWraps=slider.children().length;if(isEndOfSlider){if(numberOfWraps==1){firstPos=scrollLeft;slider.children().first().clone().appendTo(slider)}else{slider.scrollLeft(firstPos)}}})
.slider{white-space:nowrap;overflow-x:auto;overflow-y:hidden;border:1px solid red}.slider-wrap{display:inline-block}.slider-wrap .slide{display:inline-block;margin:5px}.slider-wrap .slide img{width:auto;height:120px}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><div class="slider"> <div class="slider-wrap"> <div class="slide"> <img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTa4e2VF6cfou9oL0cc5OAzVTEbmAgFjIW2r-7lTkpOljG9k38N"> </div><div class="slide"> <img src="https://nbocdn.akamaized.net/Assets/Images_Upload/2018/01/06/0060bbce-f2f2-11e7-bf60-029def90d6d6_web_scale_0.0542636_0.0542636__.jpg?maxheight=460&maxwidth=638&scale=both"> </div><div class="slide"> <img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQr0xQ-gVF1Sy1a1sHoUyfGdrBwyz-5u0Tirkt-uNCKd-AzNXY1ww"> </div><div class="slide"> <img src="https://cdn.pixabay.com/photo/2017/05/29/15/34/kitten-2354016_960_720.jpg"> </div><div class="slide"> <img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTJLwVbVu6tjubsduR43je-Muk7p8lAKDu569GuL_yDWGzrZwp2"> </div><div class="slide"> <img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQRHeW6zNDdDQBwtpuu3RvLW1ihM3Za-OLBoOMRR_4z7GvwYor2eQ"> </div><div class="slide"> <img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRKeCmurlUrTtd4CjvXYskGVAUAiDq5X49iNb3XhOcMss2vN8c6"> </div></div></div>

Categories

Resources