I am trying to make an image gallery that lets the user sort options by category (land, sea, animal, and more). I wrote a small example.
My goal: is that once the user selects (clicks) the category he wishes to sort by, the website will present only pictures from that specific category, while the other "unwanted" pictures will slowly disappear and move downward. Once the user changes selection, the "missing" pictures will reappear from below and go up until they reach their destination.
I did manage to make the in and out animations as well as keep the image hidden after the animation ends, but only after all relevant pictures disappear, the sorted pictures "jump" to their place instead of smoothly sliding toward their expected place.
Now I think my current problem is missing animation, but maybe I wrote something wrong in my CSS or my JS.
edit
i think i wasnt clear with my goal here, i am trying to filter out all of the photos that are not belong to the category selected and then display only the photos that belong to the category that has been choosen stacked from left to right in order in that point im stuck the images disappear but does not stack smoothly
const filterContainer = document.querySelector('.data-filters');
const photoItems = document.querySelectorAll('.photo-item');
filterContainer.addEventListener('click', (event) => {
filterContainer.querySelector('.active-filter').classList.remove('active-filter');
event.target.classList.add('active-filter');
const filter = event.target.getAttribute('data-filter');
photoItems.forEach((item) => {
if (item.getAttribute('data-filter') == filter || filter == 'all') {
item.classList.remove('photo-out')
item.classList.add('photo-in')
} else {
item.classList.remove('photo-in')
item.classList.add('photo-out')
}
})
})
.line-list li {
display: inline-block;
margin: 10px;
cursor: pointer;
}
.active-filter {
color: blue;
}
@keyframes go-out {
0% {
top: 0px;
opacity: 1.0
}
100% {
top: 600px;
opacity: 0;
display: none
}
}
@keyframes go-in {
100% {
top: 0px;
opacity: 1.0
}
0% {
top: 600px;
opacity: 0;
display: block
}
}
.photo-out {
animation: go-out 1.2s forwards;
}
.photo-in {
animation: go-in 1.2s forwards;
}
<html>
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
</head>
<body>
<section id='photo_wall'>
<div class='container'>
<div class='row'>
<div class='col-md-12 data-filters'>
<ul class='line-list'>
<li class='active-filter' data-filter='all'> All photos </li>
<li data-filter='land'> Land </li>
<li data-filter='sea'> Sea </li>
<li data-filter='animals'> Animals </li>
</ul>
</div>
</div>
<div class='row'>
<div class='col-md-3 photo-item p-4 photo-in' data-filter='land'>
<img src='https://fastly.picsum.photos/id/807/200/200.jpg?hmac=Y8gayvNItiQYxP_Pd-2un9GH09XuyJdIZOQPw6K9QsI'>
</div>
<div class='col-md-3 col-sm-6 photo-item p-4 photo-in' data-filter='animals'>
<img src='https://fastly.picsum.photos/id/659/200/200.jpg?hmac=kFpdD3XTBGwPUAH1tD-AiWigstjIX8WGIcyySuVQIvE' class='animals'>
</div>
<div class='col-md-3 col-sm-6 photo-item p-4 photo-in' data-filter='land'>
<img src='https://fastly.picsum.photos/id/165/200/200.jpg?hmac=tQGrY9pm5ze9soSsZ5CNBt87zqnHfFwdPv_khau12Sw' class='land'>
</div>
<div class='col-md-3 photo-item p-4 photo-in' data-filter='sea'>
<img src='https://fastly.picsum.photos/id/883/200/200.jpg?hmac=evNCTcW3jHI_xOnAn7LKuFH_YkA8r6WdQovmsyoM1IY' class='sea'>
</div>
<div class='col-md-3 photo-item p-4 photo-in' data-filter='animals'>
<img src='https://fastly.picsum.photos/id/237/200/200.jpg?hmac=zHUGikXUDyLCCmvyww1izLK3R3k8oRYBRiTizZEdyfI' class='animals'>
</div>
<div class='col-md-3 photo-item p-4 photo-in' data-filter='sea'>
<img src='https://fastly.picsum.photos/id/653/200/200.jpg?hmac=tZtho3csFdJ2rLHTTlT7WhXtDwbXgJNIIUvOQQb2dIo' class='sea'>
</div>
</div>
</div>
</section>
</body>
</html>
3
Answers
Not trivial.
Perhaps play with this
I think the problem is in your event handling.
You have to condition it to your list items only.
You have to exclude
<ul>
and parent<div>
.I cannot think of a way of smoothly minimising the cols in the Bootstrap environment.
This snippet therefore uses just inline-block.
The elements always stay in the order they are given in the HTML, but when not on show they have width 0, meaning those elements which are on show will be side by side. And width is an animatable CSS property.
To get the falling image effect therefore the images are held as backgrounds to pseudo before elements of the parent divs rather than as an img element. These pseudo elements can be made to fall (and rise) without affecting the layout as they are position absolute.
They fall, then their divs are animated down to 0px width.