How to add a linearGradient to a vertical SVG line [duplicate] - html

This question already has answers here:
SVG gradient for perfectly horizontal path
(2 answers)
Closed 3 years ago.
I'm trying to add a gradient to the stroke of a line which fades out at the top but having no luck. Actually I kind of got it working like this, but it has browser issues even in Chrome certain SVG sizes where the gradient just breaks and is solid:
<linearGradient
id='whiteFadeGrad'
x1={svgHeight}
y1='0'
x2='0'
y2={svgHeight}
gradient-units='userSpaceOnUse'
>
<stop offset='0' stop-color='rgba(255,255,255,0)' />
<stop offset='1' stop-color='rgba(255,255,255,0.2)' />
</linearGradient>
I would much rather stick to using percentage units, but can't get it to work:
<p>The solid green one works, but you can't see the other when I apply the gradient to it. I've tried a lot of different x1/x2/y1/y2 values as well as gradientTransform(rotate(d)).</p>
<svg height="200" width="500">
<defs>
<linearGradient id='fadeGrad' x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset='0%' stop-color='red' />
<stop offset='100%' stop-color='blue' />
</linearGradient>
</defs>
<line x1="100" y1="0" x2="100" y2="200" style="stroke: green; stroke-width:4px; shape-rendering: crispEdges;" />
<line x1="120" y1="0" x2="120" y2="200" style="stroke: url('#fadeGrad'); stroke-width:4px; shape-rendering: crispEdges;" />
</svg>
Thanks

It looks like a bug and a hack, but worked:
<svg height="200" width="500">
<defs>
<linearGradient id='fadeGrad' x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset='0%' stop-color='red' />
<stop offset='100%' stop-color='blue' />
</linearGradient>
</defs>
<line x1="100" y1="0" x2="100" y2="200" style="stroke: green; stroke-width:4px; shape-rendering: crispEdges;" />
<line x1="120" y1="0" x2="120.001" y2="200" style="stroke: url('#fadeGrad'); stroke-width:4px; shape-rendering: crispEdges;" />
</svg>
You might probably use <rect> instead of <line>, which is not so hacky:
<svg height="200" width="500">
<defs>
<linearGradient id='fadeGrad' x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset='0%' stop-color='red' />
<stop offset='100%' stop-color='blue' />
</linearGradient>
</defs>
<line x1="100" y1="0" x2="100" y2="200" style="stroke: green; stroke-width:4px; shape-rendering: crispEdges;" />
<rect x="120" y="0" width="4" height="200" style="fill: url('#fadeGrad'); shape-rendering: crispEdges;" />
</svg>

Check this, I dont know much about SVG, but a simple googling does the job for me.
Could you please go through the code.
<p>The solid green one works, but you can't see the other when I apply the gradient to it. I've tried a lot of different x1/x2/y1/y2 values as well as gradientTransform(rotate(d)).</p>
<svg height="200" width="500">
<defs>
<linearGradient id="e" x1="40" y1="210" x2="400" y2="210" gradientUnits="userSpaceOnUse" gradientTransform="rotate(90)">
<stop stop-color="steelblue" offset="0" />
<stop stop-color="red" offset="1" />
</linearGradient>
</defs>
<line x1="100" y1="0" x2="100" y2="200" style="stroke: green; stroke-width:10px; shape-rendering: crispEdges;" />
<line x1="120" y1="0" x2="120" y2="200" style="stroke: url('#e'); stroke-width:4px; shape-rendering: crispEdges;" />
</svg>

Related

In an SVG, can you reuse a common linearGradient but change the colors from CSS?

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>

SVG Linear gradient, UserSpaceOnUse

I am trying to get a linear gradient to work with gradientUnits='userSpaceOnUse' but for some reason the gradient is not applied.Take a look at the following code.
<svg width="500" height="500" viewBox="0 0 500 500" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<linearGradient id="user-grad" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse">
<stop stop-color="orange" offset="0"></stop>
<stop stop-color="blue" offset="1"></stop>
</linearGradient>
<linearGradient id="object-grad" x1="0" y1="0" x2="1" y2="0">
<stop stop-color="orange" offset="0"></stop>
<stop stop-color="blue" offset="1"></stop>
</linearGradient>
</defs>
<rect x="0" y="0" width="200" height="100" fill="url(#user-grad)"/>
<rect x="250" y="0" width="200" height="100" fill="url(#object-grad)"/>
</svg>
The first rect has the gradientUnits attribute applied and the second one does not. The gradient works well the second one but not the first one. How do I get the first one to look like the second one

