Three Dots

A minimal three-dot animated loader that indicates ongoing processing or content loading.

1. Copy the component file

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

three-dots-loader.jsx

import styles from "./three-dots-loader.module.css";

const ThreeDotsLoader = () => {
  return (
    <span className={styles["three-dots-loader"]}>
      <span className={styles["pair"]}>
        <span className={styles["dot"]}></span>
        <span className={styles["dot"]}></span>
      </span>
      <span className={styles["pair"]}>
        <span className={styles["dot"]}></span>
        <span className={styles["dot"]}></span>
      </span>
    </span>
  );
};

export default ThreeDotsLoader;

2. Copy the CSS module file

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

three-dots-loader.module.css

.three-dots-loader {
  --dot-size: 16px;
  --dot-color: currentColor; 

  --track-size: calc(calc(var(--dot-size) * 4) + 4px);
  --pair-size: calc(var(--track-size) * 0.75);
  --animation-duration: 1000ms;

  position: relative;
  width: var(--track-size);
  height: var(--dot-size);

  .pair {
    position: absolute;
    width: calc(var(--track-size) * 0.75);
    height: var(--dot-size);

    .dot {
      position: absolute;
      width: var(--dot-size);
      height: var(--dot-size);
      background: var(--dot-color);
      border-radius: 50%;

      &:nth-child(2) {
        right: 0px;
      }
    }

    &:nth-child(1) {
      animation: dots-spin-keyframes var(--animation-duration) ease-in-out infinite;

      .dot {
        &:nth-child(1) {
          opacity: 0;
          animation: dots-hide-keyframes var(--animation-duration) ease-in-out infinite reverse;
        }
      }
    }

    &:nth-child(2) {
      left: calc(var(--pair-size) - var(--dot-size));
      animation: dots-spin-keyframes var(--animation-duration) ease-in-out infinite reverse;

      .dot {
        &:nth-child(2) {
          opacity: 0;
          animation: dots-hide-keyframes var(--animation-duration) ease-in-out infinite;
        }
      }
    }
  }
}

@keyframes dots-hide-keyframes {
  0%,
  49% {
    opacity: 0;
  }

  50%,
  100% {
    opacity: 1;
  }
}

@keyframes dots-spin-keyframes {
  0% {
    transform: rotate(0deg);
  }

  50%,
  100% {
    transform: rotate(180deg);
  }
}

3. Use the component

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

three-dots-loader-preview.jsx

import ThreeDotsLoader from "@/components/loaders/three-dots-loader/three-dots-loader";

const ThreeDotsLoaderPreview = () => {
  return (
    <ThreeDotsLoader />
  );
};

export default ThreeDotsLoaderPreview;