JavaScript Animation Using Promises for Cwicly Gallery / column block etc

This JavaScript animation technique leverages the power of promises to control the loading and display of images or elements on a webpage. Unlike traditional scroll animations that trigger based on the user’s scroll position, this approach ensures elements animate in a specific sequence when the page loads, regardless of the user’s interaction.

View it LIVE:

Key Features

  • Sequential Loading: Animations occur in a defined order, enhancing the visual storytelling of the page.
  • Session Awareness: Animations play fully once per browser session, avoiding repetitive animations on navigation.
  • Flexibility: Customizable for different website structures and designs.

### Use Case: Cwicly Gallery Animation

  1. Add a Custom Class to Your Gallery
  • Use the class .my-gallery for your gallery block.
  1. Apply Custom CSS
.my-gallery figure {
  opacity: 0;
  transition: opacity 1.25s cubic-bezier(0.47, 0, 0.745, 0.715);

.my-gallery figure.loading-complete,
.wp-admin .my-gallery figure {
  opacity: 1;

    • The .wp-admin .my-gallery figure {opacity: 1;} ensures visibility in the editor.
  1. JavaScript Configuration for Gallery
  • Place the script in a code JS block on the page.
  • Customize the configuration object config as per your gallery structure.

### For Column Grid Configuration

  1. Apply to a Container/Div with Columns
  • Add a custom class, e.g., .project-rows, to your container.
  • Change rowSelector in the config to match your class name.
  1. Apply Custom CSS to the Container
.project-rows .cc-clmn {
  opacity: 0;
  transition: opacity 1.25s cubic-bezier(0.47, 0, 0.745, 0.715);

.project-rows .cc-clmn.loading-complete,
.wp-admin .project-rows .cc-clmn {
  opacity: 1;
  1. JavaScript Configuration for Columns
  • Adjust the config object for your specific column structure.

Customization and Adaptation

  • Adjustable Config: Modify delays, selectors, and transitions to fit your specific needs.
  • Flexible Design: The technique can be adapted for various website layouts and designs.
  • Enhanced User Experience: The animation adds a polished, professional touch to your site, improving user engagement.

This approach offers a sophisticated alternative to traditional animations, perfect for web developers looking to add a refined and controlled animation sequence to their websites.

Full JS File

document.addEventListener("DOMContentLoaded", function () {
  const config = {
    animationPlayedKey: "animationsPlayed",
    loadTimeout: 10, // delayed start
    delayIncrement: 120, // Increment delay for each column
    rowSelector: ".project-rows",
    columnSelector: ".cc-clmn",
    imageSelector: ".cc-clmn .cc-image"

  const animationsPlayed = sessionStorage.getItem(config.animationPlayedKey);
  if (animationsPlayed) {
    document.querySelectorAll(config.columnSelector).forEach((column) => {

  const applyAnimations = () => {
    let delay = 0;
    const rows = document.querySelectorAll(config.rowSelector);

    rows.forEach((row) => {
      const columns = row.querySelectorAll(config.columnSelector);
      columns.forEach((column) => {
        setTimeout(() => {
        }, delay);
        delay += config.delayIncrement;

    sessionStorage.setItem(config.animationPlayedKey, "true");

  const images = document.querySelectorAll(config.imageSelector);
  const loadPromises = images.length > 0
    ? Array.from(images).map((img) => new Promise((resolve) => {
        if (img.complete) {
        } else {
          img.addEventListener("load", resolve);
    : [Promise.resolve()];

  const timeoutFallback = new Promise((resolve) => {
    setTimeout(resolve, config.loadTimeout);

  Promise.race([Promise.all(loadPromises), timeoutFallback]).then(applyAnimations);
1 Like