多数のデータを svg
要素を使用してプロットする場合、ブラウザの画面全体に svg
要素を広げて表示したいケースがあります。
このような場合、別の HTML 要素(ページタイトルや操作パネルなど)は、svg
要素の上に重ねて表示する必要があります。
ここでは、その方法として、svg
要素を背景として表示する方法と、他の要素を相対的に配置する方法の 2 つを紹介します。
svg 要素を背景として表示する方法 (position: fixed)
この例では、svg
要素を position: fixed
スタイルを用いて、画面全体に固定表示しています。
通常、position: fixed
スタイルは、ウェブサイトのヘッダーを画面上部に固定する用途などで使用されますが、これを svg
要素に適用することで、背景画像のような効果を得ることができます。
svg
以外の要素は、まるで svg
要素が存在しないかのようにレイアウトされます。
position: fixed
スタイルが適用された svg
要素は、デフォルトでは他の要素よりも前面に表示されてしまうため、これを背面に配置するために z-index: -1
を指定しています。
<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>
* {
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-index
が auto
(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
)が必要なことに注意してください。
<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>
#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
要素の上にコントロールパネルなどを表示する場合、アルファ値を設定した背景色でパネル表示するとかっこいい感じになります。