インラインでSVGを複数書くときはstyleに注意

最近SVGにはまってます。
最初は丸とか三角しか描けなかったけど pathも覚えていろいろ描けるようになると レイヤー構成とか部品化とかを凝り始めるようになります。
そんなことをやってたらstyleまわりでちょっとハマったのでメモ。

1つのHTMLに複数のSVGがある状態

こんな感じのHTMLです。

<!DOCTYPE html>
<svg
  xmlns:svg="http://www.w3.org/2000/svg"
  xmlns="http://www.w3.org/2000/svg"
  viewBox="0 0 100 100">
  <defs>
    <style>
    .line {
      fill: blue;
    }
    </style>
  </defs>
  <rect class="line" x="10" y="10" width="80" height="80" />
</svg>

<svg
  xmlns:svg="http://www.w3.org/2000/svg"
  xmlns="http://www.w3.org/2000/svg"
  viewBox="0 0 100 100">
  <defs>
    <style>
    .line {
      fill: red;
    }
    </style>
  </defs>
  <circle class="line" cx="50" cy="50" r="40" />
</svg>

上に青い四角、下の赤い丸を書いたつもりです。 これをposition:absolute;で描画したらレイヤー表示になる!やったー。 と思ったら。

実際の表示は赤一色

なんでだよ!! 上の四角は青にしただろ!!

どうやらSVG内のstyleはグローバル汚染してるっぽい

SVGの中にstyle書けばSVG内のスコープで有効かと思ったらグローバル汚染してるみたい。 だから下の丸でlineクラスを定義したタイミングで赤に上書かれる。。 まぁSVGもHTMLの一部だと思えば当たり前なんですがなんか辛い。。

とりあえずsvgタグにid付けて逃げる

こんな感じ。

<!DOCTYPE html>
<svg id="rect"
  xmlns:svg="http://www.w3.org/2000/svg"
  xmlns="http://www.w3.org/2000/svg"
  viewBox="0 0 100 100">
  <defs>
    <style>
    #rect .line {
      fill: blue;
    }
    </style>
  </defs>
  <rect class="line" x="10" y="10" width="80" height="80" />
</svg>

<svg id="circle"
  xmlns:svg="http://www.w3.org/2000/svg"
  xmlns="http://www.w3.org/2000/svg"
  viewBox="0 0 100 100">
  <defs>
    <style>
    #circle .line {
      fill: red;
    }
    </style>
  </defs>
  <circle class="line" cx="50" cy="50" r="40" />
</svg>

これで想定通りの表示ができる。

めでたし。めでたし。