Falling Tiles

Tiles fall from the top, settle into a grid for a moment, and then descend one by one in a looping animation.

1. Copy the component file

Create a new file called falling-tiles-loader.jsx in your reusable components folder (for example /src/components/) and paste the following code into it.

falling-tiles-loader.jsx

import { memo } from "react";
import styles from "./falling-tiles-loader.module.css";

const FallingTilesLoader = (props) => {
  const {
    rows = 3,
    columns = 3,
  } = props;

  const delayBetweenTwoTilesMs = 50;
  const stayInGridDurationMs = 4000;
  
  const _rows = Math.max(1, rows);
  const _cols = Math.max(1, columns);

  const totalTiles = _rows * _cols;
  const totalAnimationDurationMs = (
    stayInGridDurationMs + (totalTiles * delayBetweenTwoTilesMs)
  );

  return (
    <span
      className={styles["falling-tiles-loader"]}
      style={{
        "--tiles-grid-columns": _cols,
      }}
    >
      {Array.from({ length: totalTiles }, ((_, index) => (
        <span
          key={`tile-${index}`}
          className={styles["tile"]} 
          style={{
            "--animation-duration": `${totalAnimationDurationMs}ms`,
            "--animation-delay": `${delayBetweenTwoTilesMs * (totalTiles - index)}ms`,
          }}
        />
      )))}
    </span>
  );
};

export default memo(FallingTilesLoader);

2. Copy the CSS module file

In the same folder, create a file called falling-tiles-loader.module.css and paste the following CSS.

falling-tiles-loader.module.css

.falling-tiles-loader {
  --tile-size: 8px;
  --tile-color: black;
  --tile-offset-y: 100px;

  @media (prefers-color-scheme: dark) {
    --tile-color: white;
  }

  display: grid;
  gap: 4px;
  grid-template-columns: repeat(var(--tiles-grid-columns), var(--tile-size));

  >.tile {
    width: var(--tile-size);
    height: var(--tile-size);
    background: var(--tile-color);
    opacity: 0;
    transform: translateY(calc(var(--tile-offset-y) * -1));
    animation: falling-tiles-keyframes ease-in-out infinite;
    animation-duration: var(--animation-duration);
    animation-delay: var(--animation-delay);
  }
}

@keyframes falling-tiles-keyframes {
  0%,
  15% {
    transform: translateY(calc(var(--tile-offset-y) * -1));
    opacity: 0;
  }

  30%,
  70% {
    transform: translateY(0);
    opacity: 1;
  }

  85%,
  100% {
    transform: translateY(var(--tile-offset-y));
    opacity: 0;
  }
}

3. Use the component

Now you can import and use the component anywhere in your project.

falling-tiles-loader-preview.jsx

import FallingTilesLoader from "@/components/loaders/falling-tiles-loader/falling-tiles-loader";

const FallingTilesLoaderPreview = () => {
  return (
    <FallingTilesLoader />
  );
};

export default FallingTilesLoaderPreview;

Props

Configure the component with the following props:

PropTypeRequiredDefaultDescription
rowsnumberNo3Number of rows in the tiles grid. Minimum value: 1.
columnsnumberNo3Number of columns in the tiles grid. Minimum value: 1.