web-dev-qa-db-ja.com

FireFoxでSVG塗りが適用されない

Firefoxがクラスの塗りつぶしの代わりにデフォルトのsvg塗りつぶし色を使用している理由を理解できないようです。

FFインスペクターを表示したときの3つの塗りつぶしは次のとおりです。

CSS

SVGは

<svg class="icon">
    <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#menu-bag"></use>
</svg>

白(.fff)の.skip-link .icon塗りつぶしが表示されているはずですが、実際には#002649のSVG塗りつぶしを使用しています。 .skip-link .iconを.skip-link svgに変更すると、正常に機能します。なぜクラスを使用できず、代わりに要素を明示的に述べることができないのですか?

FirefoxがSVGをどのように埋めるのか、明らかなことを見逃していますかこのCSSは他のブラウザでも問題なく機能します。

14
Gil

動作がバージョン56より前のFirefoxに固有の場合、それは#menu-bag<symbol>要素を参照しているためでした。

仕様によると、再利用された<symbol>ネストされた<svg> に置き換えられたかのように実装する必要があります。 FirefoxはシャドウDOMでこれを文字通り処理していた。シャドウDOMはDOMインスペクターでは表示されませんが、CSSセレクターの影響を受けます。

つまり、このコードは:

<a href="#" class="skip-link">
    <svg class="icon">
        <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#menu-bag"></use>
    </svg>
</a>

このように実装されたWA:

<a href="#" class="skip-link">
    <svg class="icon">  
        <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#menu-bag">
          <!--Start of shadow DOM boundary-->
          <svg><!-- replacement for <symbol> -->
             <!-- graphics content -->
          </svg>
          <!--End of shadow DOM boundary-->
        </use>
    </svg>
</a>

svg.icon.skip-link .iconルールと一致します(そして、カイルミットが指摘するように、そのルールは常にa:hover svgルールよりも優先されます)。この値は<use>要素にも継承されます。

ただし、shadow-DOM <svg>は、svgルールで直接スタイル設定されているため、継承された値を取得しません。セレクタを.skip-link svgに変更するか、a:hover svgルールをトリガーすると、非表示の内部要素にスタイルが直接適用されます。これは、そのSVGもリンクの子孫であるためです。

Robert Longsonがコメントで述べたように、これは、想定される動作ではありません。これは、Firefoxが完全に複製されたDOMツリーとして<use>要素を実装した方法の副作用であり、たまたまDOMインスペクターから非表示になっています。

これは、元の問題の「実際の」例です。つまり、Chrome、Safari、Opera、Firefox 56以降、またはIEにカーソルを合わせても変更されない緑色の円が表示されますが、バージョン56より前のFirefoxではホバー/フォーカスで赤に変わる青い円が表示されます。

svg {
    fill: navy;
}
a:hover svg, a:focus svg {
    fill: red;
}
.skip-link .icon {
    fill: green;
}
.icon {
    height: 50;
    width: 50;
}
 <a href="#" class="skip-link">
        <svg class="icon">
            <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#menu-bag" />
        </svg>
</a>
<svg height="0" width="0">
    <symbol id="menu-bag" viewBox="-10 -10 20 20">
        <circle r="10" />
    </symbol>
</svg>

では、Firefoxの古いバージョンをサポートする必要がある場合はどうすればよいでしょうか。 2つのオプションがあり、そのうちの1つは試行錯誤によってすでにわかっています。

  1. svgタグセレクターを使用してデフォルトのスタイルを設定することは避け、<use>要素からの通常のスタイル継承に依存します。

  2. Shadow -<svg>を意図的に選択するセレクターを使用してデフォルトをキャンセルし、他のブラウザーに意図した効果があることを確認します。

1つのオプションは、次のようなルールを使用することです。これにより、他のブラウザーに対する元のルールの特異性が維持されます。

.skip-link .icon, .skip-link .icon use>svg {
    fill: green;
}

use>svgセレクターは Firefoxのバグexceptを照合することはないため、副作用なしで安全に使用できます。 (元々、セレクタの最後にsvgを追加することをお勧めしましたが、状況によっては問題が発生する可能性があります。)

38
AmeliaBR

提供された@AmeliaBRの回答に基づくより普遍的なオプションは、次のように単に何かを行うことです。

svg use svg { 
    fill: inherit;
}

これにより、シャドウ要素が塗りつぶしの色を継承します。

3
Derek Story

Robertは、<use>が常に一貫して適用されるわけではないことは正しいです。確かに、SVGを画像として使用する場合、ページに追加したCSSルールを適用する方法がわかりません。

しかし、他にも要素のスタイルを決定できる要素がたくさんあるので、例が役立つかもしれません。

これが、議論の中心となるスタックスニペットです。

svg {
  fill: blue;
}
a:hover svg {
  fill: red;
}
.skip-link .icon {
  fill: purple;
}

