0

My SVG gradient works as isolated HTML, but doesn't work when embeded into CSS background attribute.

I want to embed SVG into my CSS so I can have some complicated backgrounds. I started with a basic green background and it works great. Code below (ignore the gradient code, its important later). So this:

<style type="text/css">

   #example { 
      background: url('data:image/svg+xml,\
         <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">\
           <defs>\
             <linearGradient id="gradient" x1="0" y1="1" x2="1" y2="1">\
               <stop offset="0%" stop-color="red" stop-opacity="100" />\
               <stop offset="100%" stop-color="black" stop-opacity="100" />\
             </linearGradient>\
           </defs>\
           <rect id="rect1" x="0" y="0" width="100%" height="100%" fill="green" />\
         </svg>\
      ') 0 / auto 100%;
      border: 1px solid red;
      height: 100px;
      width: 110px;
   }

</style>


<div id='example'>
I'm green
</div>

Yields this:

enter image description here

However, when I try to only change the fill to use the gradient, then this:

   <style type="text/css">

      #example { 
         background: url('data:image/svg+xml,\
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">\
              <defs>\
                <linearGradient id="gradient" x1="0" y1="1" x2="1" y2="1">\
                  <stop offset="0%" stop-color="red" stop-opacity="100" />\
                  <stop offset="100%" stop-color="black" stop-opacity="100" />\
                </linearGradient>\
              </defs>\
              <rect id="rect1" x="0" y="0" width="100%" height="100%" fill="url(#gradient)" />\
            </svg>\
         ') 0 / auto 100%;
         border: 1px solid red;
         height: 100px;
         width: 110px;
      }

   </style>


   <div id='example'>
   Why am I white??
   </div>

Yields this:

enter image description here

My initial assumption was that I must be messing something up in the linearGradient, so I figured I'd isolate the SVG section out and work on that. So all I'm doing here is cutting the SVG section out and running it as HTML. Now this original solid green SVG:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
  <defs>
    <linearGradient id="gradient" x1="0" y1="1" x2="1" y2="1">
      <stop offset="0%" stop-color="red" stop-opacity="100" />
      <stop offset="100%" stop-color="black" stop-opacity="100" />
    </linearGradient>
  </defs>
  <rect id="rect1" x="0" y="0" width="100%" height="100%" fill="green" />
</svg>

Yields this solid green page:

enter image description here

And the same exact code again but filling it with the gradient:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
  <defs>
    <linearGradient id="gradient" x1="0" y1="1" x2="1" y2="1">
      <stop offset="0%" stop-color="red" stop-opacity="100" />
      <stop offset="100%" stop-color="black" stop-opacity="100" />
    </linearGradient>
  </defs>
  <rect id="rect1" x="0" y="0" width="100%" height="100%" fill="url(#gradient)" />
</svg>

Yeilds a page full of this:

enter image description here

It's so specific of a problem I've been having difficulty googling what's going on. Am I not understanding this correctly, or is there maybe some limitations with embedding SVG images into CSS?

Kmus
  • 11
  • 4

1 Answers1

0

Okay, I figured it out. And I figured out a way to troubleshoot the issue more easily.

Troubleshooting

I cut out the data from the url(), and put it all on one line, like this:

data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs><linearGradient id="gradient" x1="0" y1="1" x2="1" y2="1"><stop offset="0%" stop-color="red" stop-opacity="100" /><stop offset="100%" stop-color="black" stop-opacity="100" /></linearGradient></defs><rect id="rect1" x="0" y="0" width="100%" height="100%" fill="url(#gradient)" /></svg>

Then pasting that into the address bar in Chrome renders useful error messages.

Solution

Turns out the issue was that I wasn't URL encoding the string. Specifically # needed to be replaced with %23. I did that swap and now this:

   <style type="text/css">

      #example { 
         background: url('data:image/svg+xml,\
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">\
              <defs>\
                <linearGradient id="gradient" x1="0" y1="1" x2="1" y2="1">\
                  <stop offset="0%" stop-color="red" stop-opacity="100" />\
                  <stop offset="100%" stop-color="black" stop-opacity="100" />\
                </linearGradient>\
              </defs>\
              <rect id="rect1" x="0" y="0" width="100%" height="100%" fill="url(%23gradient)" />\
            </svg>\
         ') 0 / auto 100%;
         border: 1px solid red;
         height: 100px;
         width: 110px;
      }

   </style>


   <div id='example'>
   I'm not white
   </div>

Now yields this:

enter image description here

Kmus
  • 11
  • 4