Web制作

【SVG】SVG画像にリンクが貼れなくてハマった!時の解決方法

SVG画像にリンクが貼れなくてハマった!時の解決方法

レスポンシブは当たり前、Retina対応もだんだんと進んできた今、SVG画像は非常に優秀ですよね。
拡大しても縮小しても綺麗なベクター画像なので、どんどん使っていきたい。
でも実装の方法が微妙に複雑・・・。
今回はリンク周りで少しハマったのでその対処法を書きたいと思います。

この記事の目次

SVGの実装方法

SVGを表示する方法は1つではありません。いくつかあるのでそれぞれ簡単にご紹介します。

HTMLに直接インライン

HTMLに直接インラインで記述する方法です。
svg開始タグ~svg終了タグをコピペするだけですので簡単ですが、複雑なSVGファイルの場合はHTMLソースがとんでもなく長くなり、メンテナンスがしづらくなります。

imgタグのsrc属性

jpgやpng同様、普通に画像として読み込む方法です。
ただ、画像要素として扱われるらしく、SVGファイル内のpath要素にCSS、JSが効かなくなるようです。

CSSのbackgroundプロパティ

imgタグで読み込む方法同様、画像として扱われるため、SVGファイル内のpath要素にCSS、JSが効かなくなるようです。
imgタグでの実装もCSSのbackgroundプロパティでの実装も画像として扱われますが、そこはちゃんとSVG画像ですので拡大・縮小はキレイに行われます。特別何もしないのであればこれらの実装方法で問題ありません。

object要素のdata属性

別ドキュメントをiframeで表示しているような動作になり、SVGへCSSやJSを適用させるにはその別ドキュメントに対して適用させないといけません。
object要素の中にimg要素で代替画像を配置しておけば、SVG対応ブラウザにはsvg画像を、非対応ブラウザには代替画像を表示させることが可能です。現時点ではこの方法が利用しやすいのかなと思います。

SVG画像にリンクを設定する

普通の画像のようにaタグでリンクを設定しようとするとハマります。ハマりました(;´Д`)・・・。
ハマりどころがいくつかあるので1つずつ見ていきますね。

  • リンクを設定したのにクリックできない
  • SVG領域内だけが別ページに飛ぶ

リンクを設定したのにクリックできない

原因はobject要素の仕様にあるようです。1つはaタグなどのインライン要素内で使われるとそれを踏襲して自身もインライン要素として扱われるため高さの概念がなくなり、クリックする領域が確保できない。もう1つはobject要素が親要素であるaタグを覆ってしまい、aタグをクリックすることができないことに由来します。
これ初めて知りました。

実装方法についてWebクリエイターボックスさんでも紹介されていました。
SVGアイコンを実用するために知っておきたい、リンク周りの記述方法 | Webクリエイターボックス

SVGにリンクを貼りたい場合、単純にaタグでsvgを囲んでもうまくリンクを貼ることはできません。svgタグの中のオブジェクトをaタグで囲み、xlink:href属性でURLを指定する必要があります。

上記の方法は直接インラインで記述する実装方法です。
object要素で読み込んで表示している場合は、落ち着いてSVGファイル自体をエディタで開き、同様に次のように編集します。

<svg ...>
<a xlink:href="sample.com">
(元々あったSVGファイルの内容)
</a>
</svg>

こんな感じでaタグで囲めばOKです。

SVG領域内だけが別ページに飛ぶ

しかしここで注意が必要です。
そのままhrefでリンク先だけ書くと飛んだ後にobjectで囲んでいた範囲だけiframeのような動作になり、おかしなことになります。なのでaタグの属性にtarget="_top"を付けることを忘れないようにしましょう。
また、この方法だとSVGのパス上しかクリックできない点も注意が必要です。

もっと良い方法ないの!?CSSの指定で解決する方法

上の方法だとイチイチsvgファイルを編集しないといけないですし、問題がありますよね。
そこでCSSさえ指定しておけばHTMLの編集だけで実装できるようにします。

<a class="sample01" href="/">
	<object type="image/svg+xml" data="/SVGファイルまでのパス/sample.svg" width="幅" height="高さ">
		<img src="/代替画像ファイルまでのパス/sample.png" width="幅" height="高さ" alt="サンプル">
	</object>
</a>

object要素をa要素で囲んでいるだけのシンプルな構造です。代替画像が必要なければobject要素内のimg要素は必要ありません。

.sample01{
	display: inline-block;
}

.sample01 object{
	pointer-events: none;
}

object要素に対してpointer-eventsをnoneにしてやります。これで覆っていたobject要素のクリックが無効となるのでa要素のクリックが有効になります。

こちらの記事が非常に分かりやすく、参考にさせていただきました。

Retina対応にSVGを使う方法とリンクを張る時の注意点 - ROCHAS

管理人「よら」はこう思う

ハマりポイントが多いSVG。もっと簡単に使えると嬉しいんですけどね。

それでも使用を検討する場合はソースも可読性も良いですし、SVGアニメーションを使う機会も今後は増えてくるかもしれないので、object要素での実装が良さそうです。

ナニモノリンク
黒門のココだけの話