0

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?

CodeZinx
  • 49
  • 1
  • 7
  • It's not so much the animation that's choppy, it's the reflow of your items from one row to the previous row when the item(s) can fit. – Lee Taylor Jan 07 '23 at 22:12
  • Any way I can prevent that reflow? – CodeZinx Jan 07 '23 at 22:28
  • You'd probably be better to use `position:absolute` and calculate the final position that the item will arrive at, then animate it to that position. But, you'll find that there are libraries that already do this. – Lee Taylor Jan 08 '23 at 12:47

0 Answers0