title: How can I refer to an internal gradient definition inside an SVG sprite symbol?
body: <p><i><b>SUMMARY:</b> An SVG sprite contains five icon <code>&lt;symbol&gt;</code> blocks, one of which references its own gradient definition by ID. It is no longer able to find this gradient and render properly.</i></p>
  
  <p><strong>JSFIDDLE:</strong> <a href="http://jsfiddle.net/Qtq24/1/" rel="noreferrer">http://jsfiddle.net/Qtq24/1/</a></p>
  
  <hr>
  
  <p>I am switching some graphics to SVG, and being that they are icons (in this case for social networking profiles) I'd like to keep them in a sprite (as I had with PNG before).</p>
  
  <p>I've followed <a href="http://css-tricks.com/svg-sprites-use-better-icon-fonts/" rel="noreferrer">this guide to SVG sprites on CSS-tricks.com</a> (along with <a href="http://css-tricks.com/svg-symbol-good-choice-icons/" rel="noreferrer">this follow-up which advises using <code>&lt;symbol&gt;</code> instead of <code>&lt;g&gt;</code></a>).</p>
  
  <p>I now have an SVG sprite file, <strong>social-sprite.svg</strong>, which you can view in full <a href="http://advice.uk.match.com/sites/all/themes/matchtheme/images/social-sprite.svg" rel="noreferrer">here</a>.</p>
  
  <p>This is one complete <code>&lt;svg&gt;</code> block containing five different <code>&lt;symbol&gt;</code> blocks, each with an <code>id</code> and with a <code>viewBox</code> attribute. In each case I got the SVG code for each symbol by preparing official icons in Adobe Illustrator and retaining the relevant parts of the processed code.</p>
  
  <p>The .svg file is included via PHP as soon as the <code>&lt;body&gt;</code> tag opens (and this is why the main <code>&lt;svg&gt;</code> container inside it is marked with <code>style="display: none;"</code>) so that the references to each symbol work from the HTML.</p>
  
  <p>Four icons work perfectly, and the only one I am having trouble with is the YouTube icon, because it uses an internally-defined gradient. Here is the YouTube part of the SVG code:</p>
  
  <pre><code>&lt;symbol id="youtube" viewBox="0 0 400 281.641"&gt;
      &lt;path id="Triangle" fill="#FFFFFF" d="M159.845,191.73l106.152-54.999L159.845,81.348V191.73z"/&gt;
      &lt;path id="The_Sharpness" opacity="0.12" fill-rule="evenodd" clip-rule="evenodd" fill="#420000" d="M159.845,81.348l93.091,62.162
      l13.061-6.778L159.845,81.348z"/&gt;
      &lt;g id="Lozenge"&gt;
          &lt;g&gt;
              &lt;linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="200.4204" y1="2.6162" x2="200.4204" y2="278.9292"&gt;
                  &lt;stop  offset="0" style="stop-color:#E52D27"/&gt;
                  &lt;stop  offset="1" style="stop-color:#BF171D"/&gt;
              &lt;/linearGradient&gt;
              &lt;path fill="url(#SVGID_1_)" d="M392.928,62.226c0,0-3.839-27.073-15.617-38.995C362.371,7.583,345.626,7.506,337.947,6.59
              c-54.975-3.974-137.441-3.974-137.441-3.974h-0.171c0,0-82.464,0-137.44,3.974c-7.68,0.916-24.419,0.993-39.364,16.641
              C11.753,35.153,7.92,62.226,7.92,62.226s-3.929,31.792-3.929,63.583v29.805c0,31.791,3.929,63.582,3.929,63.582
              s3.833,27.073,15.611,38.995c14.945,15.646,34.575,15.152,43.318,16.792c31.43,3.015,133.571,3.946,133.571,3.946
              s82.552-0.124,137.526-4.099c7.679-0.915,24.424-0.993,39.363-16.64c11.778-11.922,15.617-38.995,15.617-38.995
              s3.923-31.791,3.923-63.582v-29.805C396.851,94.017,392.928,62.226,392.928,62.226z M159.863,191.73l-0.018-110.383
              l106.152,55.384L159.863,191.73z"/&gt;
          &lt;/g&gt;
      &lt;/g&gt;
  &lt;/symbol&gt;
  </code></pre>
  
  <p>And this is called in the HTML with:</p>
  
  <pre><code>&lt;svg width="30" height="21"&gt;
      &lt;use xlink:href="#youtube" src="fallback.png" width="30" height="21" /&gt;
  &lt;/svg&gt;
  </code></pre>
  
  <p>The opening two paths work fine, the problem is that in this new combined sprite SVG file, with each icon separated as a <code>&lt;symbol&gt;</code>, the <em>"Lozenge"</em> <code>&lt;path&gt;</code> is unable to find the <strong>#SVGID_1_</strong> reference to the <code>&lt;linearGradient&gt;</code>.</p>
  
  <p>In Firefox this causes the lozenge to display as white (I assume, perhaps it is not displaying at all - not really looked into it):</p>
  
  <p><img src="https://i.stack.imgur.com/EVZKI.png" alt="firefox fills as white"></p>
  
  <p>whilst Chrome renders it in black:</p>
  
  <p><img src="https://i.stack.imgur.com/v58n7.png" alt="chrome fills as black"></p>
  
  <p>Obviously neither is acceptable. The only thing I can do at the moment is remove <code>fill="url(#SVGID_1_)"</code> on the path and just fill with a flat colour red appropriate to the YouTube logo. This is not a proper solution though, even discounting the fact that bastardising the YouTube logo in this way would not be accepted under their brand guidelines.</p>
  
  <p>Things I've tried (and had no luck with):</p>
  
  <ul>
  <li>removing the two <code>&lt;g&gt;</code> wrappers that surround the gradient and the path, so the whole of the symbol is just <code>&lt;path&gt;-&lt;path&gt;-&lt;linearGradient&gt;-&lt;path&gt;</code></li>
  <li>wrapping the gradient definition inside a <code>&lt;defs&gt;</code> container</li>
  <li>wrapping it in a <code>&lt;defs&gt;</code> and also moving it to the top of the SVG file, i.e. outside the bounds of the YouTube-specific <code>&lt;symbol&gt;</code></li>
  <li>changing ID name (you never know!)</li>
  <li>redefining the gradient with percentages rather than pixel values</li>
  </ul>
  
  <p>So how do I get an already-internal <code>&lt;symbol&gt;</code> to reference an also-internal <code>&lt;linearGradient&gt;</code> definition?</p>
  
  <hr>
  
  <p><strong>EDIT:</strong> It turns out the gradient fails when the whole <code>&lt;svg&gt;</code> block is marked with <code>style="display: none;"</code>. If this style is removed, the gradient renders properly. But as a reminder, this styling is added so that when you import the SVG sprite it is not rendered instantly on the page, and just allows you to make references to the id-defined symbols as required.</p>
  
  <p><code>visibility: hidden</code> or <code>opacity: 0</code> both allow the gradient to render properly, obviously they don't offer proper solutions though as they still demarcate the space that the SVG would have taken up if visible.</p>
  
  <p>After discovering all this, I was pretty sure it would be no problem to have the fully visible <code>&lt;svg&gt;</code> with no stylings added <strong>INSIDE</strong> a container <code>&lt;div&gt;</code> which is hidden. However, even this causes the gradient not to render. I'm no closer to solving the issue. </p>