デモ
デモを読み込めませんでした。
仕様
- 用途
- ローディング
- 動作
- DOM
- 種類
- レシピ
- 動作確認
- three 0.186.0・gsap 3.15.0
- 公開日
しくみと調整
文字を透明にし、帯の入ったグラデーション(幅 250%)を background-clip で文字の形に切り抜きます。background-position を右から左へ動かすと、帯が文字の上を走って見えます。帯は文字の外から入って外へ抜けるので、繰り返しの継ぎ目が目立ちません。
帯が端から端まで走る時間は1.3秒、次の帯までの間は0.3秒です。動きは ease: none(等速)にしてあります。イーズを付けると端でもたついて止まって見えるので、等速のほうが帯が流れている印象を保てます。
背景の幅を 250% よりさらに広げると、帯が文字の外を走っている時間が長くなり、動きが止まって見える瞬間が増えます。逆に狭めすぎると帯の外側の余白が無くなり、繰り返しの境目に継ぎ目が出ます。250% 前後がちょうど良いバランスです。
帯の色や角度、走る速さは自由に変えられます。読み込み中の全画面表示だけでなく、送信中のボタンや生成中の表示など、短い文言を目立たせたい場面全般に使えます。
コード
<!-- ローディングの文言。テキストそのものが読み上げにも届く -->
<div class="shimmer-loader">
<p class="shimmer-loader__text" role="status">LOADING</p>
</div>
.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;
}
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"));