.green {
  fill: green;
}
<a href="#" class="skip-link">
  <svg xmlns="http://www.w3.org/2000/svg"
       xmlns:xlink="http://www.w3.org/1999/xlink"
       class="icon" >

    <def>
      <text id="text" >use xlink</text>
      <text id="over" class="green">use xlink override</text>
    </def>
    
    <text x="5" y="15" >Plain</text>
    <use  x="5" y="30" xlink:href="#text" />

    <use  x="5" y="50" xlink:href="#over" />
    <text x="5" y="65" class="green" >class="green"</text>
    <text x="5" y="80" fill="orange" >fill="orange"</text>

  </svg>
</a>

特異性

SVG要素自体がいくつかの競合するルールでスタイル設定されています。勝つルールを決定するものは、[特異性と順序]に関係しています。この場合、SVG要素自体が紫色になります。たとえば、ホバーアンカールールは.skip-link .iconよりも限定的ではないため、表示されません。

SVG

継承

一部のプロパティは親からの継承を許可しますが、自分自身で指定されていない場合に限られます。仕様は、継承された値をオーバーライドします。質問がある場合、私の<svg>要素には特定のスタイルがありますが、すべての子要素に等しく適用されないのはなぜですか、答えは簡単です。子要素が独自の値を指定し、継承された値をオーバーライドすることは完全に問題ありません。

<text x="5" y="65" style="fill:green;" >class="green"</text>
<text x="5" y="80" fill="orange" >fill="orange"</text>

使用&Xlink

トリッキーな部分は、使用が関係するときに何が起こるかになります。この場合、実際に適用されているスタイルを追跡するのは難しい場合があります。を使用すると、xlink属性で識別される要素のインライン表現が作成されますが、この要素に直接アクセスすることはできません。したがって、開発者ツールでuseを選択すると、要素の親に適用されているスタイルのみが表示されます。要素自体が継承されたプロパティをオーバーライドする可能性があり、開発パネルでそれを観察する方法はありません。

ここでは、たとえば、使用に適用されるスタイルは親から継承されます。開発者ツールでは、勝者のルールが紫色であるように見えますが、これは、プルされる要素が考慮されていないためです。これはsoft要素が任意の値を指定する場合にオーバーライドできる値。

use

しかし、インライン化されたテキストのセレクターの完全なセットは、実際には次のようになります。

text

特定の状況

将来的に私が提案することの1つは実行可能なコードを提供するです。これにより、デバッグ時間を大幅に節約できるため、問題を簡単に再現できます。しかし、これが私があなたの正確な状況で起こっていると思うものです:

svg {
  fill: #002649;
}
a:hover svg {
  fill: #8A8B8C;
}
.skip-link .icon {
  fill: #FFF;
}
<a href="#" class="skip-link">
  <svg xmlns="http://www.w3.org/2000/svg"
       xmlns:xlink="http://www.w3.org/1999/xlink"
       class="icon" >

    <def>
      <svg xmlns="http://www.w3.org/2000/svg" id="menu-bag">
        <rect height="100" width="100" />
      </svg>
    </def>

    <use xlink:href="#menu-bag" />

  </svg>
</a>
2
KyleMit

本文またはhtmlタグにデフォルトのsvg塗りつぶし色を設定すると、デフォルトとして継承されますが、クラスだけを使用して簡単にオーバーライドできます。

body {
    fill: black;
}
.green {
    fill: green;
}
.red {
    fill: red;
}

ここで、色クラスをどこでも使用して、塗りつぶしの色を変更します。 colorクラスをsvg、またはsvgをラップするスパンまたはその他の要素に追加します。 Firefoxでも動作します。

<a href="#" class="skip-link green">
    <svg>
        <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#menu-bag" />
    </svg>
</a>
<svg height="0" width="0">
    <symbol id="menu-bag" viewBox="-10 -10 20 20">
        <circle r="10" />
    </symbol>
</svg>
1
user3735371

私の場合はまったく同じではありませんが、とにかく私はそれを共有します。以下の例のように、背景画像としてsvgを使用しています(ググってみてください。そしてFirefoxでは「塗りつぶし」の色に問題がありました。

  • 塗りつぶしの値として、RGBモードで記述し、適切に機能させる必要がありました(fill:rgb(237、237、237);)。
  • HEX(fill:#ededed;)で書き込んだ場合、レンダリングされません。
  • たとえば「fill:blue;」と書いた場合それも適切に表示されます。

    .a-class {
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 10' preserveAspectRatio='none' height='130' style='background:var(--main-lt-green); fill:rgb(237, 237, 237);'><polygon points='100 0 100 10 0 10'></polygon></svg>");
    background-repeat: no-repeat;
    background-size: 100% 100px;
    background-position-y: top;
    margin-top: -100px;
    padding-top: 100px;
    

    }