IT系おじさんのチラシの裏
2018年10月~
当サイトの記事にはアフィリエイト広告のリンクが含まれる場合があります

JavaScriptとCSSでヘルプボタンと凡例(ツールチップ)表示をする例

前回は「JavaScriptで入力フォームにふきだしのようなツールチップを表示する例」と題して、入力フォームでそれぞれの項目の横にポップアップするツールチップを表示してみましたが、今度は入力パーツがない場合にも使えるヘルプボタンを実装してみたいと思います。

サンプル

見たほうが早いと思うので、早速サンプル。下の丸いハテナアイコンをクリックまたはタップすると凡例表示されます。

?
■凡例
🍎 りんご
🍌 バナナ
🍈 メロン

マウスカーソルを載せたときに表示するような従来のツールチップでも良いのですが、前回の記事でも書いたとおり、最近はPCとスマホの両方に対応するのが当たり前になっているので、クリック(タップ)で表示する形にしてみました。

表示された凡例(ツールチップ)はページのどこでも良いのでクリック(タップ)すると消えます。

HTMLの例

<div class="help_area">
	<div class="help_icon">?</div>
	<div class="tooltip">
		■凡例<br>
		🍎 りんご<br>
		🍌 バナナ<br>
		🍈 メロン<br>
	</div>
</div>

タグは何でも良いのですが、できるだけシンプルに、かつ多少は汎用性があるようにと考え、help_areaという枠(div)の中にアイコン(help_icon)とツールチップ(tooltip)を含める形にしました。

ヘルプボタンですから、1ページ中に複数置く場合もあるでしょうし、ID指定ではなくクラス名での指定です。

CSSの例

<style>
.help_area {
	position:relative;
}
.help_icon {
	border-radius:50%;
	width:20px;
	height:20px;
	line-height:20px;
	vertical-align:middle;
	font-size:12px;
	text-align:center;
	background-color:#888888;
	color:white;
	cursor:pointer;
}
.tooltip {
	position:absolute;
	background-color:rgba(0,0,0,0.5);;
	color:white;
	border-radius:0.3em;
	padding:0.3em;
	margin:0.3em 0 0 1em;
	display:none;
}
</style>
CSSもシンプルです。

ヘルプアイコンとツールチップを囲んでいる枠はposition:relative;を設定し、ツールチップがその付近に表示されるようにしています。

ヘルプアイコンは20x20pxのサイズで、border-radius:50%;を指定することで丸くしている感じですね。
あんま格好良くないので、実際に使う場合はフリー素材で配布されているSVG形式のアイコンとか使うと良いと思います。

それからツールチップの外観は角丸にしただけの矩形。ふきだしで使うような三角を付けても良かったのですが、CSSが長くなると見ている人がウンザリするかなと思って外しましたw

JavaScriptの例

<script>
document.querySelectorAll('.help_icon').forEach (elm => {
	elm.onclick = function () {
		event.stopPropagation();
		let tooltip = this.parentNode.querySelector('.tooltip');
		if (tooltip.style.display == 'block') {
			tooltip.style.display = 'none';
		} else {
			tooltip.style.display = 'block';
		}
	};
});
document.body.onclick = function () {
	document.querySelectorAll('.tooltip').forEach (tooltip => {
		tooltip.style.display = 'none';
	});
};
</script>

大したことはやっていませんが、一応本命(?)のJavaScript。

前回の例でも querySelectorAll での要素取得は行いましたが、見つかった各要素に対してイベントを設定するのは

for (let i = 0; i < elms.length; i++) { }

のような、よく言えば見慣れた、ぶっちゃけるとなんとなくダサい書き方をしていました。

ので、今回は

document.querySelectorAll('.help_icon').forEach (elm => { } );

というように、forEachで格好つけてみました。特に深い意味はありませんw

どちらかというと大事なのはこの stopPropagation の部分ですかね。

event.stopPropagation();

ヘルプボタンを押す→ツールチップを表示
ヘルプボタンをもう一度押す→ツールチップを非表示

これはわかりやすくて良いのですが、スペースの都合上、ヘルプボタンって小さくせざるを得ないじゃないですか。

それなのにツールチップ表示中にもう一度小さなヘルプボタンを押すのは(画面サイズによっては)なかなかやりづらいでしょう。

凡例表示しているツールチップをクリックすることで閉じる、という動作でも良いのですが、どうせなら画面のどこをクリック(タップ)しても非表示になったほうが直感的じゃないですかね?

そんなふうに考えて、bodyのクリックイベントでツールチップを消すようにしました。

document.body.onclick = function () {
	document.querySelectorAll('.tooltip').forEach (tooltip => {
		tooltip.style.display = 'none';
	});
};

が、しかし、これだけではすべてのクリックイベントをbodyがひろってしまうので、ツールチップを表示するためにヘルプボタンを押したときにもこのイベントが実行され、ツールチップが開く→即閉じる という動作になります。

イベントバブリングってやつですね。

そんなわけで、子要素で発生したクリックイベントを親要素へ伝搬させないよう、stopPropagation();を実行しています。

まとめ

ググればそこら中にあるようなサンプルだと思いましたが、最近の流行りはCSSだけでツールチップを再現する方法のようで、labelタグと非表示にしたチェックボックスを使う例がゴロゴロ見つかりました。

…でも、あのやり方ってちょっとわかりづらくないですかね。:hoverで色変えるくらいならCSSでも良いのですが、:checkedでツールチップを表示したり非表示にしたりというのまでCSSでやるのは少し可読性が良くないかなぁ、と感じました。まぁJavaScriptのほうが見慣れているから、というだけの話かも知れませんw

いずれにせよ、ドヤ顔で公開するようなスクリプトではございませんが、この記事がどこかの誰かのお役に立てば幸いです。

関連記事

簡単なJavaScriptとCSSで横並びプルダウンを自作する

Web上の入力フォームにおいて、よく使われるプルダウンのお話です。 つい先日も、「PHPで日付の表記ゆれを修正する例」で選択肢が多い場合のプルダウン※の使いづらさについて少し触れました。 ※V

コメント

  • 問い合わせフォームより下記のような質問がありましたが、同じことで悩んでいる方もいらっしゃるかも知れないため、コメント欄にて回答させて頂きます。

    > フローティング表示をした後、そのルーツチップの中にリンクを置きたい
    > →リンクをクリック(タップ)しても消えないようにしたい
    > →閉じるボタン等の画像や文字を押下する事で閉じれるようにしたい
    > →画面のどこを押下しても消えるという動作を無くしたい

    画面のどこかを押下したらツールチップが消える、という動作はbodyのonclickイベントで実装しているため、下記の記述を丸ごと削除するだけで実現可能です。
    document.body.onclick = function () { /* 省略 */ }

    閉じるボタンについては普通にツールチップのDIVタグの中に実装すれば良いかと思います。

    一例)
    &lt;button onclick="this.parentNode.style.display='none';"&gt;閉じる&lt;/button&gt;

    [返信]

新しいコメントを投稿する

[新規投稿]
 
TOP