まくろぐ
更新: / 作成:

多数のデータを svg 要素を使用してプロットする場合、ブラウザの画面全体に svg 要素を広げて表示したいケースがあります。 このような場合、別の HTML 要素(ページタイトルや操作パネルなど)は、svg 要素の上に重ねて表示する必要があります。 ここでは、その方法として、svg 要素を背景として表示する方法と、他の要素を相対的に配置する方法の 2 つを紹介します。

svg 要素を背景として表示する方法 (position: fixed)

この例では、svg 要素を position: fixed スタイルを用いて、画面全体に固定表示しています。 通常、position: fixed スタイルは、ウェブサイトのヘッダーを画面上部に固定する用途などで使用されますが、これを svg 要素に適用することで、背景画像のような効果を得ることができます。 svg 以外の要素は、まるで svg 要素が存在しないかのようにレイアウトされます。 position: fixed スタイルが適用された svg 要素は、デフォルトでは他の要素よりも前面に表示されてしまうため、これを背面に配置するために z-index: -1 を指定しています。

HTML
<svg>
  <circle cx="40" cy="40" r="25" fill="royalblue" />
  <circle cx="100" cy="40" r="25" fill="indigo" />
  <circle cx="160" cy="40" r="25" fill="darkslateblue" />
  <circle cx="220" cy="40" r="25" fill="darkmagenta" />
</svg>
<p>
  この p 要素の後ろに、svg 要素がページ全体に表示されています。
</p>
CSS
* {
  margin: 0;
  box-sizing: border-box;
}

svg {
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  background: midnightblue;
  z-index: -1;  /* 他の要素より奥に表示 */
}
☝️ マウスイベントを透過させる

svg 要素の上に重なった p 要素上でのマウスイベントを svg 要素に伝播するには、p 要素に pointer-events: none を指定します。

p {
  pointer-events: none; /* マウスイベントを伝播させる */
  /* ... */
}

注意点として、前述の svg 要素のように z-index に負の値が設定されていると、うまく svg 要素にマウスイベントが伝わりません。 これは、body 要素のデフォルトの z-indexauto (0) に設定されているため、p 要素から伝播されたマウスイベントが先に body 要素で消費されてしまうからです。 この問題を解決するには、マウスイベントの伝播先である svg 要素の z-index を 0 以上に設定し、その上に表示する p 要素をそれよりも大きな z-index に設定します(あるいは、svg 要素よりも p 要素を後に配置します)。

svg {
  position: fixed;
  z-index: 0;  /* デフォルトで auto=0 なので省略しても OK */
  /* ... */
}

p {
  position: relative;
  z-index: 1;  /* 確実に svg の上に表示するなら指定しておく */
  pointer-events: none;  /* マウスイベントを伝播させる */
  /* ... */
}

あるいはちょっと特殊ですが、body 要素の z-index を一番奥にして、body 要素でのマウスイベントの処理を後回しにするという方法もあります。

svg {
  position: fixed;
  z-index: -1;  /* svg は他の要素よりも奥に表示 */
  /* ... */
}

body {
  position: relative;
  z-index: -100;  /* body 要素でのマウスイベント処理は後回し */
}

p {
  pointer-events: none;
}

他の要素を親要素の相対座標で配置する方法 (position: absolute;)

position: absolute スタイルを指定すると、親要素の位置からの相対座標で表示できるので、これを利用して svg 要素の上に他の要素を重ねて表示することができます。 子要素に position: absolute を指定する場合は、親要素にも何らかの position 指定(下記例では position: relative)が必要なことに注意してください。

HTML
<p>これは svg の外側に配置する要素。</p>

<div id="container">
  <svg>
    <circle cx="40" cy="40" r="25" fill="royalblue" />
    <circle cx="100" cy="40" r="25" fill="indigo" />
    <circle cx="160" cy="40" r="25" fill="darkslateblue" />
    <circle cx="220" cy="40" r="25" fill="darkmagenta" />
  </svg>
  <div id="overlay">
    <p>この裏に svg 要素が表示されています。</p>
  </div>
</div>

<p>これも svg の外側に配置する要素。</p>
CSS
#container {
  position: relative;  /* 子要素で absolute 指定するため */
  width: calc(100vw - 3rem);
  height: 80px;
  margin: auto;
}

svg {
  width: 100%;
  height: 100%;
  background: midnightblue;
}

#overlay {
  position: absolute;  /* 親要素を基準にして配置する */
  top: 0;
  left: 0;
  color: #ddd;
}

(おまけ)svg 内に foreignObject を埋め込む方法

svg 要素内に foreignObject 要素を配置することで、HTML の p 要素などを配置できます。

<svg style="background: darkblue;">
  <circle cx="40" cy="40" r="25" fill="royalblue" />
  <circle cx="100" cy="40" r="25" fill="indigo" />
  <circle cx="160" cy="40" r="25" fill="darkslateblue" />
  <circle cx="220" cy="40" r="25" fill="darkmagenta" />

  <foreignObject x="0" y="0" width="100%" height="100%">
    <p xmlns="http://www.w3.org/1999/xhtml">
      この p 要素は svg 要素内に配置されています。
    </p>
  </foreignObject>
</svg>

ただし、foreignObject 内に配置された HTML 要素は、外部の HTML 要素とは異なるレンダリングコンテキストで扱われるため、異なる見た目になる可能性があることに注意してください。

(おまけ)かっこいい透過コントロールパネル

svg 要素の上にコントロールパネルなどを表示する場合、アルファ値を設定した背景色でパネル表示するとかっこいい感じになります。

関連記事

まくろぐ
サイトマップまくへのメッセージ