I'm trying to make a filterable gallery using CSS flexbox that has smooth animations using HTML, CSS, and jQuery (JS).
Everything works but the animations are sometimes choppy when filtering.
Here is a reproduction of my problem where I use an .img-hidden
class to reduce width
, height
, and margin
to 0px
:
$(document).ready(function() {
// Initialization
filterImage("");
shuffleImages();
// On Filter Dropdown Change
$(".filters").change(function() {
if($(".filters").val() == "all") {
filterImage("");
}
else {
filterImage($(".filters").val());
}
});
// Shuffle Order of Images
function shuffleImages() {
// https://stackoverflow.com/questions/18483241/random-div-order-on-page-load
$(".image").each(function() {
var target = Math.floor(Math.random() * $(".image").length - 1) + 1;
var target2 = Math.floor(Math.random() * $(".image").length - 1) + 1;
$(".image").eq(target).before($(".image").eq(target2));
});
}
// Filter Images
function filterImage(tag) {
if(tag == "") {
$(".image").removeClass("img-hidden");
}
else {
$(".image").each(function(i) {
if(($(".image").eq(i).data("tag")).includes(tag)) {
$(".image").eq(i).removeClass("img-hidden");
}
else {
$(".image").eq(i).addClass("img-hidden");
}
});
}
}
});
/* Images Container */
.images {
display: flex;
flex-wrap: wrap;
width: 100%;
padding-top: 15px;
justify-content: center;
}
/* Individual Image */
.image {
display: block;
width: 200px;
height: 150px;
margin: 5px;
border-radius: 5px;
overflow: hidden;
position: relative;
transition: width 1s ease, height 1s ease, margin 1s ease;
}
.image img {
top: 0;
left: 0;
position: absolute;
width: 100%;
height: 100%;
object-fit: cover;
}
/* Transition Classes */
.img-hidden {
width: 0px !important;
height: 0px !important;
margin: 0px;
}
<html>
<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" />
<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
</head>
<body>
<label for="filters">Filter by: </label>
<select class="filters" id="filters">
<option value="all">All</option>
<option value="cat">Cat</option>
<option value="dog">Dog</option>
<option value="bird">Bird</option>
</select>
<div class="images">
<div class="image" data-tag="cat">
<!-- Source: Manja Vitolic on Unsplash -->
<img src="https://images.unsplash.com/photo-1514888286974-6c03e2ca1dba?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1443&q=80" />
</div>
<div class="image" data-tag="cat">
<!-- Source: Micheal Sum on Unsplash -->
<img src="https://images.unsplash.com/photo-1519052537078-e6302a4968d4?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1470&q=80" />
</div>
<div class="image" data-tag="cat">
<!-- Source: Mikhail Vasilyev on Unsplash -->
<img src="https://images.unsplash.com/photo-1494256997604-768d1f608cac?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1529&q=80" />
</div>
<div class="image" data-tag="cat">
<!-- Source: Pacto Visual on Unsplash -->
<img src="https://images.unsplash.com/photo-1478098711619-5ab0b478d6e6?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1470&q=80" />
</div>
<div class="image" data-tag="dog">
<!-- Source: Victor Grabarczyk on Unsplash -->
<img src="https://images.unsplash.com/photo-1561037404-61cd46aa615b?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1470&q=80" />
</div>
<div class="image" data-tag="dog">
<!-- Source: Marliese Streefland on Unsplash -->
<img src="https://images.unsplash.com/photo-1543466835-00a7907e9de1?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1374&q=80" />
</div>
<div class="image" data-tag="dog">
<!-- Source: Pauline Loroy on Unsplash -->
<img src="https://images.unsplash.com/photo-1587300003388-59208cc962cb?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1470&q=80" />
</div>
<div class="image" data-tag="dog">
<!-- Source: Justin Veenema on Unsplash -->
<img src="https://images.unsplash.com/photo-1477884213360-7e9d7dcc1e48?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1470&q=80" />
</div>
<div class="image" data-tag="bird">
<!-- Source: Vincent van Zalinge on Unsplash -->
<img src="https://images.unsplash.com/photo-1444464666168-49d633b86797?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1469&q=80" />
</div>
<div class="image" data-tag="bird">
<!-- Source: Boris Smokrovic on Unsplash -->
<img src="https://images.unsplash.com/photo-1480044965905-02098d419e96?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1470&q=80" />
</div>
<div class="image" data-tag="bird">
<!-- Source: Zdeněk Macháček on Unsplash -->
<img src="https://images.unsplash.com/photo-1551085254-e96b210db58a?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1280&q=80" />
</div>
<div class="image" data-tag="bird">
<!-- Source: Jan Meeus on Unsplash -->
<img src="https://images.unsplash.com/photo-1522926193341-e9ffd686c60f?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1470&q=80" />
</div>
</div>
</body>
</html>
However, this method isn't the only method I tried.
Here is the same problem where I used jQuery's built-in show()
and hide()
methods:
$(document).ready(function() {
// Initialization
filterImage("");
shuffleImages();
// On Filter Dropdown Change
$(".filters").change(function() {
if($(".filters").val() == "all") {
filterImage("");
}
else {
filterImage($(".filters").val());
}
});
// Shuffle Order of Images
function shuffleImages() {
// https://stackoverflow.com/questions/18483241/random-div-order-on-page-load
$(".image").each(function() {
var target = Math.floor(Math.random() * $(".image").length - 1) + 1;
var target2 = Math.floor(Math.random() * $(".image").length - 1) + 1;
$(".image").eq(target).before($(".image").eq(target2));
});
}
// Filter Images
function filterImage(tag) {
if(tag == "") {
$(".image").show(1000);
}
else {
$(".image").each(function(i) {
if(($(".image").eq(i).data("tag")).includes(tag)) {
$(".image").eq(i).show(1000);
}
else {
$(".image").eq(i).hide(1000);
}
});
}
}
});
/* Images Container */
.images {
display: flex;
flex-wrap: wrap;
width: 100%;
padding-top: 15px;
justify-content: center;
}
/* Individual Image */
.image {
display: block;
width: 200px;
height: 150px;
margin: 5px;
border-radius: 5px;
overflow: hidden;
position: relative;
}
.image img {
top: 0;
left: 0;
position: absolute;
width: 100%;
height: 100%;
object-fit: cover;
}
<html>
<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" />
<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
</head>
<body>
<label for="filters">Filter by: </label>
<select class="filters" id="filters">
<option value="all">All</option>
<option value="cat">Cat</option>
<option value="dog">Dog</option>
<option value="bird">Bird</option>
</select>
<div class="images">
<div class="image" data-tag="cat">
<!-- Source: Manja Vitolic on Unsplash -->
<img src="https://images.unsplash.com/photo-1514888286974-6c03e2ca1dba?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1443&q=80" />
</div>
<div class="image" data-tag="cat">
<!-- Source: Micheal Sum on Unsplash -->
<img src="https://images.unsplash.com/photo-1519052537078-e6302a4968d4?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1470&q=80" />
</div>
<div class="image" data-tag="cat">
<!-- Source: Mikhail Vasilyev on Unsplash -->
<img src="https://images.unsplash.com/photo-1494256997604-768d1f608cac?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1529&q=80" />
</div>
<div class="image" data-tag="cat">
<!-- Source: Pacto Visual on Unsplash -->
<img src="https://images.unsplash.com/photo-1478098711619-5ab0b478d6e6?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1470&q=80" />
</div>
<div class="image" data-tag="dog">
<!-- Source: Victor Grabarczyk on Unsplash -->
<img src="https://images.unsplash.com/photo-1561037404-61cd46aa615b?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1470&q=80" />
</div>
<div class="image" data-tag="dog">
<!-- Source: Marliese Streefland on Unsplash -->
<img src="https://images.unsplash.com/photo-1543466835-00a7907e9de1?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1374&q=80" />
</div>
<div class="image" data-tag="dog">
<!-- Source: Pauline Loroy on Unsplash -->
<img src="https://images.unsplash.com/photo-1587300003388-59208cc962cb?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1470&q=80" />
</div>
<div class="image" data-tag="dog">
<!-- Source: Justin Veenema on Unsplash -->
<img src="https://images.unsplash.com/photo-1477884213360-7e9d7dcc1e48?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1470&q=80" />
</div>
<div class="image" data-tag="bird">
<!-- Source: Vincent van Zalinge on Unsplash -->
<img src="https://images.unsplash.com/photo-1444464666168-49d633b86797?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1469&q=80" />
</div>
<div class="image" data-tag="bird">
<!-- Source: Boris Smokrovic on Unsplash -->
<img src="https://images.unsplash.com/photo-1480044965905-02098d419e96?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1470&q=80" />
</div>
<div class="image" data-tag="bird">
<!-- Source: Zdeněk Macháček on Unsplash -->
<img src="https://images.unsplash.com/photo-1551085254-e96b210db58a?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1280&q=80" />
</div>
<div class="image" data-tag="bird">
<!-- Source: Jan Meeus on Unsplash -->
<img src="https://images.unsplash.com/photo-1522926193341-e9ffd686c60f?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1470&q=80" />
</div>
</div>
</body>
</html>
I even tried using CSS Animations to animate transform: scale
and the width
, height
, and margin
properties:
$(document).ready(function() {
// Initialization
filterImage("");
shuffleImages();
// On Filter Dropdown Change
$(".filters").change(function() {
if($(".filters").val() == "all") {
filterImage("");
}
else {
filterImage($(".filters").val());
}
});
// Shuffle Order of Images
function shuffleImages() {
// https://stackoverflow.com/questions/18483241/random-div-order-on-page-load
$(".image").each(function() {
var target = Math.floor(Math.random() * $(".image").length - 1) + 1;
var target2 = Math.floor(Math.random() * $(".image").length - 1) + 1;
$(".image").eq(target).before($(".image").eq(target2));
});
}
// Filter Images
function filterImage(tag) {
if(tag == "") {
$(".image").removeClass("img-hidden");
$(".image").addClass("img-shown");
}
else {
$(".image").each(function(i) {
if(($(".image").eq(i).data("tag")).includes(tag)) {
$(".image").eq(i).removeClass("img-hidden");
$(".image").eq(i).addClass("img-shown");
}
else {
$(".image").eq(i).removeClass("img-shown");
$(".image").eq(i).addClass("img-hidden");
}
});
}
}
});
/* Images Container */
.images {
display: flex;
flex-wrap: wrap;
width: 100%;
padding-top: 15px;
justify-content: center;
}
/* Individual Image */
.image {
display: block;
width: 200px;
height: 150px;
margin: 5px;
border-radius: 5px;
overflow: hidden;
position: relative;
}
.image img {
top: 0;
left: 0;
position: absolute;
width: 100%;
height: 100%;
object-fit: cover;
}
/* Transition Classes */
.img-shown {
animation: show-image 1s ease 0s 1 forwards;
transform-origin: center;
}
.img-hidden {
animation: hide-image 1s ease 0s 1 forwards;
transform-origin: center;
}
/* Animations */
@keyframes hide-image {
0% {
transform: scale(1);
}
100% {
transform: scale(0);
width: 0;
height: 0;
margin: 0;
}
}
@keyframes show-image {
0% {
transform: scale(0);
width: 0;
height: 0;
margin: 0;
}
100% {
transform: scale(1);
}
}
<html>
<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" />
<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
</head>
<body>
<label for="filters">Filter by: </label>
<select class="filters" id="filters">
<option value="all">All</option>
<option value="cat">Cat</option>
<option value="dog">Dog</option>
<option value="bird">Bird</option>
</select>
<div class="images">
<div class="image" data-tag="cat">
<!-- Source: Manja Vitolic on Unsplash -->
<img src="https://images.unsplash.com/photo-1514888286974-6c03e2ca1dba?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1443&q=80" />
</div>
<div class="image" data-tag="cat">
<!-- Source: Micheal Sum on Unsplash -->
<img src="https://images.unsplash.com/photo-1519052537078-e6302a4968d4?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1470&q=80" />
</div>
<div class="image" data-tag="cat">
<!-- Source: Mikhail Vasilyev on Unsplash -->
<img src="https://images.unsplash.com/photo-1494256997604-768d1f608cac?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1529&q=80" />
</div>
<div class="image" data-tag="cat">
<!-- Source: Pacto Visual on Unsplash -->
<img src="https://images.unsplash.com/photo-1478098711619-5ab0b478d6e6?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1470&q=80" />
</div>
<div class="image" data-tag="dog">
<!-- Source: Victor Grabarczyk on Unsplash -->
<img src="https://images.unsplash.com/photo-1561037404-61cd46aa615b?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1470&q=80" />
</div>
<div class="image" data-tag="dog">
<!-- Source: Marliese Streefland on Unsplash -->
<img src="https://images.unsplash.com/photo-1543466835-00a7907e9de1?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1374&q=80" />
</div>
<div class="image" data-tag="dog">
<!-- Source: Pauline Loroy on Unsplash -->
<img src="https://images.unsplash.com/photo-1587300003388-59208cc962cb?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1470&q=80" />
</div>
<div class="image" data-tag="dog">
<!-- Source: Justin Veenema on Unsplash -->
<img src="https://images.unsplash.com/photo-1477884213360-7e9d7dcc1e48?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1470&q=80" />
</div>
<div class="image" data-tag="bird">
<!-- Source: Vincent van Zalinge on Unsplash -->
<img src="https://images.unsplash.com/photo-1444464666168-49d633b86797?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1469&q=80" />
</div>
<div class="image" data-tag="bird">
<!-- Source: Boris Smokrovic on Unsplash -->
<img src="https://images.unsplash.com/photo-1480044965905-02098d419e96?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1470&q=80" />
</div>
<div class="image" data-tag="bird">
<!-- Source: Zdeněk Macháček on Unsplash -->
<img src="https://images.unsplash.com/photo-1551085254-e96b210db58a?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1280&q=80" />
</div>
<div class="image" data-tag="bird">
<!-- Source: Jan Meeus on Unsplash -->
<img src="https://images.unsplash.com/photo-1522926193341-e9ffd686c60f?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1470&q=80" />
</div>
</div>
</body>
</html>
No matter what method I try, they all result in choppy animations.
Any way I can make the animations more smooth and less choppy?