本文へスキップ
HELLO!
HIGASHIYUKI®.COM
0   /   100
ローディング

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

デモ

仕様

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

しくみと調整

文字を透明にし、帯の入ったグラデーション(幅 250%)を background-clip で文字の形に切り抜きます。background-position を右から左へ動かすと、帯が文字の上を走って見えます。帯は文字の外から入って外へ抜けるので、繰り返しの継ぎ目が目立ちません。

帯が端から端まで走る時間は1.3秒、次の帯までの間は0.3秒です。動きは ease: none(等速)にしてあります。イーズを付けると端でもたついて止まって見えるので、等速のほうが帯が流れている印象を保てます。

背景の幅を 250% よりさらに広げると、帯が文字の外を走っている時間が長くなり、動きが止まって見える瞬間が増えます。逆に狭めすぎると帯の外側の余白が無くなり、繰り返しの境目に継ぎ目が出ます。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 サイト制作、端末ごとの見え方や表示速度の考え方はレスポンシブウェブサイトのページにまとめています。映像として作る動きをお探しの場合はモーショングラフィックスをご覧ください。