Textillin とは
tlt-fadeInBottom などのクラスを付けるだけで、テキストを1文字ずつアニメーションさせるライブラリです。スクロールで要素がビューポートに入ったタイミングで自動実行されます。
<strong class="tlt-bounceInBottom">
<span>文字が1文字ずつ下からバウンスしてきます。</span>
</strong>特徴:
- Vanilla JS — jQuery不要
- IntersectionObserver API — スクロール監視にネイティブAPIを使用
- MutationObserver 対応 — 動的に追加された要素も自動検出
[untextillin]属性 — 特定セクション内のアニメーションを無効化できる@media print対応 — FireShot等のスクリーンショットで正常にキャプチャされる.delayed-*/.fasted-*/.slowed-*でタイミング調整可能
使い方
1. ファイルを読み込む
<link rel="stylesheet" href="textillin.css">
<script src="textillin.js"></script>2. tlt-エフェクト名 クラスと <span> でテキストを囲む
<h2 class="tlt-fadeInBottom">
<span>スクロールで文字が1文字ずつフェードイン</span>
</h2><strong> / <h2> / <p> 等の要素に tlt-* クラスを付け、テキストを <span> で囲むだけです。スクロールで要素がビューポートに入ったタイミングで自動的にアニメーションが実行されます。
利用可能なエフェクト一覧
| クラス名 | 効果 |
|---|---|
tlt-fadeIn | 1文字ずつフェードイン |
tlt-fadeInBottom | 下から1文字ずつフェードイン |
tlt-fadeInTop | 上から1文字ずつフェードイン |
tlt-fadeInLeft | 左から1文字ずつフェードイン |
tlt-fadeInRight | 右から1文字ずつフェードイン |
tlt-bounceIn | 1文字ずつバウンスイン |
tlt-bounceInBottom | 下から1文字ずつバウンスイン |
tlt-bounceInTop | 上から1文字ずつバウンスイン |
tlt-bounceInLeft | 左から1文字ずつバウンスイン |
tlt-bounceInRight | 右から1文字ずつバウンスイン |
tlt-flipIn | 1文字ずつフリップ(3D回転) |
tlt-flipInX | X軸方向に1文字ずつフリップ |
tlt-flipInY | Y軸方向に1文字ずつフリップ |
tlt-flashIn | 1文字ずつフラッシュ(点滅) |
tlt-shakeIn | 1文字ずつシェイク |
tlt-pulseIn | 1文字ずつパルス(拡縮) |
tlt-rollIn | 1文字ずつ横からロール |
data-* 属性によるカスタマイズ
文字の登場順序
<!-- シャッフル(ランダム順)で登場 -->
<strong class="tlt-fadeInBottom">
<span data-in-shuffle="true">ランダムに登場します</span>
</strong>
<!-- 逆順で登場 -->
<strong class="tlt-bounceInBottom">
<span data-in-reverse="true">右端から登場します</span>
</strong>
<!-- 全文字同時に登場(1文字ずつでなく一斉) -->
<strong class="tlt-fadeIn">
<span data-in-sync="true">全文字が同時にフェードイン</span>
</strong>文字間のディレイ
<!-- 文字間のディレイを広くする(デフォルト30ms) -->
<strong class="tlt-fadeInBottom">
<span data-in-delay="60">ゆっくり1文字ずつ登場</span>
</strong>ループ再生と複数テキストの切り替え
<strong class="tlt-fadeIn" data-loop="true" data-minDisplayTime="2000">
<ul class="texts">
<li>最初のテキスト</li>
<li>次のテキスト</li>
<li>最後のテキスト</li>
</ul>
</strong>data-loop="true" を付けると、複数の <li> テキストがアウト→インを繰り返します。data-minDisplayTime で各テキストの表示時間(ms)を指定できます。
タイミング調整クラス
<!-- 0.5秒遅れて開始 -->
<strong class="tlt-fadeInBottom delayed-2">
<span>テキスト</span>
</strong>
<!-- ゆっくり(2秒かけて)アニメーション -->
<strong class="tlt-bounceInBottom slowed-2">
<span>テキスト</span>
</strong>ディレイ(.delayed-*)
| クラス | 遅延 |
|---|---|
delayed-0 | 0s |
delayed-1 | 0.25s |
delayed-2 | 0.5s |
delayed-3 | 0.75s |
delayed-4 | 1s |
delayed-5 | 1.25s |
delayed-6 | 1.5s |
速度調整
| クラス | 再生時間 |
|---|---|
fasted-1 | 0.75s |
fasted-2 | 0.5s |
fasted-3 | 0.25s |
slowed-1 | 1.5s |
slowed-2 | 2s |
slowed-3 | 3s |
slowed-5 | 5s |
アニメーションを無効化する([untextillin])
祖先要素に untextillin 属性を付けると、その配下のテキストアニメーションをすべて無効化できます。
<section untextillin>
<strong class="tlt-fadeInBottom">
<span>アニメーションせず即表示される</span>
</strong>
</section>CSSでは :not([untextillin]) を使って animation-name と animation-duration を無効化します。JSでは el.closest('[untextillin]') でチェックし、アニメーションをスキップして即 visibility: visible にします。これにより animationend イベントが発火しない問題も回避しています。
JavaScript API
// 手動でアニメーションを実行
TextillinOptimized.trigger(element, 'fadeInBottom');
// カスタムエフェクトを追加
TextillinOptimized.addEffect('myEffect', 'myCssClass');
// 統計情報
TextillinOptimized.getStats();
// → { registeredTypes: [...], observedCount: 3, animatedCount: 10, availableEffects: 17 }
// デバッグモード(コンソールにアニメーション情報を出力)
TextillinOptimized.enableDebug();
// 破棄(Observer切断・メモリ解放)
TextillinOptimized.destroy();Textillate・Lettering.js との関係
Textillin は内部的に以下の実装を Vanilla JS に移植して使用しています。
- Textillate.js by Jordan Schroter (MIT License) — テキストアニメーションのオーケストレーション
- Lettering.js by Dave Rupert (WTFPL) — テキストを1文字ずつ
<span>に分割 - Animate.css by Daniel Eden (MIT License) — アニメーションのキーフレーム定義
これらを組み合わせ、jQueryへの依存をなくし、IntersectionObserver によるスクロールトリガーを追加したものが Textillin です。
実装の仕組み
- ページ読み込み時に
tlt-*クラスを持つ要素を検出しIntersectionObserverに登録 - ビューポートに10%以上入ったとき(下端から50pxのマージンあり)にアニメーション発火
- テキストを1文字ずつ
<span>に分割し、各文字に順番にアニメーションを適用 - アニメーション済みの要素は監視解除(一度きり)
MutationObserverで動的に追加された要素も自動検出・登録
対応ブラウザ
- Chrome 51+
- Firefox 55+
- Safari 12.1+
- Edge 15+
@media print / FireShot 対応
Textillin のエフェクトは animation ベースのため、FireShot など印刷エンジンを使うキャプチャツールでは文字が初期状態(不可視)のままになる問題があります。@media print ブロックで対処済みです。
@media print {
[class*="tlt-"] {
animation: none !important;
opacity: 1 !important;
visibility: visible !important;
}
}
