3

Basically what Is happening is the linearGradient fill is hidden if the svg is hidden in a parallell element

.mobile {
  display: none;
}

.content-svg {
  border: 1px solid black;
}
<div class="desktop">
  <!-- stuff here -->
</div>

<div class="mobile">
  <svg class="mobile-svg" height="150" width="400">
  <defs>
    <linearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="0%">
      <stop offset="0%" style="stop-color:rgb(255,255,0);stop-opacity:1" />
      <stop offset="100%" style="stop-color:rgb(255,0,0);stop-opacity:1" />
    </linearGradient>
  </defs>
  <ellipse cx="200" cy="70" rx="85" ry="55" fill="url(#grad1)" />
  Sorry, your browser does not support inline SVG.
  </svg>
</div>

<div class="content">
  <svg class="content-svg" height="150" width="400">
  <defs>
    <linearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="0%">
      <stop offset="0%" style="stop-color:rgb(255,255,0);stop-opacity:1" />
      <stop offset="100%" style="stop-color:rgb(255,0,0);stop-opacity:1" />
    </linearGradient>
  </defs>
  <ellipse cx="200" cy="70" rx="85" ry="55" fill="url(#grad1)" />
  Sorry, your browser does not support inline SVG.
  </svg>
</div>

as you can see in the snippet above, the SVG element is there, the linearGradient fill is hidden

If I change the fill to a solid colour set in my CSS it works as expected, this only seems to happen with gradient fills

now this is just a basic example of my overall issue, I want to avoid recreating the SVG since I am using this in Vue and have created a reusable svg component

Smokey Dawson
  • 8,827
  • 19
  • 77
  • 152
  • 2
    don't use the same ID for two different gradient, actually only the first one is considered and it has display:none – Temani Afif Oct 15 '19 at 00:03
  • @TemaniAfif as I said this svg is reused through my application multiple times, changing the ID to a class doesnt seem to fix the issue either – Smokey Dawson Oct 15 '19 at 00:04
  • not a class, another ID ... check this: https://jsfiddle.net/gvda0myo/ .. changing the order fix the issue becasue the one considered is the first one without display:none. You are *obliged* to use different ID or keep only one gradient that you put inside a visible SVG – Temani Afif Oct 15 '19 at 00:04
  • @TemaniAfif that doesnt make the svg very usable does it.. and I cant re-order the mobile section and the content section – Smokey Dawson Oct 15 '19 at 00:05
  • in this case, define the gradient inside another SVG where you will only have the defs and make that svg with 0 height and width (no display:none) .. the used gradient must be inside an SVG without display:none – Temani Afif Oct 15 '19 at 00:06
  • @TemaniAfif like a global svg with just the gradient? – Smokey Dawson Oct 15 '19 at 00:07
  • yes exacrtly and having a size equal to 0 it won't affect the layout – Temani Afif Oct 15 '19 at 00:07
  • @TemaniAfif thanks that worked really well, if you post an answer I will mark it as correct – Smokey Dawson Oct 15 '19 at 00:10
  • Yeah, unfortunately, a lot of resources say unique ID's is the way to go. However, a more global solution is touched on here: https://stackoverflow.com/questions/16123721/how-to-use-local-defs-in-svg – EGC Oct 15 '19 at 00:10

1 Answers1

4

Either consider a different ID for the gradients:

.mobile {
  display: none;
}

.content-svg {
  border: 1px solid black;
}
<div class="desktop">
  <!-- stuff here -->
</div>

<div class="mobile">
  <svg class="mobile-svg" height="150" width="400">
  <defs>
    <linearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="0%">
      <stop offset="0%" style="stop-color:rgb(255,255,0);stop-opacity:1" />
      <stop offset="100%" style="stop-color:rgb(255,0,0);stop-opacity:1" />
    </linearGradient>
  </defs>
  <ellipse cx="200" cy="70" rx="85" ry="55" fill="url(#grad1)" />
  Sorry, your browser does not support inline SVG.
  </svg>
</div>

<div class="content">
  <svg class="content-svg" height="150" width="400">
  <defs>
    <linearGradient id="grad2" x1="0%" y1="0%" x2="100%" y2="0%">
      <stop offset="0%" style="stop-color:rgb(255,255,0);stop-opacity:1" />
      <stop offset="100%" style="stop-color:rgb(255,0,0);stop-opacity:1" />
    </linearGradient>
  </defs>
  <ellipse cx="200" cy="70" rx="85" ry="55" fill="url(#grad2)" />
  Sorry, your browser does not support inline SVG.
  </svg>
</div>

Or consider only one gradient if it's the same used in both SVG (related: Gradients hidden using SVG symbols)

.mobile {
  display: none;
}

.content-svg {
  border: 1px solid black;
}
<div class="desktop">
  <!-- stuff here -->
</div>

  <svg  height="0" width="0">
  <defs>
    <linearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="0%">
      <stop offset="0%" style="stop-color:rgb(255,255,0);stop-opacity:1" />
      <stop offset="100%" style="stop-color:rgb(255,0,0);stop-opacity:1" />
    </linearGradient>
  </defs>
  </svg>
<div class="mobile">
  <svg class="mobile-svg" height="150" width="400">
  <ellipse cx="200" cy="70" rx="85" ry="55" fill="url(#grad1)" />
  Sorry, your browser does not support inline SVG.
  </svg>
</div>

<div class="content">
  <svg class="content-svg" height="150" width="400">
  <ellipse cx="200" cy="70" rx="85" ry="55" fill="url(#grad1)" />
  Sorry, your browser does not support inline SVG.
  </svg>
</div>

Repeating the same ID is invalid and only the first one will be considered for both gradients and since the first one has display:none it will not render.

Changing the order will make your code work because the first one will no more have display:none

.mobile {
  display: none;
}

.content-svg {
  border: 1px solid black;
}
<div class="desktop">
  <!-- stuff here -->
</div>
<div class="content">
  <svg class="content-svg" height="150" width="400">
  <defs>
    <linearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="0%">
      <stop offset="0%" style="stop-color:rgb(255,255,0);stop-opacity:1" />
      <stop offset="100%" style="stop-color:rgb(255,0,0);stop-opacity:1" />
    </linearGradient>
  </defs>
  <ellipse cx="200" cy="70" rx="85" ry="55" fill="url(#grad1)" />
  Sorry, your browser does not support inline SVG.
  </svg>
</div>
<div class="mobile">
  <svg class="mobile-svg" height="150" width="400">
  <defs>
    <linearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="0%">
      <stop offset="0%" style="stop-color:rgb(255,255,0);stop-opacity:1" />
      <stop offset="100%" style="stop-color:rgb(255,0,0);stop-opacity:1" />
    </linearGradient>
  </defs>
  <ellipse cx="200" cy="70" rx="85" ry="55" fill="url(#grad1)" />
  Sorry, your browser does not support inline SVG.
  </svg>
</div>
Temani Afif
  • 245,468
  • 26
  • 309
  • 415