CSSでクリッカブルマップのように画像へ注釈を入れる例
お仕事関係で、Webページに載せる写真に複数の注釈コメントを入れる作業が発生したのですが、この写真がそこそこの数ありまして、すべての写真を編集するのは面倒くさいなぁ… ということでCSSで実現してみました。
先日投稿した「CSSで画像の上に文字を重ねて表示する例」の応用みたいなものですが、備忘録を兼ねて記事にしておきます。
CSSで写真の上に複数の注釈を貼る例
表示サンプル
HTML例
<dl class="sample1">
<dt><img src="[画像ファイル]" /></dt>
<dd style="top:25%;left:20%;"><a href="#">マイク</a></dd>
<dd style="top:17%;left:62%;"><a href="#">ケーブル</a></dd>
<dd style="top:60%;left:64%;"><a href="#">スタンド</a></dd>
</dl>
CSS例
.sample1 {
position:relative;
width:500px;
max-width:100%;
}
.sample1 img {
width:100%;
}
.sample1 dd {
position:absolute;
color:white;
font-weight:bold;
background-color:rgba(0,0,0,0.5);
}
.sample1 dd a {
color:white;
text-decoration:none;
}
.sample1 dd a:hover {
color:red;
}
解説
「CSSで画像の上に文字を重ねて表示する例」ではfigureタグとfigcaptionで画像の上に文字を重ねましたが、HTMLの文法的にfigureの中にfigcaptionはひとつだけ、という制限があります。
そのため、今回はdl, dt, ddタグで実現してみました。dtの内容をddで説明するリスト、という意味合いがあるのでちょうど良いかなぁと。
dlのCSS部分については前回同様、position:relative;で親要素であることを指定。width:500px;max-width:100%;という指定にしているのは画像の横幅は500pxだけど、ページの横幅がそれ以下だったら、横幅一杯に表示してね、ということです。
ブラウザの幅に合わせてデザインを変える、今どきのレスポンシブな作り方というヤツですね。
ddのCSS部分についても前回と変わらず、position:absolute;で親要素を起点に座標指定するよ、というのが重要な部分。色とか文字の太さの指定については解説不要だと思うので端折ります。
ddの位置はtop/leftで座標指定するわけですが、CSS中に書くと後で座標をちょっと修正するときに面倒かなぁ、ということで、ddタグに直接style属性を書き、style="top:25%;left:20%;"みたいにHTML中に書いてしまっています。
尚、px指定ではなくパーセンテージで指定しているのはこれまたレスポンシブ対応のため。px指定しちゃうとスマホで見たときに文字の位置がズレちゃいますからね。画像の大きさから見て25%の位置、といった指定にしておけば小さい画面で見てもほとんどズレません。
また、画像サイズを幅500pxじゃなくて、200pxにしたい、あるいは逆に1000pxにしたい、なんて後で変更するかもしれないので、やっぱり文字位置はパーセントで指定しておくのが良いかと思います。
なぜクリッカブルマップを使わないのか
画像の任意の位置をクリックできるようにする、というと昔懐かしのクリッカブルマップが思い浮かぶと思いますが、あれはけっこう面倒くさいんですよね。
imgタグの下にmapタグを置き、そこに矩形で座標指定する。そこまでは良いのですが、指定できるのはクリックできる範囲だけであって、テキストを載せられるわけではないので、画像を編集してクリックできる文字やアイコンの類を埋め込まなければいけません。更にカーソルを乗せたときに色が変わるように、などと考え始めるともっと面倒になります。
というわけで、画像の上にCSSでテキストを配置したほうが、汎用性が高いかなぁと、先述のような実装にしてみました。
画像の上に線を引いて図解っぽくする例
もひとつオマケで、CSSで斜めの線を引いて図解っぽくする例も作ってみました。
表示サンプル
HTML例
<dl class="sample2">
<dt><img src="[画像ファイル]" /></dt>
<dd style="top:25%;left:20%;" class="arrow_down"><a href="#">マイク</a></dd>
<dd style="top:17%;left:62%;" class="arrow_down"><a href="#">ケーブル</a></dd>
<dd style="top:60%;left:64%;" class="arrow_up"><a href="#">スタンド</a></dd>
</dl>
CSS例
.sample2 {
position:relative;
width:500px;
max-width:100%;
}
.arrow_up,.arrow_down {
position:absolute;
color:white;
font-weight:bold;
width:22%;
text-align:right;
border-left:2px solid #40ff40;
}
.arrow_up {
border-bottom:2px solid #40ff40;
transform: skewX(-135deg);
}
.arrow_up a {
transform: skewX(135deg);
}
.arrow_down {
border-top:2px solid #40ff40;
transform: skewX(135deg);
}
.arrow_down a {
transform: skewX(-135deg);
top:-1.4em;
position:relative;
}
.arrow_up a,.arrow_down a {
display:block;
text-decoration:none;
color:#40ff40;
}
解説
基本となるposition関係は先述の例と変わらないので解説を省略します。
ポイントはddタグに追加したarrow_upクラスとarrow_downクラスですね。upは上向きの線、downは下向きの線のためのスタイルです。
斜め線の実現は transform:skewX(135deg); で135度(右45度)要素を傾斜させることで実現しています。border-leftで左側に縦線を引き、45度傾斜させたら斜めの線になりますよね? そういうことです。
でもそのままだとddに囲まれているaタグの文字まで斜めになってしまいます。なので、aタグのほうは transform:skewX(-135deg); として逆向きに傾けて元に戻しているというわけ。なんという強引な。
それから、下向きの線の場合は線の上に載るようにテキストを配置したかったので、position:relative;とtop:-1.4em;で1.4文字分、上に文字をズラしています。
わりと思いつきで書いた感じなので強引なところもある気もしますが、実現できればよかろうなのです。うん。
まとめ
- 画像の上に注釈を載せるにはposition:relative;とabsolute;を組み合わせて使う
- 注釈の座標指定はパーセントで指定しておくとレスポンシブ的にGood
- 注釈に矢印とかを付けたい場合はtransform:skewXなどでborder付きの要素を傾斜させると楽かも
- transformで傾斜させた後は文字の傾斜を戻すのも忘れずに
といったところでしょうか。
座標指定と聞くと面倒な気がするかも知れませんが、実務上ではこういった画像はデザイナーさんに依頼することが多く、クリック位置が変わるたびにデザイン変更の依頼をするのって面倒なんですよ…。
大抵のWebサイトはHTMLの編集を楽にするためのCMS(Contents Management System、要するにWordPressみたいな)が導入されているのでHTMLの編集はちゃちゃっとできても、画像ファイルの編集となるとちょっと時間を取られることも多いと思うのです。
少なくともうちの場合はそんな案件が多いので、できるだけCSSで済むと後々楽なんですよねー。
ではそんな感じで、この記事がどこかのエンジニアのお役に立てたなら幸いです。