質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.12%

SVGをuseで読み込んだ部分にCSSを適用したい

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 3,492

kihara

score 36

 前提・実現したいこと

HTMLに直接埋め込んだインラインSVGスプライトの中のSVGの一部を使用したいのですが、
下記のコードの「#none」の部分を非表示にしようと、
「display:none」をしたのですが消えてくれません。
「#block」の部分だけを「use」で読み込めばいいのかと思いやってみると、
サイズが小さくなってしまいます。

また他の部分でも使用したいため、SVGそのものにスタイルを適用させることは出来ません。

「use」で読み込んだSVGにはCSSを適用させることは出来ないのでしょうか。
詳しい方教えていただけると助かります。

 コード

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
* {
    margin: 0;
    padding: 0;
}
.a svg {
    width: 500px;
    height: 500px;
    fill: red;
}
.a #none {
    display: none;
}
.a #block {
    width: 100%;
    height: 100%;
}
#block {
    fill: #000;
}
</style>
</head>
<body>
<svg aria-hidden="true" style="position: absolute; width: 0; height: 0; overflow: hidden;" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
  <defs>
    <symbol id="svg" viewBox="0 0 35 32">
      <title>svg</title>
      <!--この#noneを消したい-->
      <g id="none">
        <rect width="342" height="342"/>
      </g>
      <!--この#blockだけを表示したい-->
      <g id="block">
        <polygon points="43.3,0 0,75 86.6,75 "/>
      </g>
    </symbol>
    <!--
その他....
<symbol viewBox="0 0 35 32">...</symbol>
...
-->
  </defs>
</svg>
<div class="a">
  <svg>
    <use xlink:href="#svg"/>
  </svg>
  <svg>
    <use xlink:href="#block"/>
  </svg>
</div>
</body>
</html>
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+1

id="none"を消すのではなく、id="block"<symbol>として定義してあげて、id="block"<use>で呼ぶのはいかがでしょうか。<use> にidなりclassなりをつければ、スタイルを期待通りに適用できるはずです。<symbol id="svg">の中でも<use>で参照できますので、定義は1回で済みます。

<svg style="display:none">
  <defs>
    <symbol id="none">
      <rect width="342" height="342"/>
    </symbol>
    <symbol id="block">
      <polygon points="3,0 0,10 10,6"/>
    </symbol>
    <symbol id="svg" viewBox="0 0 10 10">
      <use xlink:href="#none"/>
      <use xlink:href="#block" fill="#000"/>
    </symbol>
  </defs>
</svg>
<div class="a">
  <svg class="a1" viewBox="0 0 10 10">
    <use xlink:href="#svg" x="0" y="0"/>
  </svg>
  <svg class="a2" viewBox="0 0 10 10">
    <use xlink:href="#block" x="0" y="0"/>
  </svg>
  <svg class="a3" viewBox="0 0 20 20">
    <use xlink:href="#block" x="0" y="0"/>
  </svg>
  <svg class="a4" viewBox="0 0 30 30">
    <use class="a4-1" xlink:href="#block" x="10" y="10"/>
    <use class="a4-2" xlink:href="#block" x="0" y="10"/>
    <use class="a4-3" xlink:href="#block" x="0" y="0"/>
  </svg>
</div>

で、たとえば以下のCSSにすると、

.a1 {
  fill: red;
}
.a2 {
  fill: blue;
}
.a3 {
  fill: green;
}
.a4 {
  fill: purple;
}
.a4-2 {
  fill: gold;
}
.a4-3 {
  fill: gray;
}

こうなります。

イメージ説明

以下で動作確認できます。大きさについてはviewBoxxyの指定で解決するのではないかと思います。
https://codepen.io/anon/pen/JpGwZG
Firefox(Win/Mac)、Chrome(Win/Mac)、Safari(Mac)、IE11(Win)、Edge(Win)では、大丈夫でした。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+1

CSSの記述に問題があります.

.a #none {
    display: none;
}


につき, .aクラスの配下にid="none"という要素が存在していない以上, このスタイルが有効となることはありません. use要素はあくまでsymbol要素を参照しているだけであり, symbol要素の中身がコピーされている訳ではないからです. 


use」で読み込んだSVGにはCSSを適用させることは出来ないのでしょうか。

条件付きですが可能です. 

ですが, その動作を制御するにはSVGにおけるスタイル付けの優先順位およびuse要素の振る舞いを理解する必要があります.


A. SVGにおけるスタイル付けの優先順位は以下のとおりです.

  1. 通常のCSSにおける優先順位(style属性, style要素, !important指定等)
  2. プレゼンテーション属性によるスタイルの指定(fill="red"等)
  3. 親要素のスタイル(当該プロパティがinherit値をとりうる場合)

NOTE:
つまりHTMLにおけるスタイル付けの優先順位と全く同じです.

B. use要素はレンダリング上その位置に(仮想的に)g要素/svg要素(symbol要素を参照している場合)が存在しているように振る舞います. (その要素の中にuse要素が参照するノードツリーが存在するように振る舞うのです.)

以上を踏まえた上で, 次のコードを見てみましょう.

<svg width="0" height="0">
    <defs>
        <symbol id="s" viewBox="0 0 10 10" width="100" height="100">
            <rect width="5" height="5"/><!--図形a-->
            <rect x="5" height="5" width="5" height="5" fill="red"/><!--図形b-->
        </symbol>
    </defs>
</svg>
<svg>
    <use xlink:href="#s" x="0" width="100" height="100"/><!--use1-->
    <use xlink:href="#s" x="100" width="100" height="100" style="fill:blue;"/><!--use2-->
</svg>

ここでは二つのuse要素がsymbol要素#sを参照しており, 片方にはfill="blue"が指定されています. また, symbol要素配下のrect要素の片方にはfill="red"が指定されています.

これをWEBブラウザで表示すると, use2の方の図形aにあたる部分が青く塗りつぶされることになります. この理由は次のとおりです.

  1. use2を描画する際, use2配下にsymbol#sが存在しているものとして扱う.
  2. 仮想の図形aを描画する際, 塗りつぶしスタイルfillの値を求める必要がある.
  3. 図形aにはスタイルが未指定(重要)であるため, inherit値が設定されているものとして扱われるため, 親要素のfill値が参照される.
  4. その際, 仮想の図形a要素の親にuse要素が存在しているので, このuse要素に設定されているfill:blue;が実際の塗りつぶし色として選択される.

かくして, use要素が参照している内容に対しても(use要素を介して間接的に)CSSによるスタイル付けが可能です.

NOTE:
このことから判るように, use要素に対するスタイル指定(単一の値)を内部に伝播する都合上, 複数の塗りつぶし色を外部から与えたいケースには(このままでは)対処できません.

NOTE:
use{display: none;}ではuse要素そのものがレンダリング上存在しないこととなり, グラフィックの一部を消す目的には使えません. 従ってその代替としてfill:nonefill:transparentfill:rgba(0,0,0,0)等を用いることになります.


以上を踏まえてもう一度SVGの構造を見直して下さい.

NOTE:
use要素の制御はSVGを扱う上で最も困難な箇所ですので, どうしてもうまく行かない場合は(不本意ながら)use要素の利用を諦めるのも一つの選択肢です.
ブラウザの種類・バージョン毎にuse要素の実装が異なることもあり, SVG単体では対処できないケースもあるからです.


追記)

「#block」の部分だけを「use」で読み込めばいいのかと思いやってみると、
サイズが小さくなってしまいます。 

symbol要素を介さず直接図形をuse要素で参照したため, 元の図形のサイズで表示されています.

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.12%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる