はじめに
新しいWebアプリを開いた瞬間、「で、まず何をすればいいの?」と固まってしまった経験はありませんか。開発者にとっては自明な画面でも、初めて訪れたユーザーには機能の場所も操作の順番も分かりません。せっかく作り込んだ機能が「気づかれないまま」離脱される——これはプロダクト開発で最ももったいない瞬間です。
この課題を解決する定番の手法が、画面上の要素を順番にハイライトしながら説明していく「プロダクトツアー」です。そして、それをわずか数行のコードで実現できるのが、今回紹介するIntro.jsです。10年以上メンテナンスが続く老舗ライブラリで、GitHubでは23,000を超えるスターを集めています。
Intro.jsとは
Intro.jsは、Webサイトやアプリケーションにステップバイステップのガイドツアーやヒント表示を組み込むための、軽量なユーザーオンボーディングライブラリです。依存ライブラリなしの素のJavaScriptで書かれており、フレームワークを問わず利用できます。2025年にはv8系がリリースされ、TypeScriptベースの新しいAPIに刷新されました。
主な特徴
- 導入が簡単 - HTML要素に
data-intro属性を付けるだけでもツアーが作れます。既存のマークアップをほとんど変更せずに導入できます - 依存ゼロで軽量 - jQueryなどの外部依存がなく、CSSとJSを読み込むだけで動作します
- ツアーとヒントの2つのモード - 順番に案内する「ツアー」と、要素の横にパルスアイコンを常駐させる「ヒント」を使い分けられます
- カスタマイズ性が高い - ボタンのラベル、進捗バー、テーマ、コールバックなど細かく制御できます
なお、ライセンスはAGPLv3と商用ライセンスのデュアルライセンスです。オープンソースプロジェクトでは無料で使えますが、商用プロダクトに組み込む場合は商用ライセンスの購入が必要になる点だけ注意してください。
インストール
npmまたはyarnでインストールできます。
# npm
npm install intro.js --save
# yarn
yarn add intro.js
ビルドツールを使わない場合は、CDNから直接読み込むこともできます。
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/intro.js/minified/introjs.min.css">
<script src="https://cdn.jsdelivr.net/npm/intro.js/minified/intro.min.js"></script>
npmで導入した場合は、次のようにインポートします。
import introJs from "intro.js";
import "intro.js/introjs.css";
基本的な使い方
Intro.jsのツアーは2通りの方法で定義できます。まずは最も手軽な、HTML属性を使う方法から見てみましょう。
HTML属性でステップを定義する
案内したい要素にdata-intro(説明文)とdata-step(表示順)を付けます。
<header data-intro="ここがダッシュボードのヘッダーです" data-step="1">
<h1>My Dashboard</h1>
</header>
<nav data-intro="メニューはこちらから切り替えられます" data-step="2">
...
</nav>
<button data-intro="データの追加はこのボタンから行います" data-step="3">
新規作成
</button>
あとはJavaScriptで1行実行するだけです。
introJs.tour().start();
これだけで、オーバーレイ付きのハイライトとツールチップが順番に表示されるツアーが完成します。拍子抜けするほど簡単です。
JavaScriptオブジェクトでステップを定義する
マークアップを汚したくない場合や、ステップを動的に組み立てたい場合は、setOptions()にステップの配列を渡す方法が使えます。
introJs.tour().setOptions({
steps: [
{
title: "ようこそ!",
intro: "このアプリの使い方を30秒でご案内します 👋"
},
{
element: document.querySelector("#sidebar"),
title: "ナビゲーション",
intro: "各機能へはこのサイドバーから移動できます"
},
{
element: document.querySelector("#create-button"),
title: "最初の一歩",
intro: "まずはここから最初のプロジェクトを作ってみましょう!"
}
]
}).start();
elementを省略したステップは、画面中央にモーダル風に表示されます。ツアーの冒頭の挨拶や締めのメッセージに便利です。
日本語UIにカスタマイズする
デフォルトのボタンは「Next」「Back」「Done」と英語表記なので、日本語アプリでは差し替えましょう。進捗バーの表示などもオプションで制御できます。
introJs.tour().setOptions({
nextLabel: "次へ",
prevLabel: "戻る",
doneLabel: "完了",
showProgress: true, // 進捗バーを表示
showBullets: false, // ドットのページネーションを非表示
exitOnOverlayClick: false, // オーバーレイのクリックで閉じない
steps: [ /* ... */ ]
}).start();
実践的なユースケース
ここからは、実際のプロダクトで使えるパターンを紹介します。
初回訪問時だけツアーを表示する
オンボーディングツアーで最も多い要件が「初回だけ表示したい」です。localStorageと組み合わせれば簡単に実現できます。
import introJs from "intro.js";
import "intro.js/introjs.css";
const TOUR_KEY = "dashboard-tour-done";
function startOnboardingTour() {
if (localStorage.getItem(TOUR_KEY) === "true") {
return; // すでに見たユーザーには表示しない
}
introJs.tour()
.setOptions({
nextLabel: "次へ",
prevLabel: "戻る",
doneLabel: "はじめる",
showProgress: true,
steps: [
{ title: "ようこそ!", intro: "初回だけ簡単なツアーをご案内します" },
{ element: document.querySelector("#search"), intro: "検索はここから" },
{ element: document.querySelector("#settings"), intro: "設定はこちらです" }
]
})
.onComplete(() => {
localStorage.setItem(TOUR_KEY, "true");
})
.onExit(() => {
// 途中離脱でも再表示しない場合はこちらでも保存
localStorage.setItem(TOUR_KEY, "true");
})
.start();
}
startOnboardingTour();
onCompleteは最後まで見終わったとき、onExitはEscキーなどで途中終了したときに呼ばれます。なお、v8にはdontShowAgainオプションも用意されており、「次回から表示しない」チェックボックスをツアー自体に組み込むこともできます。
機能リリース時のアナウンスに使う
新機能をリリースしたとき、その機能だけを1ステップでハイライトするのも効果的です。
introJs.tour()
.setOptions({
doneLabel: "試してみる",
steps: [
{
element: document.querySelector("#export-button"),
title: "🎉 新機能:エクスポート",
intro: "作成したレポートをPDFで出力できるようになりました!"
}
]
})
.onComplete(() => {
document.querySelector("#export-button").focus();
})
.start();
ヒントモードで「押しつけない」ガイドを作る
ツアーは強制的に画面を占有するため、人によっては煩わしく感じます。そこで使えるのがヒント(Hints)モードです。要素の横に小さなパルスアイコンを表示し、ユーザーがクリックしたときだけ説明を出します。
<button data-hint="ここからテーマを切り替えられます" data-hint-position="bottom-right">
🌙
</button>
introJs.hint().addHints();
「知りたい人だけが知れる」控えめなガイドなので、ツアーと組み合わせて「初回はツアー、以降はヒント」という設計にすると、しつこさのないオンボーディングが実現できます。
Reactで使う
Reactの場合は、useEffect内でツアーを起動し、対象要素はrefではなくセレクタで指定するのが手軽です。
import { useEffect } from "react";
import introJs from "intro.js";
import "intro.js/introjs.css";
export function DashboardTour() {
useEffect(() => {
const tour = introJs.tour().setOptions({
nextLabel: "次へ",
prevLabel: "戻る",
doneLabel: "完了",
steps: [
{ element: "#chart-area", intro: "売上の推移がここに表示されます" },
{ element: "#filter-panel", intro: "期間の絞り込みはこちら" }
]
});
tour.start();
return () => {
tour.exit(true); // アンマウント時にツアーを閉じる
};
}, []);
return null;
}
Reactに特化した公式ラッパーとしてintro.js-reactも公開されているので、宣言的に書きたい場合はそちらも検討してみてください。
まとめ
Intro.jsを使えば、これまで「作るのが面倒で後回しにしていた」プロダクトツアーを、数行のコードで導入できます。ポイントを振り返りましょう。
data-intro属性を付けてintroJs.tour().start()を呼ぶだけでツアーが動くsetOptions()でステップをJSONとして定義すれば、マークアップを汚さず動的な制御も可能onCompleteやonExitのコールバックとlocalStorageで「初回だけ表示」が実現できる- 押しつけがましくないヒントモードとの使い分けが効果的
- 商用利用時はライセンス(AGPLv3 / 商用デュアル)に注意
どんなに優れた機能も、ユーザーに見つけてもらえなければ存在しないのと同じです。まずは自分のアプリの「最初の3ステップ」をツアーにするところから試してみてはいかがでしょうか。
