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
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>
Related
In an SVG, can you reuse a common linearGradient but change the colors from CSS?
I have the following HTML:
<svg viewBox="0 0 240 240" xmlns="http://www.w3.org/2000/svg" width="240" height="240">
<defs>
<linearGradient id="sharedGradient" class="grad" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="var(--color-top)" />
<stop offset="100%" stop-color="var(--color-bot)" />
</linearGradient>
</defs>
<g transform="translate(0, 0)">
<rect class="node" width="100" height="100" x="0" y="0"></rect>
</g>
<g transform="translate(120, 0)">
<rect class="node green" width="100" height="100" x="0" y="0"></rect>
</g>
</svg>
...and the following CSS:
.node {
fill: url(#sharedGradient) #00FF00;
}
#sharedGradient {
--color-top: #f12c06;
--color-bot: #faed34;
}
.green #sharedGradient {
--color-top: #00ff00;
--color-bot: #00dd00;
}
But I can't find a way to alter the color stops of the gradient without duplicating the whole tag in the SVG.
Like #Kaiido mentioned, the linearGradient just needs to be in the svg part that is being reused via <use href="..." />, then in Firefox that can be styled with css-variables. In chrome only the default values will be shown.
#svg1 {
stroke: url(#gradient);
}
#svg2 {
stroke: url(#gradient);
--color-top: blue;
--color-bot: red;
}
#svg3 {
stroke: url(#cantBeStyled); // but reused
--color-top: violet;
--color-bot: indigo;
}
<html>
<div>
<svg id="svg1">
<defs>
<linearGradient id="cantBeStyled" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="var(--color-top, green)" />
<stop offset="100%" stop-color="var(--color-bot, yellow)" />
</linearGradient>
</defs>
<g id="toReuse">
<linearGradient id="gradient" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="var(--color-top, green)" />
<stop offset="100%" stop-color="var(--color-bot, yellow)" />
</linearGradient>
<rect width="100" height="100" x="0" y="0" stroke-width="20"></rect>
</g>
</svg>
</div>
<div>CSS-variables work in Firefox, in chrome all gradients are green-yellow as defined as defaults in the svg</div>
<div>
can be styled via css variables
<svg id="svg2">
<use href="#toReuse"></use>
</svg>
</div><br /><br/><br/>
<div>
can't be styled
<svg id="svg3">
<use href="#toReuse"></use>
</svg>
</div>
</html>
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
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>
I am trying to make an svg with 4 ellipses inside, which overlap. It works fine but it doesn't seem to respond well when the size of the screen becomes to small. What should I do to make it responsive?
This is my current snippet for the svg elements:
<div class="row">
<div class="col-md-12">
<svg height="220" width="100%">
<defs>
<radialGradient id="grad1" cx="50%" cy="50%" r="50%" fx="50%" fy="50%">
<stop offset="0%" style="stop-color:rgb(255,255,255);
stop-opacity:0" />
<stop offset="100%" style="stop-color:rgb(0,0,255);stop-opacity:1" />
</radialGradient>
</defs>
<ellipse cx="125" cy="110" rx="95" ry="85" fill="url(#grad1)" />
<defs>
<radialGradient id="grad1" cx="50%" cy="50%" r="50%" fx="50%" fy="50%">
<stop offset="0%" style="stop-color:rgb(255,255,255);
stop-opacity:0" />
<stop offset="100%" style="stop-color:rgb(0,0,255);stop-opacity:1" />
</radialGradient>
</defs>
<ellipse cx="300" cy="110" rx="95" ry="85" fill="url(#grad1)" />
<defs>
<radialGradient id="grad1" cx="50%" cy="50%" r="50%" fx="50%" fy="50%">
<stop offset="0%" style="stop-color:rgb(255,255,255);
stop-opacity:0" />
<stop offset="100%" style="stop-color:rgb(0,0,255);stop-opacity:1" />
</radialGradient>
</defs>
<ellipse cx="475" cy="110" rx="95" ry="85" fill="url(#grad1)" />
<defs>
<radialGradient id="grad1" cx="50%" cy="50%" r="50%" fx="50%" fy="50%">
<stop offset="0%" style="stop-color:rgb(255,255,255);
stop-opacity:0" />
<stop offset="100%" style="stop-color:rgb(0,0,255);stop-opacity:1" />
</radialGradient>
</defs>
<ellipse cx="650" cy="110" rx="95" ry="85" fill="url(#grad1)" />
</div>
</div>
This is how it looks on normal monitor
and this on mobile screen:
If you want the SVG to scale to the size of its parent container, then you need to tell the browser how big the SVG contents are, so it knows how much it needs to scale the SVG to fit the space available.
The way you do that is with the viewBox attribute. The viewBox value consists of four numbers:
<left X> <top Y> <width> <height>
Your four ellipses occupy the area from 30,25 (top left of first ellipse) to 745,195 (bottom right of last ellipse). So you should set the viewBox to:
viewBox="30 25 715 170"
When you do that, the SVG will scale.
<div class="row">
<div class="col-md-12">
<svg height="220" width="100%" viewBox="30 25 715 170">
<defs>
<radialGradient id="grad1" cx="50%" cy="50%" r="50%" fx="50%" fy="50%">
<stop offset="0%" style="stop-color:rgb(255,255,255);
stop-opacity:0" />
<stop offset="100%" style="stop-color:rgb(0,0,255);stop-opacity:1" />
</radialGradient>
</defs>
<ellipse cx="125" cy="110" rx="95" ry="85" fill="url(#grad1)" />
<defs>
<radialGradient id="grad1" cx="50%" cy="50%" r="50%" fx="50%" fy="50%">
<stop offset="0%" style="stop-color:rgb(255,255,255);
stop-opacity:0" />
<stop offset="100%" style="stop-color:rgb(0,0,255);stop-opacity:1" />
</radialGradient>
</defs>
<ellipse cx="300" cy="110" rx="95" ry="85" fill="url(#grad1)" />
<defs>
<radialGradient id="grad1" cx="50%" cy="50%" r="50%" fx="50%" fy="50%">
<stop offset="0%" style="stop-color:rgb(255,255,255);
stop-opacity:0" />
<stop offset="100%" style="stop-color:rgb(0,0,255);stop-opacity:1" />
</radialGradient>
</defs>
<ellipse cx="475" cy="110" rx="95" ry="85" fill="url(#grad1)" />
<defs>
<radialGradient id="grad1" cx="50%" cy="50%" r="50%" fx="50%" fy="50%">
<stop offset="0%" style="stop-color:rgb(255,255,255);
stop-opacity:0" />
<stop offset="100%" style="stop-color:rgb(0,0,255);stop-opacity:1" />
</radialGradient>
</defs>
<ellipse cx="650" cy="110" rx="95" ry="85" fill="url(#grad1)" />
</svg>
</div>
</div>
What is the correct way to fill an SVG rectangle with jet colour scheme? Using multiple stops in linearGradient does not seem to work.
Edit, I am trying to fill the a rectangle with one of the following colour gradient.
I edited the MDN code with a rainbow example
<!-- Learn about this code on MDN: https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Gradients -->
<svg width="120" height="240" version="1.1" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="Gradient2" x1="0" x2="0" y1="0" y2="1">
<stop offset="0%" stop-color="#d30000"/>
<stop offset="30%" stop-color="#ffff05"/>
<stop offset="50%" stop-color="#05ff05"/>
<stop offset="70%" stop-color="#05ffff"/>
<stop offset="100%" stop-color="#041ae0"/>
</linearGradient>
</defs>
<rect x="10" y="10" rx="15" ry="15" width="100" height="100" fill="url(#Gradient2)"/>
</svg>
in a fiddle: https://jsfiddle.net/9bmvr5hd/
The BbwrR gradient is the example used in Mozilla's SVG - Gradients documentation:
<svg width="120" height="240" version="1.1" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="Gradient1">
<stop class="stop1" offset="25%"/>
<stop class="stop2" offset="50%"/>
<stop class="stop3" offset="75%"/>
</linearGradient>
<linearGradient id="Gradient2" x1="0" x2="0" y1="0" y2="1">
<stop offset="25%" stop-color="blue"/>
<stop offset="50%" stop-color="black" stop-opacity="0"/>
<stop offset="75%" stop-color="red"/>
</linearGradient>
<style type="text/css"><![CDATA[
#rect1 { fill: url(#Gradient1); }
.stop1 { stop-color: blue; }
.stop2 { stop-color: black; stop-opacity: 0; }
.stop3 { stop-color: red; }
]]></style>
</defs>
<rect id="rect1" x="10" y="10" rx="15" ry="15" width="100" height="100"/>
<rect x="10" y="120" rx="15" ry="15" width="100" height="100" fill="url(#Gradient2)"/>
</svg>
I swapped the location of the red and blue and adjusted the offset percentages to try to make it look more like your image. You should be able to just change the colors and add/remove stops for the others.
I'm trying to apply a CSS Mask to fade a DIV horizontally in both direction.
I created the mask with an online editor and it works smoothly using -webkit-mask and base64 encoding:
#slicenter{-webkit-mask: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA+gAAAAUCAYAAAAeGxcbAAACWUlEQVR4Xu3bQU4DMQwFUHoH4P7ng94BGkSlyKQjRv6bqG8kVKVgd/rqjflwefl7vZWnxvly+/r6fXwt59XP31u8T3WjfnWeX672Olu/eDueIkCAAAECBAgQIECAAIEnEvgse+i1nMf352t1vu+/4/GovtZ+lH15dX742mPxrtfZpfhoqT6zzI/76Pwy4InmzVslQIAAAQIECBAgQIAAgQcC0aX59hpHS3dy2f9JxuslQTfnBAgQIECAAAECBAgQILCrgAR9+uTmBF6CvutIu28CBAgQIECAAAECBAjsKSBBnz63OYFP/rn8f/6Hfc/xcdcECBAgQIAAAQIECBAgkBKQoEvQU7OkDwECBAgQIECAAAECBAg0BCToEvTG+CglQIAAAQIECBAgQIAAgZSABF2CnpolfQgQIECAAAECBAgQIECgISBBl6A3xkcpAQIECBAgQIAAAQIECKQEJOgS9NQs6UOAAAECBAgQIECAAAECDQEJugS9MT5KCRAgQIAAAQIECBAgQCAlIEGXoKdmSR8CBAgQIECAAAECBAgQaAhI0CXojfFRSoAAAQIECBAgQIAAAQIpAQm6BD01S/oQIECAAAECBAgQIECAQENAgi5Bb4yPUgIECBAgQIAAAQIECBBICUjQJeipWdKHAAECBAgQIECAAAECBBoCEnQJemN8lBIgQIAAAQIECBAgQIBASkCCLkFPzZI+BAgQIECAAAECBAgQINAQkKBL0Bvjo5QAAQIECBAgQIAAAQIEUgISdAl6apb0IUCAAAECBAgQIECAAIGGwLYJ+jfSylgzQ2my8wAAAABJRU5ErkJggg==);}
The problem is: this works just on Chrome (and maybe Safari).
So I tried to export the same image to HTML/SVG. This is what I got:
<svg xmlns="http://www.w3.org/2000/svg" width="200px" height="200px" >
<defs>
<linearGradient id="lgrad" x1="0%" y1="50%" x2="100%" y2="50%" >
<stop offset="0%" style="stop-color:rgb(0,0,0);stop-opacity:0" />
<stop offset="5%" style="stop-color:rgb(0,0,0);stop-opacity:1" />
<stop offset="95%" style="stop-color:rgb(0,0,0);stop-opacity:1" />
<stop offset="100%" style="stop-color:rgb(0,0,0);stop-opacity:0" />
</linearGradient>
</defs>
<rect x="0" y="0" width="100%" height="100%" fill="url(#lgrad)"/>
</svg>
And then I tried to convert this vector in a mask (but it's probably wrong):
<svg height="0" >
<defs>
<linearGradient id="g" gradientUnits="objectBoundingBox" x1="0%" y1="50%" x2="100%" y2="50%" >
<stop offset="0%" style="stop-color:rgb(0,0,0);stop-opacity:0" />
<stop offset="5%" style="stop-color:rgb(0,0,0);stop-opacity:1" />
<stop offset="95%" style="stop-color:rgb(0,0,0);stop-opacity:1" />
<stop offset="100%" style="stop-color:rgb(0,0,0);stop-opacity:0" />
</linearGradient>
<mask id="lgrad" maskUnits="objectBoundingBox" maskContentUnits="objectBoundingBox">
<rect x="0" y="0" width="100%" height="100%" fill="url(#g)"/>
</mask>
</defs>
</svg>
I applied the mask to the same element with:
#slicenter{mask: url(#lgrad);}
But it doesn't works. Any Ideas?
Cheers