本文へスキップ
HELLO!
HIGASHIYUKI®.COM
0   /   100

ローディング

ローディングの「LOADING」の文字に光が走る

デモ

仕様

動作
DOM
種類
レシピ
動作確認
three 0.186.0・gsap 3.15.0
公開日

しくみと調整

「LOADING」の文字の中だけを、明るい光の筋が左から右へ通り抜けていきます。文字の色は透明にして、中央に光の筋が入ったグラデーションを、background-clip で文字の形に切り抜いています。グラデーションの幅は文字の250%あり、光の筋は文字の外から入ってきて外へ抜けていきます。光が文字にかかっていないあいだに次の周へ切り替わるので、繰り返しの継ぎ目が見えません。

コードでは背景の位置(background-position)を100%から0%へ減らしていますが、見た目の光は左から右へ進みます。値の向きと見た目の向きが逆に見えるので、向きを変えたいときは読み違えないようにしてください。

光が端から端まで走るのは1.3秒、次の光までの間は0.3秒。動きは ease: none の等速にしました。イージングを付けると、端の近くで光がもたついて止まったように見え、流れている感じが途切れます。

背景の幅は、250%前後からあまり動かさないほうが安全です。広げるほど光が文字の外にいる時間が延びて、止まって見える瞬間が増えます。狭めすぎると光の外側の余白がなくなり、繰り返しの境目に継ぎ目が出ます。光の色や角度、走る速さを変えれば、送信中のボタンや生成中の表示など、短い文言に目を留めてほしい場所にも使えます。

コード

HTML
<!-- ローディングの文言。テキストそのものが読み上げにも届く -->
<div class="shimmer-loader">
  <p class="shimmer-loader__text" role="status">LOADING</p>
</div>

CSS
.shimmer-loader {
  --ground: #111111; /* 背景色。文字のグラデーションとは別の要素に付ける(同じ要素だと背景色まで文字の形に切り抜かれる) */
  position: fixed;
  inset: 0;
  z-index: 10;
  display: grid;
  place-items: center;
  padding: 0 6vw;
  background: var(--ground);
}

.shimmer-loader__text {
  --base: #898989;  /* 光が当たっていない文字の色 */
  --shine: #eeece6; /* 光の筋。当たったところだけ文字の色になる */
  margin: 0;
  color: transparent;
  font-size: clamp(32px, 9vw, 80px);
  font-weight: 800;
  line-height: 1.15;
  letter-spacing: 0.06em;
  padding-left: 0.06em; /* 最後の字の後ろにも付く字間の分を左にも足し、字を中央にそろえる */
  text-align: center;
  background-image: linear-gradient(105deg, var(--base) 0%, var(--base) 44%, var(--shine) 50%, var(--base) 56%, var(--base) 100%);
  background-size: 250% 100%;
  background-repeat: no-repeat;
  -webkit-background-clip: text;
  background-clip: text;
}

JavaScript
import { gsap } from "gsap";

const reduceMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
const SWEEP = 1.3; // 光の筋が端から端まで走る時間(秒)
const REST = 0.3; // 次の光の筋までの間(秒)。光の筋は等速(ease: "none")にすると、文字にかかっている時間を長く取れる

function createLoader(label) {
  const root = label.closest(".shimmer-loader");
  const shimmer = reduceMotion
    ? gsap.set(label, { backgroundPosition: "50% 0%" }) // 動きを減らす設定では走らせず、光の筋を乗せたまま止める
    : gsap.fromTo(
        label,
        { backgroundPosition: "100% 0%" },
        { backgroundPosition: "0% 0%", duration: SWEEP, ease: "none", repeat: -1, repeatDelay: REST }
      );

  return {
    // 読み込みが終わったら呼ぶ。光の筋を止めて、ローディング画面ごと消す
    done() {
      shimmer.kill();
      gsap.to(root, { autoAlpha: 0, duration: reduceMotion ? 0 : 0.3, onComplete: () => root.remove() });
    },
  };
}

// 例: fetch や画像の読み込みを待って loader.done()。ボタンの「処理中」やAIの「生成中」表示にも
export const loader = createLoader(document.querySelector(".shimmer-loader__text"));

インタラクションデザインについて、
お気軽にご相談ください。

ここに並べているのは、Web サイトの中で動く UI のサンプルです。新しく作るサイトに組み込むことも、いま公開中のサイトに、ボタンやヒーロー、スクロールの演出だけを足すこともできます。設計から実装までの進め方はWeb サイト制作、端末ごとの見え方や表示速度の考え方はレスポンシブウェブサイトのページにまとめています。映像として作る動きをお探しの場合はモーショングラフィックスをご覧ください。