How do I fill several svg path by one gradient?

There is an example with group of two paths, group filled by gradient.
<svg height="1000" width="1400">
<defs>
<linearGradient id="lingrad" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stop-color="red" />
<stop offset="100%" stop-color="green" />
</linearGradient>
</defs>
<g fill="url(#lingrad)">
<path d="M501.333,490.667H10.667C4.779,490.667,0,495.445,0,501.333C0,507.221,4.779,512,10.667,512h490.667
c5.888,0,10.667-4.779,10.667-10.667C512,495.445,507.221,490.667,501.333,490.667z"/>
<path d="M96,362.667H32c-5.888,0-10.667,4.779-10.667,10.667v128C21.333,507.221,26.112,512,32,512h64
c5.888,0,10.667-4.779,10.667-10.667v-128C106.667,367.445,101.888,362.667,96,362.667z M85.333,490.667H42.667V384h42.667
V490.667z"/>
</g>
</svg>
But each path is filled by its own gradient.
How do I fill all paths by one shared gradient?
By just creating one path.
Just add the d tag of one path to the d tag of the other path:
<path d="M501.333,490.667H10.667C4.779,490.667,0,495.445,0,501.333C0,507.221,4.779,512,10.667,512h490.667
c5.888,0,10.667-4.779,10.667-10.667C512,495.445,507.221,490.667,501.333,490.667z"/>
<path d="M96,362.667H32c-5.888,0-10.667,4.779-10.667,10.667v128C21.333,507.221,26.112,512,32,512h64
c5.888,0,10.667-4.779,10.667-10.667v-128C106.667,367.445,101.888,362.667,96,362.667z M85.333,490.667H42.667V384h42.667
V490.667z"/>
<svg height="1000" width="1400">
<defs>
<linearGradient id="lingrad" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stop-color="red" />
<stop offset="100%" stop-color="green" />
</linearGradient>
</defs>
<g fill="url(#lingrad)">
<path d="M501.333,490.667H10.667C4.779,490.667,0,495.445,0,501.333C0,507.221,4.779,512,10.667,512h490.667
c5.888,0,10.667-4.779,10.667-10.667C512,495.445,507.221,490.667,501.333,490.667zM96,362.667H32c-5.888,0-10.667,4.779-10.667,10.667v128C21.333,507.221,26.112,512,32,512h64
c5.888,0,10.667-4.779,10.667-10.667v-128C106.667,367.445,101.888,362.667,96,362.667z M85.333,490.667H42.667V384h42.667
V490.667z"/>
</g>
</svg>
Define the gradient dimensions not relative to the object bounding box (of the individual shapes, gradientUnits="objectBoundingBox" is the default), but relative to the local coordinate system of the <g> element (gradientUnits="userSpaceOnUse").
<svg height="1000" width="1400">
<defs>
<linearGradient id="lingrad" x1="0" y1="0" x2="512" y2="0" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="red" />
<stop offset="100%" stop-color="green" />
</linearGradient>
</defs>
<g fill="url(#lingrad)">
<path d="M501.333,490.667H10.667C4.779,490.667,0,495.445,0,501.333C0,507.221,4.779,512,10.667,512h490.667
c5.888,0,10.667-4.779,10.667-10.667C512,495.445,507.221,490.667,501.333,490.667z"/>
<path d="M96,362.667H32c-5.888,0-10.667,4.779-10.667,10.667v128C21.333,507.221,26.112,512,32,512h64
c5.888,0,10.667-4.779,10.667-10.667v-128C106.667,367.445,101.888,362.667,96,362.667z M85.333,490.667H42.667V384h42.667
V490.667z"/>
</g>
</svg>

SVG - Filling Rectangle with Jet Colour Scheme

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.

Apply an opacity mask with CSS3

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